mirror of
https://github.com/PDP-10/stacken.git
synced 2026-03-04 10:24:35 +00:00
7112 lines
242 KiB
Plaintext
7112 lines
242 KiB
Plaintext
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
|
||
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
|
||
;
|
||
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1985,1986,1988.
|
||
;ALL RIGHTS RESERVED.
|
||
|
||
IFNDEF FTOPS20,<FTOPS20==0>
|
||
IFNDEF FTOPS10,<FTOPS10==1>
|
||
|
||
SALL
|
||
|
||
IFN FTOPS20,<
|
||
SEARCH MACSYM,MONSYM,PROLOG,TTYDEF
|
||
SEARCH NIPAR
|
||
|
||
TTITLE (LATSRV,,< -- LAT-20 Terminal Host>)
|
||
|
||
XRESCD ;[7.1024]
|
||
>
|
||
|
||
IFN FTOPS10,<
|
||
SEARCH F,S,D36PAR,MACSYM
|
||
SEARCH ETHPRM
|
||
|
||
.CPYRT<1985,1988>
|
||
TITLE LATSER -- LAT-10 Terminal Host
|
||
|
||
$RELOC
|
||
$HIGH ;SO BEGSTR DOESN'T OVERLAY LOW SEG WITH JUNK
|
||
|
||
XP VLATSER,4 ;PUT VERSION NUMBER IN STORAGE MAP AND GLOB
|
||
>
|
||
SUBTTL Table of Contents
|
||
|
||
|
||
; Table of Contents for LATSER
|
||
;
|
||
;
|
||
; Section Page
|
||
; 1. Definitions - Literals - Circuit Parameters. . . . . . 3
|
||
; 2. Definitions - Literals - Slot Parameters . . . . . . . 4
|
||
; 3. External References. . . . . . . . . . . . . . . . . . 5
|
||
; 4. Definitions - Data Structures. . . . . . . . . . . . . 7
|
||
; 5. CIRCUIT BLOCK data structure definitions . . . . . . . 8
|
||
; 6. SLOT BLOCK data struction definitions. . . . . . . . . 10
|
||
; 7. Miscellaneous Structure Definitions. . . . . . . . . . 11
|
||
; 8. Symbol Definitions
|
||
; 8.1. Macros MIN.,MAX.,MAXENT . . . . . . . . . . . 12
|
||
; 9. LATOP% JSYS
|
||
; 9.1. Definitions . . . . . . . . . . . . . . . . . 13
|
||
; 9.2. Entry point . . . . . . . . . . . . . . . . . 15
|
||
; 9.3. SET/CLEAR Functions . . . . . . . . . . . . . 16
|
||
; 9.4. SET/CLEAR SERVICE . . . . . . . . . . . . . . 17
|
||
; 9.5. SET LAT HOST NAME . . . . . . . . . . . . . . 19
|
||
; 9.6. SET/CLEAR HOST IDENTIFICATION STRING. . . . . 20
|
||
; 9.7. SET/CLEAR HOST GROUP CODES. . . . . . . . . . 21
|
||
; 9.8. SET MAXIMUM CIRCUITS. . . . . . . . . . . . . 22
|
||
; 9.9. SHOW CHARACTERISTIC HOST. . . . . . . . . . . 24
|
||
; 9.10. SHOW TERMINAL CONNECTS. . . . . . . . . . . . 26
|
||
; 9.11. SHOW SERVERS. . . . . . . . . . . . . . . . . 27
|
||
; 9.12. SHOW/ZERO COUNTERS. . . . . . . . . . . . . . 28
|
||
; 9.13. Utility Routines
|
||
; 9.13.1. FNDSRV . . . . . . . . . . . . . . . 29
|
||
; 9.13.2. GTSRVR . . . . . . . . . . . . . . . 30
|
||
; 9.13.3. SCMPAR String Compare. . . . . . . . 31
|
||
; 10. LATINI - LAT Initialization. . . . . . . . . . . . . . 33
|
||
; 11. Multicast Transmitter. . . . . . . . . . . . . . . . . 36
|
||
; 12. Routines to Build the Host Multicast Message
|
||
; 12.1. BMCFXD. . . . . . . . . . . . . . . . . . . . 37
|
||
; 12.2. BMCFXD. . . . . . . . . . . . . . . . . . . . 38
|
||
; 12.3. BMCNID. . . . . . . . . . . . . . . . . . . . 39
|
||
; 12.4. BMCSRV. . . . . . . . . . . . . . . . . . . . 40
|
||
; 12.5. BMCRAT. . . . . . . . . . . . . . . . . . . . 41
|
||
; 13. Multicast Transmit Check Routine . . . . . . . . . . . 42
|
||
; 14. Build the START Message Template . . . . . . . . . . . 43
|
||
; 15. LAINTR
|
||
; 15.1. LAT DLL Callback Routinea . . . . . . . . . . 44
|
||
; 15.2. Interrupt Level Virtual Circuit Message Receiver 45
|
||
; 16. LAINTX - Interrupt Level Virtual Circuit Message Receiver 46
|
||
; 17. LARSCH - Scheduler Level Virtual Circuit Message Receiver 47
|
||
; 18. LATLSC - Ethernet Link State Change Callback . . . . . 49
|
||
; 19. Message Receiver - HMSTRT. . . . . . . . . . . . . . . 50
|
||
; 20. HSTRCB . . . . . . . . . . . . . . . . . . . . . . . . 51
|
||
; 21. CBINIT - Circuit Block Initialization. . . . . . . . . 52
|
||
; 22. CMNIAD - Find CB base on NI address. . . . . . . . . . 53
|
||
; 23. HMRUN. . . . . . . . . . . . . . . . . . . . . . . . . 55
|
||
; 24. HSTRCB . . . . . . . . . . . . . . . . . . . . . . . . 56
|
||
; 25. HMSTOP . . . . . . . . . . . . . . . . . . . . . . . . 57
|
||
; 26. Message Transmit Routines. . . . . . . . . . . . . . . 59
|
||
; 27. Message Transmitter
|
||
; 27.1. XMTMSG. . . . . . . . . . . . . . . . . . . . 67
|
||
; 27.2. XMTDON. . . . . . . . . . . . . . . . . . . . 68
|
||
; 28. Receive Message Handling Routines. . . . . . . . . . . 69
|
||
; 29. Transmit Message Handling Routines . . . . . . . . . . 70
|
||
; 30. Slot Demultiplexor - LSDMUX. . . . . . . . . . . . . . 72
|
||
; 31. HSSTRT . . . . . . . . . . . . . . . . . . . . . . . . 73
|
||
; 32. Slot Processing Routines
|
||
; 32.1. STOP Slots. . . . . . . . . . . . . . . . . . 74
|
||
; 32.2. DATA_A,DATA_B Slots . . . . . . . . . . . . . 75
|
||
; 33. Slot Block Allocation and Deallocation Routines. . . . 77
|
||
; 34. Slot Multiplexor - Main Loop . . . . . . . . . . . . . 83
|
||
; 35. BLDMSL . . . . . . . . . . . . . . . . . . . . . . . . 85
|
||
; 36. Slot Formatting Routines
|
||
; 36.1. XSLSTA. . . . . . . . . . . . . . . . . . . . 87
|
||
; 36.2. XSLSTP. . . . . . . . . . . . . . . . . . . . 88
|
||
; 36.3. XSLDTA. . . . . . . . . . . . . . . . . . . . 89
|
||
; 36.4. XSLDTB. . . . . . . . . . . . . . . . . . . . 91
|
||
; 37. Queue Handling Routines. . . . . . . . . . . . . . . . 94
|
||
; 38. Buffer Handling Routines
|
||
; 38.1. Transmit Buffers. . . . . . . . . . . . . . . 96
|
||
; 38.2. Receive Buffers . . . . . . . . . . . . . . . 100
|
||
; 39. TTYSRV DEVICE DEPENDENT ROUTINES . . . . . . . . . . . 101
|
||
; 40. General Untility Routines. . . . . . . . . . . . . . . 102
|
||
|
||
SUBTTL TOPS20 definitions
|
||
|
||
IFN FTOPS20,<
|
||
|
||
;[7.1039] Add XBLT exec to user
|
||
;
|
||
DEFINE XBLTXU (AC<T1>),<XCT 1,[EXTEND AC,[XBLT]]>
|
||
|
||
;[7.1039] Add XBLT user to exec
|
||
;
|
||
DEFINE XBLTUX (AC<T1>),<XCT 2,[EXTEND AC,[XBLT]]>
|
||
|
||
> ;END IFN FTOPS20
|
||
SUBTTL Definitions -- TOPS-10 -- Redefinitions of TOPS-20 Things
|
||
|
||
|
||
IFN FTOPS10,<
|
||
|
||
OPDEF NOP[TRN]
|
||
DEFINE RESCD <$HIGH> ;Resident (nonpagged) code
|
||
DEFINE SWAPCD <$HIGH> ;Swappable code
|
||
DEFINE XRESCD <$XHIGH>;Resident (XRCOD PSECT)
|
||
DEFINE XSWAPCD <$XHIGH>;Swappable (XNCOD PSECT)
|
||
DEFINE RESDT <$LOW> ;
|
||
DEFINE NOSKD1 <> ;Don't have to worry
|
||
DEFINE OKSKD1 <> ; about these
|
||
DEFINE MCENT <> ; in TOPS-10
|
||
DEFINE UNSPI,<UNSID> ;Secondary portal ID
|
||
DEFINE UN.SPI,<UN.SID> ; (NIPAR/ETHPRM)
|
||
DEFINE BITS,<BITTBL##>
|
||
DEFINE MAXACB,<MAXCIR##>
|
||
DEFINE MAXACC,<MAXCIR##>
|
||
DEFINE TODCLK,<SYSUTM##>;[7.xxxx]System uptime in milliseconds
|
||
EXTERN RTRADR
|
||
EXTERN LAHNDB
|
||
EXTERN NTTLAH
|
||
EXTERN SBBWDS
|
||
EXTERN SBBITS
|
||
EXTERN LDLIDL
|
||
EXTERN RTN
|
||
|
||
; Redefine the D36PAR line states.
|
||
;
|
||
LS.OFF==0 ;Off
|
||
LS.ON==1 ;On
|
||
LS.SHT==2 ;Shutdown
|
||
|
||
; XCTU is used for "normal" instructions which move data from User to eXec
|
||
; and eXec to User
|
||
;
|
||
DEFINE XCTU <PXCT 4,> ;For all "normal" instructions
|
||
DEFINE XCTBU <PXCT 3,> ;To load from and deposit to user
|
||
;with byte pointer in eXec
|
||
SUBTTL Definitions -- TOPS-10 -- LATOP. UUO
|
||
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
; CALL: MOVEI AC,ADR
|
||
; LATOP. AC,
|
||
; <NON-SKIP>
|
||
; <SKIP>
|
||
|
||
;LATOP. Function Code Definitions
|
||
|
||
.LASET==0 ;Set
|
||
.LACLR==1 ;Clear
|
||
.LASCH==2 ;Show characteristics of host
|
||
.LASTC==3 ;Show terminal connects
|
||
.LASAS==4 ;Show adjacent servers
|
||
.LASCO==5 ;Show counters
|
||
.LAZCO==6 ;Zero counters
|
||
.LARHC==7 ;[7.1120]Request host-initiated connect
|
||
.LATHC==10 ;[7.1120]Terminate host-initiated connect
|
||
.LASHC==11 ;[7.1120]Show host-initiated connects
|
||
|
||
;Argument list offsets
|
||
|
||
.LAACT==0 ;Argument block count
|
||
.LAFCN==1 ;LATOP% function code
|
||
.LAPRM==2 ;SET/CLEAR parameter number
|
||
LA%PSI==1B0 ;Use PSI to interrupt (TOPS-20)
|
||
LA%WAI==1B0 ;Wait for completion (TOPS-10)
|
||
LA%QUE==1B1 ;Queue the request at the remote server
|
||
LA%SYS==1B2 ;Show all host-initiated connects
|
||
LA%JOB==1B3 ;Show all host-initiated connects for the job
|
||
LA%CID==777777 ;Connect id
|
||
.LAVAL==3 ;SET/CLEAR new parameter value
|
||
LA%CHN==0,,-1 ;[7.1120]Interrupt channel
|
||
.LABCT==2 ;Buffer count
|
||
LA%ECB==1B0 ;Use the Extended Connect Block
|
||
.LABFA==3 ;Buffer Address
|
||
.LAQUA==4 ;Qualifier
|
||
.LADSC==5 ;(ASCIZ string pointer)
|
||
|
||
.LASVR==4 ;[7.1120]Server name
|
||
.LASVC==5 ;[7.1120]Service name
|
||
.LAPRT==6 ;[7.1120]Port name
|
||
|
||
LA%RAT==1B0 ;Set the rating specified
|
||
LA%DSC==1B1 ;Set the service description
|
||
|
||
;Parameter numbers for SET/CLEAR
|
||
|
||
.LPMAC==1 ;Maximum number of active circuits
|
||
.LPMCO==2 ;Maximum number of simultaneous connects
|
||
.LPNUM==3 ;Host number
|
||
.LPLAS==4 ;LAT access state
|
||
.LPRLI==5 ;Circuit retransmit limit
|
||
.LPTIM==6 ;Circuit timer initial value
|
||
.LPMTI==7 ;Multicast timer initial value
|
||
.LPCOD==10 ;Access codes
|
||
.LPNNM==11 ;Host node name
|
||
.LPNID==12 ;Host node identification string
|
||
.LPSRV==13 ;Service rating or description (depends on .LAQUA)
|
||
|
||
;Port type codes
|
||
|
||
.LATTY==1 ;[7.1120]Standard LAT terminal connection
|
||
.LADLP==2 ;[7.1120]Dial-up Lat terminal connection
|
||
.LAAPP==3 ;[7.1120]LAT application terminal
|
||
|
||
;Status and rejection codes
|
||
|
||
.LASOL==377777 ;[7.1120]Request is being solicited
|
||
.LAQUE==377776 ;[7.1120]Request is queued
|
||
.LACAN==377775 ;[7.1120]Request was cancelled by user
|
||
.LATMO==377774 ;[7.1120]Request has timed out
|
||
|
||
.LAUNK==00 ;[7.1120]Unknown error
|
||
.LAURD==01 ;[7.1120]User requested disconnect
|
||
.LASSP==02 ;[7.1120]System shutdown in progress
|
||
.LAISR==03 ;[7.1120]Invalid slot received
|
||
.LAISC==04 ;[7.1120]Invalid service class
|
||
.LAIRS==05 ;[7.1120]Insufficient resources
|
||
.LASIU==06 ;[7.1120]Service is in use
|
||
.LANSS==07 ;[7.1120]No such service
|
||
.LASDI==10 ;[7.1120]Service is disabled
|
||
.LASNP==11 ;[7.1120]Service is not offered by requested port
|
||
.LANSP==12 ;[7.1120]No such port name
|
||
.LAIPW==13 ;[7.1120]Invalid password
|
||
.LAENQ==14 ;[7.1120]Entry is not in queue
|
||
.LAIAR==15 ;[7.1120]Immediate access rejected
|
||
.LAACD==16 ;[7.1120]Access denied
|
||
.LACSR==17 ;[7.1120]Corrupted solicit request
|
||
.LACTI==20 ;[7.1120]Command type code is illegal
|
||
.LASCS==21 ;[7.1120]Start slot can't be sent
|
||
.LAQED==22 ;[7.1120]Queue entry deleted by local node
|
||
.LAIRP==23 ;[7.1120]Inconsistent or illegal request parameters
|
||
SUBTTL Definitions -- TOPS-10 -- Error Codes
|
||
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
DEFINE ITERR (ERRCOD),<
|
||
IFB <ERRCOD>,<CALLRET STOTAC##>
|
||
IFNB <ERRCOD>,<
|
||
CALLRET [ MOVEI T1,ERRCOD
|
||
CALLRET STOTAC##]>>
|
||
|
||
DEFINE RETBAD (ERRCOD),<
|
||
IFB <ERRCOD>,<RET>
|
||
IFNB <ERRCOD>,<
|
||
CALLRET [ MOVEI T1,ERRCOD
|
||
RET]>>
|
||
|
||
DEFINE .ERRT (A,B,C,D) <
|
||
B==A
|
||
C==A> ;internal and external name
|
||
|
||
.ERRT (00,LATX01,LABTS%,<Buffer size too small for available data>)
|
||
.ERRT (01,LATX02,LAVOR%,<LAT parameter value out of range>)
|
||
.ERRT (02,LATX03,LALNO%,<LAT is not operational>)
|
||
.ERRT (03,LATX04,LASVR%,<Invalid or unknown LAT server name>)
|
||
.ERRT (04,LATX05,LAIPN%,<Invalid LAT parameter>)
|
||
.ERRT (05,LATX06,LAIPV%,<Invalid LAT parameter value>)
|
||
.ERRT (06,LATX07,LASVC%,<Invalid or unknown LAT service name>)
|
||
.ERRT (07,LATX08,LAILR%,<Insufficient LAT Resources>)
|
||
.ERRT (10,LATX09,LAHAS%,<LAT Host name already set>)
|
||
.ERRT (11,ARGX02,LAIVF%,<Function code out of range>)
|
||
.ERRT (12,ARGX04,LAABS%,<Argument list too small>)
|
||
.ERRT (13,LATXAC,LAADC%,<Address check for argument list>)
|
||
.ERRT (14,LATXPV,LAPRV%,<No privilege for attempted operation>)
|
||
.ERRT (15,LATX10,LAPRT%,<Invalid or unknown LAT port name>) ;[7.1120]
|
||
.ERRT (16,LATX11,LACID%,<Invalid or unknown connect id>) ;[7.1120]
|
||
SUBTTL Definitions -- TOPS-10 -- KS10 conditionals
|
||
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
IFE FTXMON,<
|
||
|
||
; Redefine some stuff if we running non-extended (KS10 especially)
|
||
;
|
||
DEFINE OWGP. (SS,ADR,POS),<POINT SS,ADR,POS>
|
||
|
||
DEFINE XBLT.(AC<T1>),<
|
||
IFN <AC>-T1,<PRINTX ? CAN'T XBLT VIA AC, USE T1>
|
||
CALL XBLTA##
|
||
>
|
||
|
||
> ;End IFN FTXMON
|
||
SUBTTL Definitions -- TOPS-10 -- Symbol purging macros
|
||
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
; Define some macros which will help purge all symbols of
|
||
; the form ..nnnn at the end of assembly. This will get rid
|
||
; of about 200 useless symbols generated by .IFSKP and friends
|
||
|
||
define eq(a,b),<a==b>
|
||
|
||
define highest(sym,%tg),< ;;Macro to find highest generated symbol
|
||
....==sixbit/%tg/&000077777777 ;;Isolate the nnnn part of ..nnnn
|
||
eq(sym,\'....)
|
||
purge ....>
|
||
|
||
define prgnum(n),< ;;Macro to purge symbol named ..nnnn
|
||
....==sixbit/n/ ;;given a number n
|
||
ifl <n-1000>,<....==<..../100>!sixbit/0/> ;;make leading zero fill
|
||
ifl <n-100>,<....==<..../100>!sixbit/0/>
|
||
ifl <n-10>,<....==<..../100>!sixbit/0/>
|
||
prgsym(..,\'....)
|
||
purge ....>
|
||
|
||
define prgsym(sy1,sy2),<
|
||
purge sy1'sy2
|
||
>
|
||
|
||
define prgall,< ;;End product: macro to purge all symbols
|
||
if2,< ;;of the form ..nnnn
|
||
highest XX ;;Use this just before END statement
|
||
nn==XX
|
||
repeat XX,<prgnum(\nn)
|
||
nn==nn-1>
|
||
|
||
nn==.npac
|
||
repeat .npac,<prgsym(.fpac,\nn) ;;get rid of .fpacN symbols
|
||
nn==nn-1>
|
||
purge nn,XX,.npac>
|
||
>
|
||
SUBTTL Definitions -- TOPS-10 -- Accumulators
|
||
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
; Allocate some ACs for use in LATOP. UUO
|
||
; Use W, since we don't use it for anything else.
|
||
; Use M, since it is W+1 for 7.03
|
||
; We don't bother saving W, since it is useless.
|
||
; We save M at start of LATOP. UUO and restore just before end
|
||
; because it contains the actual UUO and AC field to store to
|
||
;
|
||
Q1==W ;redefine some TOPS-20 ACs
|
||
Q2==M ;( = W+1)
|
||
|
||
|
||
; Don't let TRVAR allocate storage for TOPS-10, since TOPS-10 cannot
|
||
; maintain a frame pointer. If TRVAR is used, it will create undefined
|
||
; global symbols.
|
||
;
|
||
DEFINE TRVAR(LIST),<>
|
||
|
||
DEFINE ACDEF(N,AC),<.FPAC'N==AC>
|
||
|
||
DEFINE FREEAC(AC),<
|
||
.NPAC==0
|
||
IRP AC,<
|
||
ACDEF(\.NPAC,AC)
|
||
.NPAC==.NPAC+1
|
||
>>
|
||
|
||
FREEAC <W,M,P1,P2,P3,P4,J> ;These are all the ACs available for ACVAR
|
||
;Explicitly do NOT use "U" since it is used
|
||
;for the normal TOPS-10 function to point to
|
||
;an LDB throughout the code
|
||
;Still in IFN FTOPS10
|
||
SUBTTL Definitions -- Title
|
||
|
||
|
||
DEFINE ACVAR (LIST)<
|
||
..NAC==0 ;;INIT NUMBER OF ACS USED
|
||
IRP LIST,<
|
||
.ACV1 (LIST,\..NAC) ;;PROCESS ITEMS
|
||
..NAC==..NAC+1>
|
||
SAVEAC (<LIST>) ;;SAVE ACS USED (QUICK AND DIRTY)
|
||
DEFINE ENDAV.<.ENAV1 <LIST>>>
|
||
|
||
DEFINE .ACV1 (ITEM,N)<
|
||
.ACV2 (ITEM,N)> ;;PEEL OFF ANGLEBRACKETS IF ANY
|
||
|
||
DEFINE .ACV2 (NAM,N)<
|
||
IFDEF NAM,<.IF NAM,SYMBOL,<PRINTX ACVAR NAM ALREADY DEFINED>>
|
||
NAM==.FPAC'N ;;DEFINE VARIABLE
|
||
$'NAM==NAM ;;FOR DDT
|
||
>
|
||
|
||
DEFINE .ENAV1 (ARGS)<
|
||
IRP ARGS,<
|
||
.ENAV2 (ARGS)>>
|
||
|
||
DEFINE .ENAV2 (ARG)<
|
||
.ENAV3 (ARG)>
|
||
|
||
DEFINE .ENAV3 (NAM,SIZ)<
|
||
PURGE NAM,NAM
|
||
>
|
||
XOFFC=="S"-100 ;XOFF CHARACTER
|
||
XONC=="Q"-100 ;XON CHARACTER
|
||
|
||
> ;End IFN FTOPS10
|
||
SUBTTL Definitions -- Literals -- Circuit Parameters
|
||
|
||
|
||
;
|
||
;LAT Virtual Circuit Message Types
|
||
;
|
||
MT.RUN==0 ;RUN message
|
||
MT.STA==1 ;START message
|
||
MT.STP==2 ;STOP message
|
||
MT.MCA==^D10 ;Multicast message
|
||
MT.CMD==^D12 ;[7.1120]Command message
|
||
MT.STS==^D13 ;[7.1120]Status message
|
||
MT.SIN==^D14 ;[7.1120]Solicit Information message
|
||
MT.RIN==^D15 ;[7.1120]Response Information message
|
||
MT.EID==^D10 ;[7.1150]Offset to Entry ID field in command msg
|
||
|
||
;LAT Virtual Circuit States
|
||
;
|
||
|
||
CS.HLT==0 ;HALTED
|
||
CS.STA==1 ;STARTING
|
||
CS.RUN==2 ;RUNNING
|
||
CS.TRN==-1 ;In transition between HALTED and STARTING
|
||
|
||
;
|
||
;Circuit STOP message reason codes
|
||
;
|
||
|
||
CE.NSL==1 ;No slots connected on circuit
|
||
CE.ILL==2 ;Illegal message or slot format
|
||
CE.HLT==3 ;Circuit halted by local system
|
||
CE.NPM==4 ;No progress being made
|
||
CE.TIM==5 ;Time limit expired
|
||
CE.LIM==6 ;Retransmit limit exceeded
|
||
CE.RES==7 ;Insufficient resources
|
||
CE.STO==10 ;Server circuit timer out of range
|
||
CE.SKW==11 ;Protocol version skew
|
||
CE.INV==12 ;Invalid Message
|
||
|
||
;Circuit STOP reason codes of local significance only
|
||
|
||
CE.NIH==200 ;Local NI halted
|
||
|
||
MMHDSI==^D8 ;Minimum Message Header Size
|
||
MSTMSI==^D16 ;Minimum START Message Size(excluding header)
|
||
|
||
SUBTTL Definitions -- Literals -- Slot Parameters
|
||
|
||
|
||
;
|
||
;LAT Slot Types
|
||
;
|
||
|
||
ST.DTA==0 ;DATA_A slot
|
||
ST.STA==11 ;START slot
|
||
ST.DTB==12 ;DATA_B slot
|
||
ST.ATT==13 ;ATTENTION slot
|
||
ST.REJ==14 ;REJECT slot
|
||
ST.STP==15 ;STOP slot
|
||
|
||
;
|
||
; LAT Slot States
|
||
;
|
||
|
||
SS.HLT==0 ;Halted
|
||
SS.RUN==1 ;Running
|
||
SS.SIN==2 ;[7.1120]Solicit Information
|
||
SS.SAI==3 ;[7.1120]Solicit Access (initialize first)
|
||
SS.SAC==4 ;[7.1120]Solicit Access
|
||
SS.QUE==5 ;[7.1120]Queued
|
||
SS.REJ==6 ;[7.1120]Rejected
|
||
SS.TMO==7 ;[7.1120]Timed out
|
||
SS.CAI==10 ;[7.1120]Cancel (initialize first)
|
||
SS.CAN==11 ;[7.1120]Cancel
|
||
SS.MAX==SS.CAN ;[7.1120]Maximum state value
|
||
|
||
;
|
||
; SLOT Reject and Stop Reason Codes
|
||
;
|
||
|
||
SE.USR==1 ;User requested disconnect
|
||
SE.SHU==2 ;System shutdown in progress
|
||
SE.ISR==3 ;Invalid slot received
|
||
SE.SER==4 ;Invalid service class
|
||
SE.RES==5 ;Insufficient resources available
|
||
SE.ENQ==^D12 ;[7.1120]Entry is not in queue
|
||
SE.CSR==^D15 ;[7.1120]Corrupted solicit request
|
||
;
|
||
; DATA_B Slot Control Flag Bit Definitions
|
||
; Low order bit always set to enable "HOSTSYNC" flow control ala VAX
|
||
; Other bits Enables/Disables "TTSYNC" in VAX terms.
|
||
|
||
SL.EXF==^B0101 ;[7.1039]Enable XON/XOFF recognition in server
|
||
SL.DXF==^B1001 ;[7.1039]Disable XON/XOFF recognition in server
|
||
|
||
; Connect id's for pending requests have a random portion (determined by
|
||
; the array PRRAND) and a fixed protion (the index into PRVECT and
|
||
; PRRAND).
|
||
;
|
||
PR.NDX==000377 ;[7.1120]The LO eight-bits are the index
|
||
PR.RAN==000377 ;[7.1120]The HO eight-bits are random
|
||
PR%RAN==<PR.RAN>B27 ;[7.1120]Here is the position of PR.RAN
|
||
|
||
;
|
||
; SLOT Size Definitions
|
||
;
|
||
|
||
SLHDSI==4 ;Slot header size
|
||
ATTSIZ==SLHDSI ;ATTENTSION slot size
|
||
DTBSIZ==SLHDSI+5 ;DATA_B slot size
|
||
IFN FTOPS20,<
|
||
NIPIA==DLSCHN ;Priority Interrupt Assignment for KLNI
|
||
>
|
||
|
||
;
|
||
;Response Information Status Bits
|
||
;
|
||
RI%NDS==1 ;[7.1120]Node is disabled
|
||
RI%NSS==2 ;[7.1120]No such service
|
||
RI%CMD==4 ;[7.1120]Node can accept a command message
|
||
;
|
||
;Miscellaneous Constants
|
||
;
|
||
|
||
LAHPV==5 ;Highest protocol version supported
|
||
LALPV==5 ;Lowest protocol version supported
|
||
PROVER==5 ;Our LAT protocol version
|
||
PROECO==1 ;[7.1120]Our LAT protocol ECO
|
||
MXSLSI==^D40 ;[7346]Maximum slot size we will receive
|
||
MXSLTS==^D64 ;Maximum slot sessions per circuit
|
||
LMRFSI==^D1504 ;Receive buffer size
|
||
MXHSRV==10 ;Maximum number of services offered
|
||
IFN FTOPS20,<
|
||
LHPRID==6 ;Product code type for TOPS-20 host
|
||
>
|
||
IFN FTOPS10,<
|
||
LHPRID==7 ;Product code type for TOPS-10 host
|
||
>
|
||
SCITTY==1 ;Interactive terminal service class
|
||
MAXXBF==2 ;Maximum number of transmit buffers/circuit
|
||
CBMAXI==^D255 ;[7.1164]Absolute maximum circuit id
|
||
PRMAXI==^D64 ;[7.1120]Maximum pending requests
|
||
SLHDSZ==4 ;Slot header size (bytes)
|
||
MAXCRE==2 ;Maximum number of credits to extend to remote.
|
||
MXBALC==6 ;Number of ticks to wait before sending
|
||
; unsolicited message to server
|
||
DLL.FL==1B0 ;[7.1120]UNUID: Buffer is in DLL (NI service)
|
||
SAV.FL==1B1 ;[7.1120]UNUID: Buffer for pending request
|
||
MSB.FL==2 ;[7.1155]Symbol for Master/slave bit
|
||
MINXBF==^D46 ;Minimum transmit buffer size
|
||
|
||
XRESCD ;[7.1024]
|
||
|
||
SUBTTL Definitions -- Data Structures
|
||
|
||
|
||
; UN Block Extension
|
||
|
||
BEGSTR UE
|
||
WORD LW0 ;Queue Link Word for linking buffers to CB Qs
|
||
WORD LW1 ;Queue Link Word for linking buffers to NI Qs
|
||
ENDSTR
|
||
|
||
;
|
||
; Buffer offsets
|
||
;
|
||
|
||
UNB.OF==UE.LEN ;Start of UN block for all buffers
|
||
MDB.OF==UE.LEN+UN.LEN ;Start of MD block
|
||
XBF.OF==UE.LEN+UN.LEN+MD.LEN
|
||
SBF.OF==UE.LEN+UN.LEN
|
||
|
||
SZMSTP==<XBF.OF+SZ.MHD+1>;STOP message size in words
|
||
SZ.SHD==4 ;Slot header size
|
||
SZ.ATT==1 ;Attention size
|
||
SZ.REJ==0 ;Reject slot size
|
||
SZ.SDB==5 ;DATA_B slot size
|
||
SZ.SSP==0 ;Stop slot size
|
||
SZ.SST==6 ;Start slot size
|
||
SZ.XBF==<^D1500+3>/4
|
||
SZ.MSP==^D10 ;Start message size
|
||
SZ.MHD==^D8 ;Message header size
|
||
|
||
ML.NNM==6 ;Max length of node name
|
||
ML.SYS==^D16 ;Max length of system name
|
||
ML.LOC==^D64 ;Max length of location field
|
||
ML.DSC==^D64 ;Max length of description field
|
||
ML.SRN==^D16 ;[7.1120]Max length of server name
|
||
ML.PRN==^D16 ;[7.1120]Max length of port name
|
||
ML.SVN==^D16 ;[7.1120]Max length of service name
|
||
ML.SID==^D64 ;Max length of service identification field
|
||
ML.HMC==^D33+<1+ML.NNM>+<1+ML.DSC>+MXHSRV*<1+ML.SVN+1+ML.SID>+2
|
||
;Host multicast message max length
|
||
ML.HSM==^D12+<1+ML.NNM>+<1+ML.LOC>+<1+ML.SYS>+1
|
||
;Host start message max length
|
||
ML.HCM==^D54+ML.SRN+ML.SYS+ML.SVN+ML.PRN
|
||
;[7.1120]Max length of host command msg
|
||
MW.SYS==<ML.SYS+4>/5 ;[7.1039]Max length of system name in words
|
||
MW.LOC==<ML.LOC+4>/5 ;[7.1039]Max length of location field in words
|
||
MW.SHC==4+<ML.SRN+4>/5+<ML.PRN+4>/5+<ML.SVN+4>/5
|
||
;[7.1120]Length of an .LASSC Status block
|
||
MW.OCB==<<ML.SYS+4>/5>+2;[7.1120]Length of an "old style" connect
|
||
;block
|
||
MW.ECB==MW.OCB+1+<<<ML.SYS+4>/5>*2>
|
||
;[7.1120]Length of an "extended" connect
|
||
;block
|
||
|
||
SUBTTL Definitions -- Data Structures -- Host Node (HN) Block
|
||
|
||
|
||
;Host Node Data Structures
|
||
;
|
||
|
||
BEGSTR GB ;SERVICE BLOCK
|
||
WORD RAT ;Service Rating.
|
||
HWORD NC ;Count of bytes in service name.
|
||
HWORD LC ;Count of bytes in service description
|
||
WORD NAM,<<ML.SVN+4>/5> ;Storage for up to 16 bytes of service name.
|
||
WORD HID,<<ML.SID+4>/5> ;Storage for up to 64 bytes of service id.
|
||
ENDSTR
|
||
|
||
BEGSTR HN ;HOST NODE Data Base
|
||
FIELD FLG,^D18
|
||
BIT RUN ;NI run state
|
||
BIT ANY ;Reconstruct of START msg necessary
|
||
BIT CIP ;Virtual circuit connect in progress
|
||
FILLER ^D10
|
||
FIELD CFL,^D8 ;Multicast message change flags
|
||
BIT OTH ;Something other than above changed
|
||
BIT FIL
|
||
BIT CLS ;A host service class changed
|
||
BIT SVD ;A host service description changed
|
||
BIT SVR ;A host service rating changed
|
||
BIT SVN ;A host service name changed
|
||
BIT NDD ;Host Node Description changed
|
||
BIT ACS ;Access Codes changed
|
||
;START OF PARAMETERS DISPLAYED BY .LASCH
|
||
HWORD MXC ;Maximum allocatable circuit blocks
|
||
HWORD NCC ;Number of currently allocated circuit blocks
|
||
HWORD MAC ;Maximum number of active circuits
|
||
HWORD NAC ;Number of currently active circuits
|
||
HWORD MCO ;Maximum number of simultaneous connects
|
||
HWORD CON ;Current number of active connects
|
||
HWORD NUM ;Host number
|
||
HWORD LAS ;LAT access state
|
||
HWORD RLI ;Virtual circuit message retransmit limit
|
||
HWORD TIM ;Virtual circuit timer initial value (ms)
|
||
HWORD MTI ;Multicast timer initial value (sec)
|
||
;END OF PARAMETERS DISPLAYED BY .LASCH
|
||
HWORD RAT ;Host node dynamic rating
|
||
HWORD PRG ;Host progress timer
|
||
HWORD NRB ;Number of receive buffers allocated
|
||
;[7.xxxx]Remove definition of HNRTX
|
||
HWORD CMT ;[7.1120]Command message retry timer (ms)
|
||
HWORD CMX ;[7.1120]Command message retry limit
|
||
WORD HST ;Address of state table
|
||
WORD QAC,2 ;Queue header for active circuit blocks
|
||
WORD QIC,2 ;Queue header for inactive circuit blocks
|
||
WORD NIQ,2 ;Interrupt level message queue
|
||
WORD SCQ,2 ;Scheduler level message queue
|
||
WORD PID ;NI Portal ID
|
||
HWORD NXI ;Next circuit block index to assign
|
||
HWORD NSV ;Number of offered services
|
||
WORD LOK ;Lock for HN data base
|
||
HWORD NMC ;Host node name count
|
||
HWORD IDC ;Host identification string count
|
||
WORD NAM,2 ;Host node name string
|
||
WORD ID,<<ML.DSC+4>/5> ;Host identification string
|
||
WORD SMT,<<<ML.HSM+3>/4>+SBF.OF>;Start message template
|
||
WORD MCM,<<ML.HMC+3>/4> ;Copy of the multicast message.
|
||
WORD SRV,<GB.LEN*MXHSRV>;Storage for service blocks
|
||
ENDSTR
|
||
|
||
BEGSTR AC,HN.LST ;ACCESS CODES
|
||
WORD LNG ;Access code string length in bytes
|
||
WORD COD,^D32 ;Storage for 256 bit bit-mask
|
||
ENDSTR
|
||
|
||
;LAT Circuit counters for all servers
|
||
|
||
BEGSTR HC,AC.LST
|
||
WORD RCV ;Messages received
|
||
WORD XMT ;Messages transmitted
|
||
WORD RTR ;Messages retransmitted
|
||
WORD SEQ ;Receive message sequence errors
|
||
WORD IMR ;Illegal messages received
|
||
WORD ISR ;Illegal slots received
|
||
WORD RES ;Resource errors
|
||
WORD MSK ;Illegal message error mask
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Data Structures -- Circuit Block (CB)
|
||
|
||
|
||
BEGSTR CB ;CIRCUIT BLOCK
|
||
WORD LNK,2 ;Queue Link words (must be first words)
|
||
HWORD RID ;Circuit handle assigned by the remote
|
||
HWORD LID ;Local circuit index
|
||
FIELD FLG,3 ;Virtual circuit flags
|
||
BIT RRF ;Reply requested flag
|
||
BIT MRS ;Must reply soon flag
|
||
BIT MRN ;Must reply now flag
|
||
HWORD CSB ;Count since balanced
|
||
HWORD SDC ;Number of slots with data waiting
|
||
HWORD TSQ ;Next transmit sequence number
|
||
HWORD RSQ ;Next expected receive sequence number
|
||
HWORD LRA ;Sequence number of last message ack'd by remote node.
|
||
WORD TIM ;Current value of circuit timer.
|
||
HWORD RTC ;Current retransmit count
|
||
WORD KAV ;[7295]2*Server Keep-alive-timer in ms.
|
||
; (in jiffies for TOPS-10)
|
||
WORD KAT ;TODCLK last time message receieved from server
|
||
HWORD QUA ;Circuit quality
|
||
HWORD ERR ;Reason code for last time circuit stopped
|
||
HWORD DLL ;Number of transmit buffers in the DLL
|
||
WORD XBQ,2 ;Queue of free transmit buffers
|
||
WORD AKQ,2 ;Unacknowledged queue header
|
||
WORD SBQ,2 ;Circuit slot queue
|
||
;
|
||
;The following are returned as part of the LATOP Get Server information info.
|
||
;
|
||
WORD DNI,2 ;NI address of remote server
|
||
HWORD MTF ;Maximum transmit frame size for circuit
|
||
HWORD RPV ;Remote protocol version and ECO
|
||
HWORD MSL ;Maximum slots allowed by remote
|
||
HWORD NBF ;Additional transmit buffers allowed by remote
|
||
HWORD CTI ;Value of remote's circuit timer
|
||
HWORD KTI ;Value of remote's keep-alive timer
|
||
HWORD PTC ;Product type code for remote node
|
||
HWORD STA ;Virtual circuit state
|
||
HWORD NUM ;Remote's system number
|
||
HWORD RSC ;Remote's system name count
|
||
HWORD RLC ;Remote's location text count
|
||
WORD SNM,<<ML.SVN+4>/5> ;Remote's system name
|
||
WORD LOC,<<ML.LOC+4>/5> ;Remote's location string
|
||
ENDSTR
|
||
BEGSTR CC,CB.LST ;CIRCUIT COUNTERS
|
||
WORD RCV ;Messages received
|
||
WORD XMT ;Messages transmitted
|
||
WORD RTR ;Messages retransmitted
|
||
WORD SEQ ;Receive message sequence errors
|
||
WORD IMR ;Illegal messages received
|
||
WORD ISR ;Illegal slots received
|
||
WORD RES ;Resource errors
|
||
WORD MSK ;Illegal message error mask
|
||
ENDSTR
|
||
|
||
|
||
; Boundary definitions in the CB for CLEAR and SHOW
|
||
; LAT Control Program functions.
|
||
|
||
CLRBEG==CB.FLG ;First clear field for .LACLR
|
||
CLREND==CB.DLL ;End of clear field for .LACLR
|
||
SASBEG==CB.DNI ;Start of .LASAS fields for single server
|
||
SASBG==CB.STA ;Start of .LASAS fields for multiple servers
|
||
SASEN==CB.SNM+<ML.SYS+4>/5 ;End of .LASAS fields for single server
|
||
SASEND==CB.LOC+<ML.LOC+4>/5 ;End of .LASAS fields for multiple servers
|
||
|
||
SUBTTL Definitions -- Data Structures -- Slot Block (SB)
|
||
|
||
|
||
BEGSTR SB
|
||
WORD LNK,2 ;Queue link word (must be first)
|
||
FIELD FLG,^D18 ;Flags
|
||
;*** Beginning of bits to be kept in order ***
|
||
BIT SDP ;Slot data present (must be sign bit)
|
||
BIT REJ ;Send REJECT Slot
|
||
BIT STR ;Send START Slot
|
||
BIT FOU ;Flush output
|
||
BIT OUT ;Output data available
|
||
BIT FCC ;Flow control change
|
||
BIT STO ;Send STOP Slot(Must be last)
|
||
;*** End of bits to be kept in order ***
|
||
SBSMSK==SBREJ!SBSTR!SBFOU!SBOUT!SBFCC!SBSTO ;[7.1120]
|
||
;[7.1120]Mask of bits which match BLSDSP
|
||
BIT DLP ;[7.1120]This slot is a dialup line
|
||
HWORD ATS ;Maximum attention slot size
|
||
HWORD MDS ;Maximum slot data size
|
||
HWORD STA ;Slot state
|
||
HWORD RID ;Remote slot id
|
||
HWORD LID ;Local slot id
|
||
HWORD XCR ;Transmit credits available to us
|
||
HWORD RCR ;Receive credits still outstanding
|
||
HWORD REA ;Reason code for stop or reject
|
||
HWORD SRC ;[7.1120]Server name count
|
||
HWORD PRC ;[7.1120]Port name count
|
||
HWORD SVC ;[7.1120]Service name count
|
||
WORD SRN,<<ML.SRN+4>/5> ;[7.1120]Server name
|
||
WORD PRN,<<ML.PRN+4>/5> ;[7.1120]Port name
|
||
WORD SVN,<<ML.SVN+4>/5> ;[7.1120]Service name
|
||
WORD TDB ;Terminal data block
|
||
WORD CBA ;Circuit block address for this slot
|
||
WORD PRA ;[7.1120]Pending request block address
|
||
IFN FTOPS10,<
|
||
FIELD REM,^D18 ;More flags for TOPS-10
|
||
BIT TTO ;"Character in SBCHR" bit, must be sign bit
|
||
BIT XNF ;"XON/XOF processing enabled
|
||
HWORD CHR ;space to hold saved character
|
||
> ;End IFN FTOPS10
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Data Structures -- Pending Request Block (PR)
|
||
|
||
|
||
;[7.1120]
|
||
BEGSTR PR
|
||
FIELD FLG,^D18 ;Flags
|
||
BIT WAI ;Wait for the connection
|
||
BIT QUE ;Queue this request
|
||
HWORD STA ;State (internal use only)
|
||
HWORD STS ;Status (visible to user)
|
||
HWORD QDP ;Queue depth
|
||
HWORD CID ;Local connect id
|
||
HWORD EID ;Remote entry id
|
||
HWORD JOB ;Job number (JCH for TOPS-10)
|
||
HWORD FRK ;Fork number
|
||
HWORD PSI ;PSI channel number
|
||
HWORD CMC ;Command message retry count
|
||
HWORD SRC ;Server name count
|
||
HWORD PRC ;Port name count
|
||
HWORD SVC ;Service name count
|
||
WORD SRN,<<ML.SRN+4>/5> ;Server name
|
||
WORD PRN,<<ML.PRN+4>/5> ;Port name
|
||
WORD SVN,<<ML.SVN+4>/5> ;Service name
|
||
WORD CMT ;Command message retry timer
|
||
WORD SBA ;Address of slot block
|
||
WORD XBA ;Address of COMMAND message
|
||
WORD DNI,2 ;Address of remote server
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- Data Structures -- Miscellaneous
|
||
|
||
|
||
BEGSTR QL ;Halfword Queue Link Word
|
||
WORD FWD ;Next forward queue element
|
||
WORD BWD ;Previous backward queue element
|
||
ENDSTR
|
||
|
||
SUBTTL Definitions -- External References
|
||
|
||
|
||
IFN FTOPS20,<
|
||
EXT DNGWDZ
|
||
EXT DNFWDS
|
||
EXT TTCHI
|
||
EXT LATMCT ;CLK2TM table timer for multicast
|
||
EXT LATCMT ;[7.1120]CLK2TM table timer for command message
|
||
>;END IFN FTOPS20
|
||
|
||
SUBTTL Definitions -- MIN.,MAX.,MAXENT Macros
|
||
|
||
|
||
; Macro MIN. (symbol,list) - Assigns minimum arithmetic value of list of items.
|
||
;
|
||
|
||
DEFINE MIN. (SYM,LIST),
|
||
<IRP LIST,<..X==LIST ;;Assign first value in list
|
||
STOPI>
|
||
IRP LIST,<IFL <LIST-..X>,<..X==LIST>> ;;Assign lowest in list
|
||
SYM==:..X> ;;Generate value
|
||
|
||
;
|
||
; Macro MAX. (symbol,list) - Assigns maximum arithmetic value of list of items.
|
||
;
|
||
|
||
DEFINE MAX. (SYM,LIST),
|
||
<IRP LIST,<..X==LIST ;;Assign first value in list
|
||
STOPI>
|
||
IRP LIST,<IFG <LIST-..X>,<..X==LIST>> ;;Assign highest in list
|
||
SYM==:..X> ;;Generate value
|
||
|
||
DEFINE PARTB. (PRM,MAX,MIN,CLRVAL,INSTR,FLAGS) <
|
||
|
||
.ORG <.LP'PRM+TBRNGE-1>
|
||
EXP <MAX,,MIN>
|
||
.ORG
|
||
.ORG <.LP'PRM+TBFLGS-1>
|
||
EXP <FLAGS!CLRVAL>
|
||
.ORG
|
||
.ORG <.LP'PRM+TBEXEC-1>
|
||
IFB <INSTR>,<
|
||
STOR T2,HN'PRM,(Q2)
|
||
>
|
||
IFNB <INSTR>,<
|
||
INSTR
|
||
>
|
||
.ORG
|
||
>
|
||
|
||
SUBTTL Definitions -- Local Variables
|
||
|
||
|
||
|
||
RESDT
|
||
|
||
CBVECT: BLOCK 1
|
||
SBVECT: BLOCK 1
|
||
PRVECT: BLOCK 1 ;[7.1120]Table of pending requests
|
||
PRRAND: BLOCK 1 ;[7.1120]Table of "random" connect id values
|
||
PRBITS: BLOCK <PRMAXI+^D35>/^D36 ;[7.1120]Bit table for PRVECT
|
||
PRBITN==.-PRBITS ;[7.1120]Length of PRBITS table
|
||
LASDEF::EXP LS.ON ;LAT Access Default State
|
||
NSLOTS: BLOCK 1
|
||
|
||
IFN FTOPS20,<
|
||
PRWMSK: BLOCK <PRMAXI+^D35>/^D36 ;[7.1120]Wake up mask for LATST
|
||
LAHNDB: BLOCK 1
|
||
|
||
MAX. (TMPLNG,<<GB.LEN+1>,ML.NNM,ML.DSC>)
|
||
NR (TMPBLK, TMPLNG)
|
||
TMPGB==TMPBLK+1
|
||
> ;end IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
OURNAM: BLOCK 2
|
||
OURCNT: BLOCK 1
|
||
LATRTQ: BLOCK 2 ;QUEUE FOR LAT LDBS
|
||
LATFRE: BLOCK QL.LEN ;QUEUE FOR LAT FREE CORE BLOCKS
|
||
LATLOC: BLOCK 1 ;START OF LAT FREE CORE (SET UP AT ONCE TIME)
|
||
LATMCT: BLOCK 1 ;Multicast timer (in seconds for TOPS-10)
|
||
LATNFB: BLOCK 1 ;Number of free buffers in pool
|
||
LATWFB: BLOCK 1 ;Number of free buffers wanted for new circuits
|
||
LATRFB: BLOCK 1 ;Number of buffers requested on last cycle
|
||
LASBAD: BLOCK 2 ;Ethernet address of sender of last bad msg
|
||
MSGDID: BLOCK 1 ;Destination ID from msg
|
||
MSGSID: BLOCK 1 ;Source ID from msg
|
||
MSGACK: BLOCK 1 ;ACK/SEQ field from msg
|
||
STPCOD: BLOCK 1 ;Stop reason
|
||
SLTDID: BLOCK 1 ;Destination ID from RUN msg
|
||
SLTSID: BLOCK 1 ;Source ID from RUN msg
|
||
SLTCNT: BLOCK 1 ;Slot count from RUN msg
|
||
SLTTYP: BLOCK 1 ;Slot type/credits/reason
|
||
SLTEPT: BLOCK 1 ;Pointer to the next slot
|
||
|
||
MAX. (TMPLNG,<<GB.LEN+1>,ML.NNM,ML.DSC>)
|
||
TMPBLK: BLOCK TMPLNG ;Temporary block for LATOP.
|
||
TMPGB==TMPBLK+1
|
||
|
||
>;end IFN FTOPS10
|
||
|
||
SUBTTL LATOP% JSYS -- Dispatch
|
||
|
||
|
||
XSWAPCD ;[7.1024]
|
||
|
||
XNENT (.LATOP,G) ;[7.1024].LATOP::, X.LATO::
|
||
|
||
IFN FTOPS20,<
|
||
MCENT
|
||
UMOVE Q1,1 ;Get the argument block address
|
||
> ;End IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
SAVEAC <W,M,P1,P2,P3,P4>;Save W (Q1) and M (Q2)
|
||
MOVE Q1,T1 ;Get the argument block address
|
||
MOVE J,.CPJOB## ;Also need job number
|
||
|
||
; For TOPS10, we must address-check the argument block or else we might
|
||
; get an IME doing a UMOVE or UMOVEM.
|
||
;
|
||
MOVE M,T1 ;Point to user's argument block
|
||
SNCALL (GETWRD##,MCSEC1);Get the first word (arg count)
|
||
ITERR (LATXAC) ;Arg block is not addressable!
|
||
MOVE P1,T1 ;Save length of argument block
|
||
MOVE T1,Q1 ;Copy address of argument block
|
||
MOVE T2,P1 ;Copy length of argument block
|
||
SNCALL (ARNGE##,MCSEC1) ;Address check the argument block
|
||
NOP ;Not addressable!
|
||
ITERR (LATXAC) ;Not writeable!
|
||
; (error because .LABCT gets rewritten)
|
||
> ;End IFN FTOPS10
|
||
|
||
; ..
|
||
; ..
|
||
|
||
SKIPN Q2,LAHNDB ;If there is no data base,
|
||
ITERR (LATX03) ; then LAT is not operational
|
||
UMOVE P1,.LAACT(Q1) ;Get the length of the argument block
|
||
UMOVE P2,.LAFCN(Q1) ;Get the function code
|
||
SKIPL P2 ;
|
||
CAILE P2,FNCMAX ;Range check the function code
|
||
ITERR (ARGX02) ;Function code out of range
|
||
LDB T1,[POINTR (FNCDSF(P2),LF%MSZ)] ;[7.1120]
|
||
CAMGE P1,T1 ;[7.1120]Is the argument block big enough?
|
||
ITERR (ARGX04) ;[7.1120]No, argument list too small
|
||
MOVE P3,FNCDSF(P2) ;[7.1120]Get the function flags word
|
||
TXNN P3,LF%PRV ;[7.1120]Is this a privileged operation?
|
||
IFSKP. ;[7.1120]Yes, then check capabilities
|
||
IFN FTOPS20,<
|
||
MOVE T1,CAPENB ;[7.1120]
|
||
TXNN T1,SC%WHL!SC%OPR ;[7.1120]Has WHEEL or OPERATOR privileges?
|
||
ITERR (CAPX1) ;[7.1120]No, insufficient privileges
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVSI T1,JP.POK ;[7.xxxx]Has POKE, JACCT, or [1,2]
|
||
SNCALL (PRVBIT##,MCSEC1) ; privileges?
|
||
TRNA ;Yes, proceed
|
||
ITERR (LATXPV) ;No, insufficient privileges
|
||
> ;End IFN FTOPS10
|
||
ENDIF.
|
||
|
||
; ..
|
||
; ..
|
||
|
||
IFN FTOPS20,<
|
||
NOINT ;Don't allow PSI while owning lock
|
||
LOCK HN.LOK(Q2) ;Get the lock
|
||
CALL @FNCDSP(P2) ;[7.1120]Dispatch to perform the function
|
||
IFSKP. ;[7.1120]
|
||
UNLOCK HN.LOK(Q2) ;[7.1120]Release data base lock
|
||
OKINT ;[7.1120] and allow interrupts
|
||
MRETNG ;[7.1120]Return to the user
|
||
ELSE. ;[7.1120]
|
||
UNLOCK HN.LOK(Q2) ;[7.1120]Release data base lock
|
||
OKINT ;[7.1120] and allow interrupts
|
||
ITERR () ;[7.1120]Error already reported
|
||
ENDIF. ;[7.1120]
|
||
MRETNG ;[7.1120]Return to user
|
||
> ;End IFN FTOPS20
|
||
|
||
; For TOPS-10, check the addressability of the show buffer.
|
||
;
|
||
IFN FTOPS10,<
|
||
TXNN P3,LF%SBF ;Is there a show buffer?
|
||
IFSKP. ;Yes, then check addressability
|
||
UMOVE T1,.LABFA(Q1) ;Get address of show buffer
|
||
XCTU [HRRE T2,.LABCT(Q1)] ;Get length of show buffer
|
||
SNCALL (ARNGE##,MCSEC1) ;Address check the show buffer
|
||
NOP ;Not addressable!
|
||
ITERR (LATXAC) ;Not writeable!
|
||
ENDIF.
|
||
|
||
CALL @FNCDSP(P2) ;Dispatch to perform the function
|
||
ITERR () ;Error already reported
|
||
RETSKP ;Return to the user
|
||
> ;End IFN FTOPS10
|
||
|
||
;[7.1120]LATOP% JSYS dispatch table
|
||
|
||
DEFINE FNC,<
|
||
|
||
XALL ;;List generated table
|
||
|
||
XX .LASET, LASET, LF%PRV , .LAVAL+1 ;; (0) Set host parameters
|
||
XX .LACLR, LACLR, LF%PRV , .LAPRM+1 ;; (1) Clear host parameters
|
||
XX .LASCH, LASCH, LF%SBF , .LABFA+1 ;; (2) Show characteristics
|
||
XX .LASTC, LASTC, LF%SBF , .LABFA+1 ;; (3) Show terminal connects
|
||
XX .LASAS, LASAS, LF%SBF , .LAQUA+1 ;; (4) Show adjacent servers
|
||
XX .LASCO, LASCO, LF%SBF , .LABFA+1 ;; (5) Show counters
|
||
XX .LAZCO, LAZCO, LF%PRV!LF%SBF, .LABFA+1 ;; (6) Zero counters
|
||
XX .LARHC, LARHC, LF%PRV , .LADSC+1 ;; (7) Request host-initiated connect
|
||
XX .LATHC, LATHC, LF%PRV , .LAPRM+1 ;;(10) Terminate host-initiated connect
|
||
XX .LASHC, LASHC, LF%PRV!LF%SBF, .LAQUA+1 ;;(11) Show host-initiated connects
|
||
|
||
SALL ;;Turn listing back on
|
||
|
||
> ;End DEFINE FNC
|
||
|
||
DEFINE XX (CODE,DISP,FLAG,MNSZ),<
|
||
XADDR. DISP ; CODE
|
||
> ;End DEFINE XX
|
||
|
||
|
||
; Generate function dispatch table
|
||
;
|
||
FNCDSP: FNC ;[7.1120]
|
||
FNCMAX==.-FNCDSP-1 ;[7.1120]Maximum LATOP% JSYS function code
|
||
|
||
|
||
|
||
LF%PRV==1B0 ;[7.1120]Privileged function
|
||
LF%SBF==1B1 ;[7.1120]Address check show buffer
|
||
LF%MSZ==777 ;[7.1120]Minimum size of the argument block
|
||
|
||
|
||
DEFINE XX (CODE,DISP,FLAG,MNSZ),<
|
||
EXP FLAG!MNSZ ; CODE
|
||
> ;End DEFINE XX
|
||
|
||
|
||
; Generate function flags table
|
||
;
|
||
FNCDSF: FNC ;[7.1120]
|
||
SUBTTL LATOP% JSYS -- Set/Clear Functions -- SSERVC
|
||
|
||
|
||
;LASET - Set LAT host parameters.
|
||
;LACLR - Clear LAT host parameters.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASET/LACLR
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LASET:
|
||
LACLR: UMOVE T1,.LAPRM(Q1) ;Get the parameter number to set/clear.
|
||
CAIL T1,MNSPAR ;Range check it
|
||
CAILE T1,MXSPAR ; ...
|
||
RETBAD (LATX06) ;Parameter number out of range
|
||
CAIE P2,.LACLR
|
||
IFSKP.
|
||
MOVX T3,LF%CLR ;Is this parameter clearable?
|
||
TDNN T3,TBFLGS-1(T1) ; ...
|
||
RETBAD (LATX07) ;No, return error
|
||
HRRZ T2,TBFLGS-1(T1) ;Get the value to clear to
|
||
JRST LASET0 ; and go clear it.
|
||
ENDIF.
|
||
UMOVE T2,.LAVAL(Q1) ;Get the new value to set
|
||
MOVX T3,LF%RNG ;Check if this parameter value should
|
||
TDNN T3,TBFLGS-1(T1) ; be range checked.
|
||
IFSKP. ;Yes
|
||
MOVE T3,TBRNGE-1(T1) ;Get the upper and lower ranges.
|
||
HRRZ T4,T3 ;Lower bound
|
||
HLRZS T3 ;Upper bound
|
||
CAML T2,T4
|
||
CAMLE T2,T3
|
||
RETBAD (LATX02)
|
||
ENDIF.
|
||
LASET0: HLRZ T3,TBFLGS-1(T1) ;Change flags to set.
|
||
ANDI T3,377
|
||
IORM T3,HN.FLG(Q2) ;Set them
|
||
XCT TBEXEC-1(T1) ;Do the store.
|
||
RETSKP
|
||
|
||
LF%RNG==1B1 ;Do range check on parameter value to set
|
||
LF%LOK==1B2 ;Lock the database before setting parameter
|
||
LF%CLR==1B3 ;Parameter may be cleared.
|
||
|
||
MAX. (MXSPAR,<.LPMAC,.LPMCO,.LPNUM,.LPLAS,.LPRLI,.LPTIM,.LPMTI,.LPCOD,.LPNNM,.LPNID,.LPSRV>)
|
||
MIN. (MNSPAR,<.LPMAC,.LPMCO,.LPNUM,.LPLAS,.LPRLI,.LPTIM,.LPMTI,.LPCOD,.LPNNM,.LPNID,.LPSRV>)
|
||
|
||
TBRNGE: BLOCK <MXSPAR-MNSPAR+1>
|
||
TBFLGS: BLOCK <MXSPAR-MNSPAR+1>
|
||
TBEXEC: BLOCK <MXSPAR-MNSPAR+1>
|
||
|
||
PARTB. (MAC,CBMAXI,1,^D10,<JRST SETMAC>,LF%RNG!LF%CLR) ;[7.1164]
|
||
PARTB. (MCO,NTTLAH,1,NTTLAH,,LF%RNG!LF%CLR)
|
||
PARTB. (NUM,177777,0,RTRADR,,LF%RNG!LF%CLR)
|
||
PARTB. (LAS,LS.ON,LS.OFF,0,,LF%RNG!<HNOTH_^D18>)
|
||
PARTB. (RLI,100,0,^D30,,LF%RNG!LF%CLR)
|
||
;[7.xxxx] Remove subroutine SETRTX.
|
||
PARTB. (TIM,^D100000,^D100,^D1000,,LF%RNG!LF%CLR) ;[7.1120]
|
||
PARTB. (MTI,60,10,^D30,,LF%RNG!LF%CLR!<HNOTH_^D18>)
|
||
PARTB. (COD,0,0,0,<JRST SETCOD>,LF%CLR!<HNACS_^D18>)
|
||
PARTB. (NNM,0,0,0,<JRST SETNNM>,0)
|
||
PARTB. (NID,0,0,0,<JRST SETNID>,LF%CLR!<HNNDD_^D18>)
|
||
PARTB. (SRV,0,0,0,<JRST SSERVC>,LF%CLR)
|
||
SUBTTL LATOP% JSYS -- SET/CLEAR SERVICE
|
||
|
||
;SSERVC - Set LAT Service
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL SSERVC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
SSERVC: SAVEAC <P3,P4>
|
||
CALL FNDSRV ;(T1-T4/T1)Find the service to be set/cleared.
|
||
RETBAD ()
|
||
MOVEM T1,P3 ;Save the service block address
|
||
CAIN P2,.LACLR ;Clearing rather than setting?
|
||
JRST CSERVC ;Yes.
|
||
SETZ P4,0 ;P4 will be used to assemble the change flags
|
||
UMOVE T1,.LAQUA(Q1) ;Get the flags and rating
|
||
TXNN T1,LA%RAT ;Set the rating?
|
||
IFSKP. ;Yes.
|
||
TXO P4,HNSVR ;Set rating change flag
|
||
HRRE T2,T1
|
||
MOVE T3,T2
|
||
AOS T2
|
||
CAIL T2,0 ;Range check the rating.
|
||
CAILE T2,^D256 ; ...
|
||
RETBAD () ;Out of range
|
||
STOR T3,GBRAT,+TMPGB ;Store the rating
|
||
ENDIF.
|
||
TXNN T1,LA%DSC ;Set the description?
|
||
IFSKP.
|
||
TXO P4,HNSVD ;Description change flag
|
||
UMOVE T1,.LADSC(Q1) ;Get the user's pointer to description string
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Is the ASCIZ string addressable?
|
||
RETBAD (LATXAC) ;No, address check for argument list
|
||
> ;End IFN FTOPS10
|
||
MOVX T2,<POINT 7,GB.HID+TMPGB>;Where to put it.
|
||
MOVEI T3,ML.SID ;Maximum string count
|
||
CALL UMVAZS ;(T1-T3/T3)Move the string
|
||
RETBAD (LATX06)
|
||
STOR T3,GBLC,+TMPGB ;Store the description length
|
||
ENDIF.
|
||
SKIPN TMPBLK ;Did we add a new service?
|
||
IFSKP.
|
||
OPSTRM <AOS>,HNNSV,(Q2);Yes.
|
||
TXO P4,HNSVN ;Flag that number of services changed
|
||
ENDIF.
|
||
IORM P4,HN.FLG(Q2) ;Enter the assebled flags
|
||
MOVEI T1,GB.LEN ;Move the new service
|
||
XMOVEI T2,TMPGB ; to the service block
|
||
MOVE T3,P3 ; supplied by FNDSRV.
|
||
XBLT. T1
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Set/Clear Functions -- CSERVC
|
||
|
||
|
||
;CSERVC - Clear LAT service.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL CSERVC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
CSERVC: MOVE T3,T1 ;Start of overlay
|
||
LOAD T1,HNNSV,(Q2) ;Number of services before clear
|
||
CAIN T1,1 ;There must always be at least one service
|
||
RETBAD(LATX07) ;So return an error.
|
||
IMULI T1,GB.LEN ;Total length of service blocks
|
||
XMOVEI T4,HN.SRV(Q2) ;Service block start address
|
||
ADD T1,T4 ;Address of first word outside service block
|
||
XMOVEI T2,GB.LEN(T3) ;First address to move down
|
||
SUB T1,T2 ;Number of words to move down
|
||
SKIPG T1 ;Is there a service block above?
|
||
JRST CSRVC0 ;No so nothing to move
|
||
XBLT. T1 ;Compress all blocks downward
|
||
CSRVC0: OPSTRM <SOS>,HNNSV,(Q2) ;One service less.
|
||
MOVEI T1,HNCLS!HNSVD!HNSVR!HNSVN
|
||
IORM T1,HN.FLG(Q2) ;Indicate service changed.
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Set/Clear Functions -- SETNNM
|
||
|
||
|
||
;SETNNM - Set LAT host name.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL SETNNM
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
SETNNM: OPSTR <SKIPE>,HNNMC,(Q2);Has one already been set?
|
||
RETBAD (LATX09) ;Yes, illegal to reset.
|
||
UMOVE T1,.LABFA(Q1) ;Node name string pointer from the user.
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Is the ASCIZ string addressable?
|
||
RETBAD (LATXAC) ;No, address check for argument list
|
||
> ;End IFN FTOPS10
|
||
MOVX T2,<POINT 7,TMPBLK>;Pointer to where to build the string.
|
||
MOVEI T3,ML.NNM ;Maximum node name count.
|
||
CALL UMVAZS ;(T1-T3/T3)Move the ASCIZ string.
|
||
RETBAD (LATX06)
|
||
STOR T3,HNNMC,(Q2) ;Store the actual string count
|
||
MOVEI T1,<ML.NNM+4>/5 ;Maximum number of words in the string
|
||
XMOVEI T2,TMPBLK ;Move the string to
|
||
XMOVEI T3,HN.NAM(Q2) ; the host node data base
|
||
XBLT. T1 ; ...
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Set/Clear Functions -- SETNID/CLRNID
|
||
|
||
|
||
;SETNID/CLRNID - Set/Clear host identification string.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL SETNID/CLRNID
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
SETNID: CAIN P2,.LACLR ;Clearing rather than setting?
|
||
JRST CLRNID ;Yes.
|
||
UMOVE T1,.LABFA(Q1) ;Node description string pointer from the user.
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Is the ASCIZ string addressable?
|
||
RETBAD (LATXAC) ;No, address check for argument list
|
||
> ;End IFN FTOPS10
|
||
MOVX T2,<POINT 7,TMPBLK>;Pointer to where to build the string.
|
||
MOVEI T3,ML.DSC ;Maximum node description count.
|
||
CALL UMVAZS ;(T1-T3/T3)Move the ASCIZ string.
|
||
RETBAD (LATX06)
|
||
STOR T3,HNIDC,(Q2) ;Store the actual string count
|
||
MOVEI T1,<ML.DSC+4>/5 ;Maximum number of words in the string
|
||
XMOVEI T2,TMPBLK
|
||
XMOVEI T3,HN.ID(Q2)
|
||
XBLT. T1
|
||
RETSKP
|
||
|
||
CLRNID: SETZRO HNIDC,(Q2) ;Clear the string count
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Set/Clear Functions -- SETCOD
|
||
|
||
|
||
; SETCOD - Set/clear access codes
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL SETCOD
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
SETCOD:
|
||
IFN FTOPS10,<
|
||
UMOVE T1,.LABFA(Q1) ;Get address of string
|
||
MOVEI T2,^D8 ;and length
|
||
SNCALL (ARNGE##,MCSEC1) ; so check it.
|
||
ITERR (LATXAC) ;not there
|
||
NOP ;not writeable (that's ok)
|
||
> ;End IFN FTOPS10
|
||
SAVEAC <P1>
|
||
STKVAR <USRPTR,MSKPTR>
|
||
SETZM TMPBLK ;Zero out the storage where mask to be built.
|
||
XMOVEI T2,TMPBLK ;Zero the first workd
|
||
XMOVEI T3,1(T2) ;Address of second word
|
||
MOVEI T1,^D7 ;Number of words to zero.
|
||
XBLT. T1 ;
|
||
UMOVE T1,.LABFA(Q1) ;Group code address in user space.
|
||
HRLI T1,441000 ;Make an 8-bit byte pointer
|
||
MOVEM T1,USRPTR ;Save it as pointer to user code string.
|
||
MOVX T1,<POINT 8,TMPBLK>;Pointer to temporary storage for mask
|
||
MOVEM T1,MSKPTR ;Save it too.
|
||
MOVEI P1,^D32 ;Number of bytes to do
|
||
DO.
|
||
XCTBU [ILDB T1,USRPTR];Get a user group code byte
|
||
CALL BITSWP ;(T1/T1)Swap the bits
|
||
IDPB T1,MSKPTR ;Put into mask words
|
||
SOJG P1,TOP. ;Continue for full count
|
||
ENDDO.
|
||
MOVEI T1,^D8 ;32 bytes is 8 words
|
||
XMOVEI T2,AC.COD+7(Q2) ;Address of last group code word in database
|
||
DO.
|
||
MOVE T3,TMPBLK-1(T1) ;Get a mask word, going backwards
|
||
CAIN P2,.LACLR ;Clearing of Setting?
|
||
IFSKP.
|
||
IORM T3,(T2) ;Set the bits
|
||
ELSE.
|
||
ANDCAM T3,(T2) ;Clear the bits
|
||
ENDIF.
|
||
SOS T2
|
||
SOJG T1,TOP.
|
||
ENDDO.
|
||
RETSKP ;Return success.
|
||
;BITSWP - Swap all bits in an 8-bit byte.
|
||
;
|
||
; T1/ Byte to swap
|
||
; CALL BITSWP
|
||
; Return+1: Always, T1/ Swapped byte
|
||
|
||
BITSWP: SAVEAC <P1>
|
||
JUMPE T1,RTN ;If no bits, don't bother
|
||
MOVEI T3,1 ;Bit to test
|
||
MOVEI T4,200 ;Mirror bit
|
||
SETZ P1, ;Initialize result
|
||
DO.
|
||
TRNE T1,(T3) ;Is the bit set?
|
||
TRO P1,(T4) ;Yes, set mirror bit in result
|
||
LSH T3,1 ;Shift bit to test
|
||
LSH T4,-1 ; and mirror bit
|
||
JUMPN T4,TOP. ;Done?
|
||
ENDDO.
|
||
MOVE T1,P1 ;Return swapped byte in T1
|
||
RET
|
||
|
||
SUBTTL LATOP% JSYS -- SET MAXIMUM CIRCUITS
|
||
;[7.1164] Add routine SETMAC
|
||
;SETMAC - Set Maximum Circuits
|
||
;Call: T2/ New Maximum Circuits value
|
||
; Q2/ Host node data base address
|
||
;RETSKP - always
|
||
;
|
||
; This routine is called when a user issues the SET MAX CIRCUITS
|
||
;command to LCP. When it is called, HNMAC has already been range checked.
|
||
;It is in the range of 1 - CBMAXI.
|
||
|
||
SETMAC: STOR T2,HNMAC,(Q2) ;Store the new value
|
||
ADDI T2,MAXACB ;HNMXC should be at least HNMAC+MAXACB
|
||
OPSTR <CAMG T2,>,HNMXC,(Q2) ;Is it?
|
||
IFSKP. ;No, its not
|
||
CAILE T2,CBMAXI ;so make sure its not greater than CBMAXI
|
||
MOVEI T2,CBMAXI ; (It was, but its not now)
|
||
STOR T2,HNMXC,(Q2) ;And update HNMXC
|
||
ENDIF. ;
|
||
RETSKP ;All done
|
||
|
||
XRESCD ;[7.1024]
|
||
|
||
;UMVAZS - Move a user ASCIZ string into monitor space.
|
||
;
|
||
; T1/ User's string pointer
|
||
; T2/ Monitor's destination pointer
|
||
; T3/ Maximum string length in bytes
|
||
; CALL UMVAZS
|
||
; Return+1: Failure, string too long
|
||
; Return+2: Success, T3/ Number of bytes moved
|
||
|
||
UMVAZS: STKVAR <MAXCNT>
|
||
MOVEM T3,MAXCNT ;Save the maximum count
|
||
SETZ T3, ;Clear the string count
|
||
IFN FTOPS20,<
|
||
TLC T1,-1 ;Make an ASCII pointer to the
|
||
TLCN T1,-1 ; user's buffer
|
||
HRLI T1,(<POINT 7,0>) ; if necessary.
|
||
> ;End IFN FTOPS20
|
||
UMVAZ0: XCTBU [ILDB T4,T1] ;Get a character from his string.
|
||
JUMPE T4,RSKP ;Null found so string ended
|
||
CAML T3,MAXCNT ;If we are at the maximum, read no more.
|
||
RET
|
||
IDPB T4,T2 ;Deposit character in temp storage.
|
||
AOJA T3,UMVAZ0 ;Increment string count
|
||
|
||
ENDSV.
|
||
|
||
;MMVAZS - Move ASCIZ string within monitor context
|
||
|
||
;Call: T1/ Source ASCIZ Pointer
|
||
; T2/ Destination Pointer
|
||
; T3/ Maximum string count permitted
|
||
;RET - If string longer than maximum, truncated.
|
||
; T3/ Actual string count
|
||
|
||
MMVAZS: STKVAR <MAXCNT>
|
||
MOVEM T3,MAXCNT ;Save the maximum count
|
||
SETZ T3, ;Clear the string count
|
||
IFN FTOPS20,<
|
||
TLC T1,-1 ;[7.1039]Make an ASCII pointer to the
|
||
TLCN T1,-1 ;[7.1039] user's buffer
|
||
HRLI T1,(<POINT 7,0>) ;[7.1039] if necessary.
|
||
> ;End IFN FTOPS20
|
||
MMVAZ0: ILDB T4,T1 ;Get a character from his string.
|
||
JUMPE T4,RTN ;Null found so string ended
|
||
CAML T3,MAXCNT ;If we are at the maximum, read no more.
|
||
RET
|
||
IDPB T4,T2 ;Deposit character at destination
|
||
AOJA T3,MMVAZ0 ;Increment string count
|
||
|
||
ENDSV.
|
||
SUBTTL LATOP% JSYS -- Show Characteristics of Host
|
||
|
||
XSWAPCD ;[7.1024]
|
||
|
||
;LASCH - Show LAT host characteristics.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASCH
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
|
||
LASCH: SAVEAC <P1,P2,P3>
|
||
UMOVE T3,.LABFA(Q1) ;User buffer address
|
||
|
||
;Check to see if the user provided buffer is large enough for all the data
|
||
;
|
||
LOAD T1,HNNSV,(Q2) ;Compute the total buffer size
|
||
IMULI T1,GB.LEN ; required.
|
||
ADDI T1,<HN.MXC-HN.MTI+<ML.LOC+3>/4+<ML.DSC+3>/4+<ML.NNM+3>/4+^D16>
|
||
CALL UBFCHK ;[7.1039](T1,Q1/T1)Is user's buffer big enough?
|
||
RETBAD () ;[7.1039]No, too small
|
||
|
||
;Move fixed length dynamic parameters from the host node database (HN) to the
|
||
;user's buffer.
|
||
;
|
||
MOVEI T1,<HN.MTI-HN.MXC+1>;Number words to move
|
||
XMOVEI T2,HN.MXC(Q2) ;Address of first HN parameter to move
|
||
XBLTXU T1
|
||
|
||
;Move static parameters to the user's buffer.
|
||
;
|
||
MOVEI T1,5 ;Number of words to move
|
||
XMOVEI T2,[EXP <LAHPV,,LALPV>;Static parameter address
|
||
EXP <PROECO,,PROVER>
|
||
EXP <MXSLSI,,MXSLTS>
|
||
EXP <LMRFSI,,MXHSRV>
|
||
EXP <LHPRID,,0>]
|
||
XBLTXU T1
|
||
|
||
;Move the access code words
|
||
;
|
||
MOVEI P3,^D32 ;Number of bytes for the access codes
|
||
XMOVEI P2,AC.COD(Q2) ;Address of the access codes
|
||
TXO P2,<OWGP. 8,0> ;Make global pointer
|
||
MOVE P1,T3 ;Current address in user's buffer.
|
||
TXO P1,<OWGP. 8,0> ;Make a byte pointer
|
||
DO.
|
||
ILDB T1,P2 ;Get a byte for group codes
|
||
CALL BITSWP ;(T1/T1)Swap the bits
|
||
XCTBU [IDPB T1,P1] ;Deposit swapped byte into user buffer.
|
||
SOJG P3,TOP. ;Do all bytes
|
||
HRRZI T3,1(P1) ;Make user pointer an address again.
|
||
ENDDO.
|
||
;Move Host node name and host node description
|
||
;
|
||
MOVEI T1,<<ML.NNM+4>/5+<ML.DSC+4>/5+1> ;[7.1039]
|
||
XMOVEI T2,HN.NMC(Q2) ;[7.1039]Address of node name and description
|
||
XBLTXU T1 ;[7.1039]
|
||
|
||
;Move the service blocks
|
||
;
|
||
LOAD T1,HNNSV,(Q2) ;Number of services currently defined
|
||
UMOVEM T1,(T3) ;Move to user buffer
|
||
AOS T3 ;Advance buffer address
|
||
LOAD T1,HNNSV,(Q2) ;Get the size of the
|
||
IMULI T1,GB.LEN ; service blocks.
|
||
XMOVEI T2,HN.SRV(Q2) ;Address of service blocks
|
||
XBLTXU T1
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Show Terminal Connects
|
||
|
||
|
||
;LASTC - Show terminal connects.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASTC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
;[7.1039]Clean up register usage in LASTC/LAS1C
|
||
LASTC: SAVEAC <P1,P2,P3>
|
||
STKVAR <LTTCNT>
|
||
LOAD T1,HNCON,(Q2) ;How many do we think are connected?
|
||
MOVE P1,T1 ;Save count
|
||
XMOVEI P3,LAS1C ;[7.1120]Get routine to handle old connect blk
|
||
MOVEI T3,MW.OCB ;[7.1120]Initialize T3 with old size
|
||
UMOVE T2,.LABCT(Q1) ;[7.1120]Get the ECB flag
|
||
TXNN T2,LA%ECB ;[7.1120]Is it set?
|
||
IFSKP. ;[7.1120]Yes, so...
|
||
XMOVEI P3,LAS2C ;[7.1120] get routine to handled new
|
||
MOVEI T3,MW.ECB ;[7.1120] connect block and use new size.
|
||
ENDIF. ;[7.1120]
|
||
IMUL T1,T3 ;[7.1120]Calculate buffer space requirements
|
||
CALL UBFCHK ;[7.1039](T1,Q1/T1)Is his buffer big enough?
|
||
RETBAD () ;[7.1039]No, too small
|
||
MOVEI T1,NTTLAH ;Get size of SBvect
|
||
MOVEM T1,LTTCNT ;Save in local for decrementing
|
||
UMOVE T3,.LABFA(Q1) ;Get user's buffer address
|
||
MOVE P2,SBVECT ;Point to table of SBs
|
||
LASTCL: SKIPE T1,1(P2) ;Is there a slot block there?
|
||
CALL 0(P3) ;[7.1120](T1,T3/T3)Yes-move data to user buffer
|
||
JRST LASTCN ;No, go for next one
|
||
SOJLE P1,LASTCD ;Have we given the user as many as we said?
|
||
LASTCN: SOSLE LTTCNT ;Or have we exhausted SBVECT?
|
||
AOJA P2,LASTCL ;No, just go for next data block
|
||
LASTCD: UMOVE T1,.LABFA(Q1) ;Done, get address of show buffer again
|
||
SUB T3,T1 ;Calculate number of words moved
|
||
XCTU [HRLM T3,.LABCT(Q1)] ;and store it.
|
||
RETSKP ;And give good return
|
||
|
||
;LAS1C - Move one connect block to the user's show buffer.
|
||
;
|
||
; T1/ Slow block address
|
||
; T3/ Next address in the show buffer
|
||
; CALL LAS1C
|
||
; Return+1: Failure, no attached terminal or circuit block
|
||
; Return+2: Success, T3/ Updated address into show buffer
|
||
|
||
LAS1C:
|
||
IFN FTOPS20,<
|
||
SKIPE T2,SB.TDB(T1) ;Any LDB associated with slot?
|
||
SKIPN T4,SB.CBA(T1) ;Any circuit block?
|
||
RET ;No, skip this one
|
||
DYNST ;Get TTY line number (in T2)
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SKIPE U,SB.TDB(T1) ;Any LDB associated with slot?
|
||
SKIPN T4,SB.CBA(T1) ;Any circuit block?
|
||
RET ;No, skip this one
|
||
LDB T2,@[IW MCSEC1,LDPLNO##] ;Get TTY line number
|
||
> ;End IFN FTOPS10
|
||
OPSTR <HRLZ T1,>,CBRSC,(T4) ;Get server name string count
|
||
UMOVEM T2,0(T3) ;Give the TTY line number to the user
|
||
UMOVEM T1,1(T3) ;Store counts
|
||
ADDI T3,2 ;Two words have been moved
|
||
MOVEI T1,<<ML.SYS+4>/5> ;Get length of string
|
||
XMOVEI T2,CB.SNM(T4) ;Source name string
|
||
XBLTXU T1 ;Fill in the user's buffer
|
||
RETSKP
|
||
;LAS2C - Move one extended connect block to the user's show buffer.
|
||
;[7.1120]
|
||
; T1/ Slow block address
|
||
; T3/ Next address in the show buffer
|
||
; CALL LAS2C
|
||
; Return+1: Failure, no attached terminal or circuit block
|
||
; Return+2: Success, T3/ Updated address into show buffer
|
||
|
||
LAS2C: MOVE T4,T1 ;Stash the SB address here
|
||
IFN FTOPS20,<
|
||
SKIPE T2,SB.TDB(T4) ;Any LDB associated with slot?
|
||
SKIPN SB.CBA(T4) ;Any circuit block?
|
||
RET ;No, skip this one
|
||
DYNST ;Get TTY line number (in T2)
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SKIPE U,SB.TDB(T4) ;Any LDB associated with slot?
|
||
SKIPN SB.CBA(T4) ;Any circuit block?
|
||
RET ;No, skip this one
|
||
LDB T2,@[IW MCSEC1,LDPLNO##] ;Get TTY line number
|
||
> ;End IFN FTOPS10
|
||
UMOVEM T2,0(T3) ;Give the TTY line number to the user
|
||
MOVEI T2,.LATTY ;Assume standard tty
|
||
OPSTR <SKIPE>,SBDLP,(T4);Is this a dialup?
|
||
MOVEI T2,.LADLP ;Maybe, if it isn't an application terminal...
|
||
OPSTR <SKIPE>,SBPRA,(T4);Is it an application terminal?
|
||
MOVEI T2,.LAAPP ;Yes
|
||
OPSTR <HRL T2,>,SBSRC,(T4) ;Get server name string count
|
||
UMOVEM T2,1(T3) ;Store counts
|
||
ADDI T3,2 ;Two words have been moved
|
||
MOVEI T1,<<ML.SYS+4>/5> ;Get length of string
|
||
XMOVEI T2,SB.SRN(T4) ;Source name string
|
||
XBLTXU T1 ;Fill in the user's buffer
|
||
OPSTR <HRL T2,>,SBPRC,(T4) ;Get the port name count
|
||
OPSTR <HRR T2,>,SBSVC,(T4) ;Get the service name count
|
||
UMOVEM T2,0(T3) ;Give these counts to the user
|
||
AOS T3 ;Another word has been moved
|
||
MOVEI T1,<<ML.SYS+4>/5>*2 ;Get length of the string
|
||
XMOVEI T2,SB.PRN(T4) ;Port/service name strings
|
||
XBLTXU T1 ;Fill in the user's buffer
|
||
RETSKP
|
||
SUBTTL LATOP% JSYS -- Show Adjacent Servers
|
||
|
||
|
||
;LASAS - Show adjacent servers.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASAS
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LASAS: CAIL P1,.LAQUA+1 ;[7.1120]
|
||
XCTU [SKIPN T1,.LAQUA(Q1)] ;Is there a server name?
|
||
IFSKP. ;Yes, return information for that one
|
||
IFN FTOPS20,<
|
||
CALL MAKPTR ;(T1/T1)Make a valid ASCIZ pointer.
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Is the ASCIZ string addressable?
|
||
RETBAD (LATXAC) ;No, address check for argument list
|
||
> ;End IFN FTOPS10
|
||
CALL GTSRVR ;(T1,Q2/T1)Find circuit block by server name.
|
||
RETBAD () ;Unknown server
|
||
MOVE T4,T1 ;Save the circuit block address
|
||
MOVEI T1,<SASEND-SASBEG>;# words returned for single server
|
||
CALL UBFCHK ;[7.1039](T1,Q1/T1)Is user's buffer big enough?
|
||
RETBAD () ;No, too small
|
||
UMOVE T3,.LABFA(Q1) ;Get his buffer address
|
||
XMOVEI T2,SASBEG(T4) ;Address of source
|
||
XBLTXU T1 ;Move to user space
|
||
RETSKP ;Return successfully.
|
||
ENDIF.
|
||
|
||
LOAD T1,HNNCC,(Q2) ;Get the number of allocated circuit blocks
|
||
IMULI T1,<<<ML.SYS+4>/5>+3>;Compute space needed in user's buffer
|
||
CALL UBFCHK ;[7.1039](T1,Q1/T1)Is user's buffer big enough?
|
||
RETBAD () ;[7.1039]No, too small
|
||
UMOVE T3,.LABFA(Q1) ;Get user buffer address
|
||
MOVE T4,HN.QAC(Q2) ;First element on the active queue
|
||
CALL SASLP ;Get all those on the active queue
|
||
MOVE T4,HN.QIC(Q2) ;Do the same for
|
||
CALL SASLP ; the inactive queue.
|
||
RETSKP ;Return successfully.
|
||
|
||
SASLP: JUMPE T4,RTN ;No more circuit blocks on this queue
|
||
MOVE T1,CB.RSC(T4) ;get <number,,name count>
|
||
UMOVEM T1,(T3) ;Give it to user
|
||
ADDI T3,1 ;Bump destination address
|
||
MOVEI T1,<<ML.SYS+4>/5> ;There are 4 words of name
|
||
XMOVEI T2,CB.SNM(T4) ;Address of first to copy
|
||
XBLTXU T1 ;Copy to user's space
|
||
DMOVE T1,CB.DNI(T4) ;Get Ethernet address
|
||
XCTU [DMOVEM T1,(T3)] ;Give it to the user
|
||
ADDI T3,2 ;Account for those words
|
||
LOAD T4,QLFWD,+CB.LNK(T4);Get the next CB
|
||
JRST SASLP ;And continue looping thru queue
|
||
|
||
SUBTTL LATOP% JSYS -- Show Counters
|
||
|
||
|
||
;LASCO - Show LAT Counters.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASCO
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LASCO: UMOVE T1,.LAQUA(Q1) ;Get server name requested
|
||
CALL GTLCOB ;(T1/T1,T2)Get counter block given server name.
|
||
RET ;Error, already reported
|
||
XCTU [HRLM T1,.LABCT(Q1)];Tell user
|
||
XCTU [HRRZ T3,.LABCT(Q1)];Get his buffer count.
|
||
CAMGE T3,T1 ;Has user allocated large enough buffer?
|
||
RETBAD (LATX01) ;No
|
||
UMOVE T3,.LABFA(Q1) ;Get his buffer address
|
||
XBLTXU T1
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Zero counters
|
||
|
||
|
||
;LAZCO - Zero LAT Counters.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LAZCO
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LAZCO: UMOVE T1,.LAQUA(Q1) ;Get server name requested
|
||
CALL GTLCOB ;(T1/T1,T2)Get counter block given server name.
|
||
RET ;Error, already reported
|
||
SETZM (T2) ;Zero the first counter
|
||
XMOVEI T3,1(T2) ;
|
||
SOSLE T1 ;Compute number of words to zero
|
||
XBLT. T1 ;Zero the block
|
||
RETSKP ;Return successfully.
|
||
;GTLCOB - Get LAT Counter Block. Get the length and address of the LAT
|
||
; counter block based on server number.
|
||
|
||
;CALL: T1/ Pointer to server name or [0,,-1]
|
||
;RET: Error - server unknown
|
||
;RETSKP:Success with
|
||
; T1/ Counter block length in words
|
||
; T2/ Counter block address
|
||
|
||
GTLCOB: XCTU [SKIPN T1,.LAQUA(Q1)] ;[7.1039]Get server name requested
|
||
IFSKP. ;Zero a particular server's counters
|
||
IFN FTOPS20,<
|
||
CALL MAKPTR ;(T1/T1)Make a valid pointer
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Check to see if ASCIZ string is addressable
|
||
RETBAD (LATXAC) ;Nope, lose
|
||
>;end ifn FTOPS10
|
||
CALL GTSRVR ;(T1,Q2/T1)Find circuit block given server name
|
||
RETBAD () ;Unknown server
|
||
XMOVEI T2,CC.BEG(T1) ;Server counter block address
|
||
MOVEI T1,CC.LEN ;Server counter block length
|
||
ELSE. ;Local host counters wanted
|
||
MOVEI T1,HC.LEN ;Host counter block length
|
||
XMOVEI T2,HC.BEG(Q2) ;Host counter block address
|
||
ENDIF.
|
||
RETSKP
|
||
SUBTTL LATOP% JSYS -- Request Host-Initiated Connect
|
||
|
||
|
||
;[7.1120]
|
||
;LARHC - Request host-initiated connect.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LARHC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LARHC: MOVEI T1,PR.LEN ;Length of the pending request block
|
||
CALL MMGTZW ;(T1/T1)Allocate memory
|
||
RETBAD (LATX08) ;Error, insufficient LAT resources
|
||
MOVEM T1,P2 ;Save address of pending request block
|
||
CALL CKRHC ;(Q1,Q2,P1,P2)Check the arguments
|
||
IFSKP.
|
||
LOAD T1,PRCID,(P2) ;Save the connect id
|
||
XCTU [HRRM T1,.LAPRM(Q1)]
|
||
OPSTR <SKIPN>,PRWAI,(P2) ;Wait for the connection?
|
||
RETSKP ;Return (PSI interrupt on connection)
|
||
MOVE T1,P2 ;Get address of pending request block
|
||
CALL PRWAIT ;(T1)Wait for the connection
|
||
MOVE T1,P2 ;Get address of pending request block
|
||
LOAD T2,PRSTS,(P2) ;Return with status, rejection code,
|
||
UMOVEM T2,.LAVAL(Q1) ; or Terminal Designator
|
||
IFN FTOPS20,<
|
||
TXNE T2,.TTDES ;Did the connection succeed?
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
CAIL T2,.UXTRM ;
|
||
CAILE T2,.UXTRM+777 ;Did the connection succeed?
|
||
TRNA ;No, SKIP
|
||
> ;End IFN FTOPS10
|
||
RETSKP ;Yes - the connection succeeded.
|
||
SETZ T2, ;Here if it failed... Clear T2
|
||
XCTU [HRRM T2,.LAPRM(Q1)] ;Connect ID is invalid
|
||
CALL PRDEL ;Delete the pending request
|
||
RETSKP ;Return
|
||
ENDIF.
|
||
EXCH T1,P2 ;Save the error code and get the
|
||
; address of the pending request block
|
||
CALL PRDEL ;(T1)Delete the pending request block
|
||
MOVE T1,P2 ;Restore the error code
|
||
RETBAD () ;
|
||
;[7.1120]
|
||
;CKRHC - Check the .LARHC argument list and fill in the pending request block.
|
||
; This subroutine does almost all of the work for the routine LARHC so
|
||
; that LARHC can easily deallocate resources if an error occurs.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ Address of the pending request block
|
||
; CALL CKRHC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
CKRHC: MOVX T1,.LASOL ;Initialize status to "Soliciting"
|
||
STOR T1,PRSTS,(P2) ;
|
||
UMOVE T3,.LAPRM(Q1) ;Get the parameter word
|
||
SETO T1, ;
|
||
TXNE T3,LA%QUE ;Should the server queue this request?
|
||
STOR T1,PRQUE,(P2) ;Yes, set this bit
|
||
|
||
IFN FTOPS20,<
|
||
SAVEAC <P3> ;Get an AC
|
||
MOVE P3,T3 ;Save user's parm's here
|
||
MOVE T2,JOBNO ;Get my job number
|
||
STOR T2,PRJOB,(P2) ;Save it here
|
||
MOVE T2,FORKX ;Get my fork number
|
||
STOR T2,PRFRK,(P2) ;Save it here
|
||
TXNN T3,LA%PSI ;Using the interrupt system?
|
||
IFSKP.
|
||
LDB T2,[POINTR (T3,LA%CHN)]
|
||
STOR T2,PRPSI,(P2) ;Save the interrupt channel
|
||
ELSE.
|
||
STOR T1,PRWAI,(P2) ;Save the event wait flag
|
||
ENDIF.
|
||
|
||
> ;End IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
TXNE T3,LA%WAI ;Is the wait bit set?
|
||
STOR T1,PRWAI,(P2) ;Yes, set the event wait flag
|
||
MOVE T2,.CPJCH## ;Save the JCH
|
||
STOR T2,PRFRK,(P2) ;
|
||
ANDI T2,JOBMSK## ;Save the job number
|
||
STOR T2,PRJOB,(P2) ;
|
||
> ;End IFN FTOPS10
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Get the server name, service name, and port name.
|
||
;
|
||
CALL MVRHC ;(Q1,P1,P2)Move the ASCIZ strings
|
||
RETBAD () ;Error, return
|
||
OPSTR <SKIPG>,PRSRC,(P2) ;Is there a server name?
|
||
RETBAD (LATX04) ;No, invalid or unknown server name
|
||
LOAD T1,PRSVC,(P2) ;Get the length of the service name
|
||
LOAD T2,PRPRC,(P2) ;Get the length of the port name
|
||
SKIPN T1 ;Is there a service name
|
||
SKIPE T2 ; or port name?
|
||
TRNA ;Yes, all is well
|
||
RETBAD (LATX07) ;No, invalid or unknown service name
|
||
|
||
; Format the Solicit Information message.
|
||
;
|
||
CALL PRGET ;(/T1)Get a free PRVECT index number
|
||
RETBAD (LATX08) ;Error, insufficient LAT resources
|
||
STOR T1,PRCID,(P2) ;Save the PRVECT index number
|
||
MOVX T1,SBF.OF+<ML.HCM+4>/5 ;Get max length of a command msg
|
||
CALL MMGTZW ;(T1/T1)Allocate space for one
|
||
RETBAD (LATX08) ;Error, insufficient LAT resources
|
||
STOR T1,PRXBA,(P2) ;Save address of transmit buffer
|
||
MOVE T1,P2 ;Copy the address of pending request block
|
||
CALL FMSIN ;(T1)Format Solicit Information message
|
||
RETBAD () ;Error, return
|
||
MOVX T1,SS.SIN ;Change to Soliciting Information state
|
||
STOR T1,PRSTA,(P2) ; (need the Ethernet address)
|
||
LOAD T1,PRCID,(P2) ;Get the PRVECT index number
|
||
ANDI T1,PR.NDX ;Throw away the random portion
|
||
IFN FTOPS20,<
|
||
TXNE P3,LA%PSI ;Does the user want to block?
|
||
IFSKP.
|
||
MOVE T2,T1 ;Yes, don't destroy T1 (index into PRVECT)
|
||
IDIVI T2,^D36 ;Calculate the offset T2,
|
||
MOVE T3,BITS(T3) ; and the bit in T3
|
||
IORM T3,PRWMSK(T2) ;Set it now, so scheduler test will block
|
||
ENDIF.
|
||
> ;End IFN FTOPS20
|
||
ADD T1,PRVECT ;Calculate address of PRVECT entry
|
||
MOVEM P2,(T1) ;Save address of slot block
|
||
RETSKP ;
|
||
;[7.1120]
|
||
;MVRHC - Move the string values for the routine CKRHC.
|
||
;
|
||
; Q1/ User argument block address
|
||
; P1/ Length of user argument block
|
||
; P2/ Address of the pending request block
|
||
; CALL MVRHC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
MVRHC: SAVEAC <P3> ;Save P3
|
||
MOVN P3,P1 ;
|
||
CAILE P1,.LAPRT+1 ;Too many arguments specified?
|
||
MOVNI P3,.LAPRT+1 ;Yes, use the maximum
|
||
ADDI P3,.LASVR ;Calculate the negative number of strings
|
||
HRLZS P3 ;Make it an AOBJN pointer
|
||
|
||
; Loop for each of the ASCIZ strings specified.
|
||
;
|
||
MVRHC1: MOVEI T1,.LASVR(P3) ;Calculate the address
|
||
ADD T1,Q1 ; of the ASCIZ string pointer
|
||
XCTU [SKIPN T1,(T1)] ;Get the string pointer itself
|
||
JRST MVRHC2 ;None, try the next one
|
||
IFN FTOPS20,<
|
||
TLNN T1,777777 ;Is it a valid byte pointer?
|
||
JRST MVRHC3 ;No, invalid or unknown name
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
TLNN T1,777777 ;Is it a valid byte pointer?
|
||
TXO T1,<POINT 7> ;No, make it a valid byte pointer
|
||
SNCALL (CKSTR##,MCSEC1) ;(T1)Is this string addressable?
|
||
RETBAD (LATXAC) ;No, address check for argument list
|
||
> ;End IFN FTOPS10
|
||
XMOVEI T2,(P2) ;Calculate the destination address
|
||
ADD T2,RHCDST(P3) ;Make it a global byte pointer
|
||
MOVE T3,RHCMXL(P3) ;Get the maximum length
|
||
CALL UMVAZS ;(T1,T2,T3/T3)Move the ASCIZ string
|
||
JRST MVRHC3 ;Error, invalid or unknown name
|
||
XCT RHCXCT(P3) ;Save the length of the string
|
||
MVRHC2: AOBJN P3,MVRHC1 ;Save all of the ASCIZ strings
|
||
RETSKP ;
|
||
|
||
; Come here to return with an invalid or unknown name error.
|
||
;
|
||
MVRHC3: MOVE T1,RHCERR(P3) ;Return with appropriate error code
|
||
RET
|
||
;[7.1120] Table of destination byte pointers
|
||
;
|
||
RHCDST: OWGP. 7,PR.SRN ;Server name
|
||
OWGP. 7,PR.SVN ;Service name
|
||
OWGP. 7,PR.PRN ;Port name
|
||
|
||
|
||
; Table of maximum lengths
|
||
;
|
||
RHCMXL: EXP ML.SRN ;Server name
|
||
EXP ML.SVN ;Service name
|
||
EXP ML.PRN ;Port name
|
||
|
||
|
||
; Table of instructions to save the byte count
|
||
;
|
||
RHCXCT: STOR T3,PRSRC,(P2) ;Server name
|
||
STOR T3,PRSVC,(P2) ;Service name
|
||
STOR T3,PRPRC,(P2) ;Port name
|
||
|
||
|
||
; Table of error codes if the name is invalid
|
||
;
|
||
RHCERR: EXP LATX04 ;Invalid or unknown server name
|
||
EXP LATX07 ;Invalid or unknown service name
|
||
EXP LATX10 ;Invalid or unknown port name
|
||
;[7.1120]
|
||
;PRGET - Get a free PRVECT index number.
|
||
;
|
||
; CALL PRGET
|
||
; Return+1: Failure, insufficient resources
|
||
; Return+2: Success, T1/ PRVECT index number
|
||
|
||
PRGET: MOVSI T3,-PRBITN ;Look for a free PR block index
|
||
IFN FTOPS10,<UUOLOK ;Get the interlock: one user at a time>
|
||
PRGET1: SKIPE T1,PRBITS(T3) ; by examining the free PR block words
|
||
JFFO T1,PRGET2 ; for the first 1 bit. This represents
|
||
AOBJN T3,PRGET1 ; the first free PR block index.
|
||
IFN FTOPS10,<UUONLK ;Give up the interlock>
|
||
RET ;No PR blocks available
|
||
PRGET2: MOVE T1,BITS(T2) ;Clear the bit since the index is
|
||
ANDCAM T1,PRBITS(T3) ; no longer free.
|
||
IFN FTOPS10,<UUONLK ;Give up the interlock>
|
||
HRRZ T1,T3 ;Compute the PR block index,
|
||
IMULI T1,^D36 ; which must be greater than zero.
|
||
ADDI T1,1(T2) ;
|
||
CAILE T1,PRMAXI ;Larger than the maximum?
|
||
RET ;Yes, insufficient resources
|
||
MOVE T3,T1 ;Copy the index number
|
||
ADD T3,PRRAND ;Get address of random number
|
||
AOS T2,(T3) ;Get the next random number
|
||
ANDI T2,PR.RAN ;Perform modulo arithematic
|
||
JUMPG T2,PRGET3 ;Non-zero: use it in the connect id
|
||
AOS (T3) ;Get the next random number
|
||
AOS T2 ;Wrap around to one
|
||
PRGET3: DPB T2,[POINTR (T1,PR%RAN)] ;Fill in the ranom portion
|
||
RETSKP ;
|
||
XRESCD ;[7.1120]
|
||
|
||
;[7.1120]
|
||
;PRREL - Release a PRVECT index number.
|
||
;
|
||
; T1/ PRVECT index number
|
||
; CALL PRREL
|
||
; Return+1: Always
|
||
|
||
PRREL: ANDI T1,PR.NDX ;Throw away the random portion
|
||
JUMPE T1,RTN ;Zero left: return
|
||
MOVE T2,T1 ;Copy the index number
|
||
ADD T2,PRVECT ;Get address of PRVECT entry
|
||
SETZM (T2) ;Clear the address
|
||
SOS T1 ;PRVECT index numbers start with one
|
||
IDIVI T1,^D36 ;Get the PRBITS index and bit number
|
||
MOVE T2,BITS(T2) ;Get a bit to set with
|
||
IORM T2,PRBITS(T1) ;Set the bit to indicate that it is free
|
||
RET ;
|
||
|
||
|
||
;[7.1120]
|
||
;PRDEL - Delete a PRVECT entry.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL PRDEL
|
||
; Return+1: Always
|
||
|
||
PRDEL: SAVEAC <P1> ;
|
||
MOVE P1,T1 ;Save address of pending request block
|
||
OPSTR <SKIPN T1,>,PRSBA,(P1) ;Is there a slot block?
|
||
IFSKP. ;
|
||
BUG. (CHK,LATIPR,LATSER,SOFT,<LAT Invalid PR block>,<<P1,PRBLOK>,<T1,SBBLOK>>,<
|
||
|
||
Cause: A Pending Request block was about to be deleted that still had a
|
||
Slot block attached to it.
|
||
|
||
>)
|
||
ENDIF.
|
||
OPSTR <SKIPE T1,>,PRCID,(P1) ;Is there a PRVECT index number?
|
||
CALL PRREL ;(T1)Yes, release it
|
||
OPSTR <SKIPN T1,>,PRXBA,(P1) ;Is there a transmit buffer?
|
||
IFSKP.
|
||
MOVX T2,DLL.FL ;
|
||
EXCH T2,UNUID+UNB.OF(T1) ;Clear the "Keep me" bit
|
||
TXNN T2,DLL.FL ;Is this buffer inside NI service?
|
||
CALL MMFREE ;(T1)No, release this buffer
|
||
ENDIF.
|
||
MOVE T1,P1 ;
|
||
CALLRET MMFREE ;(T1)Deallocate the slot block
|
||
;[7.1120]
|
||
;FMSIN - Format a Solicit Information message.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL FMSIN
|
||
; Return+1: Failure, T1/ Error code
|
||
; Return+2: Success
|
||
|
||
FMSIN: SAVEAC <P1,P2,P3> ;
|
||
MOVE P1,T1 ;Save address of pending request block
|
||
LOAD P2,PRXBA,(P1) ;Get address of transmit buffer
|
||
SKIPN P3,LAHNDB ;Get address of host node (HN) table
|
||
RETBAD (LATX03) ;Error, LAT is not operational
|
||
SETZ T3, ;Initialize the byte count
|
||
XMOVEI T4,SBF.OF(P2) ;Get address of transmit buffer
|
||
TXO T4,<OWGP. 8,0> ;Make it a global byte pointer
|
||
STOR T4,UNBFA,+UNB.OF(P2) ;Save the byte pointer
|
||
|
||
; Build the fixed portion of the message.
|
||
;
|
||
MOVX T1,MT.SIN_2 ;Message type = Solicit Information
|
||
; (RM bits = 0) protocol format = 0
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,LALPV_10+LAHPV ;Hishest protocol version and
|
||
; lowest procotol version
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,PROECO_10+PROVER;Current protocol version and
|
||
; current protocol ECO level
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,LMRFSI+^D14 ;Data link receive frame size
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
LOAD T1,PRCID,(P1) ;Use PRVECT index number
|
||
; as the solicit identifier
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
LOAD T1,HNCMT,(P3) ;Get the response timer
|
||
IDIVI T1,^D1000 ;[7.xxxx]Convert to seconds
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
|
||
; ..
|
||
; ..
|
||
|
||
LOAD T1,PRSRC,(P1) ;Get the server name count
|
||
XMOVEI T2,PR.SRN(P1) ;Get address of server name string
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
LOAD T1,ACLNG,(P3) ;Get the length of the group code
|
||
XMOVEI T2,AC.COD(P3) ;Get address of group code
|
||
TXO T2,<OWGP. 8,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put it in the string
|
||
LOAD T1,HNNMC,(P3) ;Get the host name count
|
||
XMOVEI T2,HN.NAM(P3) ;Get address of the host name
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
LOAD T1,PRSVC,(P1) ;Get the service name length
|
||
XMOVEI T2,PR.SVN(P1) ;Get address of service name
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
SETZ T1, ;
|
||
IDPB T1,T4 ;No parameters specified
|
||
ADDI T3,1 ;Update the length of the message
|
||
STOR T3,UNBSZ,+UNB.OF(P2) ;Save the length of the message
|
||
DMOVE T1,[BYTE (8) 11,00,53,00,00,17,00,00]
|
||
OPSTRM <DMOVEM T1,>,UNDAD,+UNB.OF(P2) ;Store multicast address
|
||
RETSKP ; (09-00-2B-00-00-0F)
|
||
;[7.1120]
|
||
;FMSAC - Format a Solicit Access message.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL FMSAC
|
||
; Return+1: Failure, T1/ Error code
|
||
; Return+2: Success
|
||
|
||
FMSAC: SAVEAC <P1,P2,P3> ;
|
||
MOVE P1,T1 ;Save address of pending request block
|
||
LOAD P2,PRXBA,(P1) ;Get address of transmit buffer
|
||
SKIPN P3,LAHNDB ;Get address of host node (HN) table
|
||
RETBAD (LATX03) ;Error, LAT is not operational
|
||
SETZ T3, ;Initialize the byte count
|
||
XMOVEI T4,SBF.OF(P2) ;Get address of transmit buffer
|
||
TXO T4,<OWGP. 8,0> ;Make it a global byte pointer
|
||
STOR T4,UNBFA,+UNB.OF(P2) ;Save the byte pointer
|
||
|
||
; Build the fixed portion of the command message.
|
||
;
|
||
MOVX T1,MT.CMD_2 ;Message type = Command Message
|
||
; (RM bits = 0) protocol format = 0
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,LALPV_10+LAHPV ;Highest protocol version and
|
||
; lowest protcol version
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,PROECO_10+PROVER;Current protocol version and
|
||
; current protocol ECO level
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,LMRFSI+^D14 ;Data link receive frame size
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
LOAD T1,PRCID,(P1) ;Use PRVECT index number
|
||
; as the request number
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
SETZ T1,0 ;Entry identifier = 0
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
MOVX T1,1 ;Solicit non-queued access and no status
|
||
OPSTR <SKIPE>,PRQUE,(P1) ;Do we want queued access?
|
||
MOVX T1,2_10+2 ;Solicit queued access and send status
|
||
; every time the queue depth changes
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Fill in the first part of the object information: the server name.
|
||
;
|
||
LOAD T1,PRSRC,(P1) ;Get the server name count
|
||
XMOVEI T2,PR.SRN(P1) ;Get address of server name string
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
|
||
; Fill in the subject information.
|
||
;
|
||
LOAD T1,ACLNG,(P3) ;Get the length of the group code
|
||
XMOVEI T2,AC.COD(P3) ;Get address of group code
|
||
TXO T2,<OWGP. 8,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
LOAD T1,HNNMC,(P3) ;Get the host name count
|
||
XMOVEI T2,HN.NAM(P3) ;Get address of the host name
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
SETZ T1, ;
|
||
IDPB T1,T4 ;There is no subject port name
|
||
IDPB T1,T4 ;There is no subject description name
|
||
ADDI T3,2 ;Update the length of the message
|
||
|
||
; Fill in the object information.
|
||
;
|
||
LOAD T1,PRSVC,(P1) ;Get the service name length
|
||
XMOVEI T2,PR.SVN(P1) ;Get address of service name
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
LOAD T1,PRPRC,(P1) ;Get the port name length
|
||
XMOVEI T2,PR.PRN(P1) ;Get address of port name
|
||
TXO T2,<OWGP. 7,0> ;Make it a global byte pointer
|
||
CALL MVSTC ;(T1-T4/T3,T4)Put string in message
|
||
SETZ T1, ;
|
||
IDPB T1,T4 ;No parameters specified
|
||
ADDI T3,1 ;Update the length of the message
|
||
STOR T3,UNBSZ,+UNB.OF(P2) ;Save the length of the message
|
||
OPSTR <DMOVE T1,>,PRDNI,(P1) ;Use the correct Ethernet address
|
||
OPSTRM <DMOVEM T1,>,UNDAD,+UNB.OF(P2)
|
||
RETSKP ;
|
||
;[7.1120]
|
||
;FMCAN - Change the Solicit Access to a Cancel Entry message.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL FMCAN
|
||
; Return+1: Failure, no entry id
|
||
; Return+2: Success
|
||
|
||
FMCAN: SAVEAC <P1,P2> ;
|
||
MOVE P1,T1 ;Save address of slot block
|
||
OPSTR <SKIPE T1,>,PREID,(P1) ;Is there an entry id?
|
||
OPSTR <SKIPN P2,>,PRXBA,(P1) ;Is there a transmit buffer?
|
||
RET ;No, no Status messages received
|
||
XMOVEI T3,<SBF.OF>(P2) ;[7.1150]Get address of transmit buffer
|
||
TXO T3,<OWGP. 8,0> ;[7.1150]Make it a global byte pointer
|
||
MOVEI T4,MT.EID ;[7.1150]Get the offset to the entry id
|
||
ADJBP T4,T3 ;[7.1150]Point there
|
||
CALL MVBY2 ;(T1,T3,T4/T3,T4)Put entry-id in message
|
||
MOVX T3,3 ;[7.1150]Command type = Cancel
|
||
IDPB T3,T4 ;[7.1150]Put it in the message
|
||
RETSKP ;
|
||
|
||
;[7.1120]
|
||
;MVSTC - Move a counted string (including the byte count).
|
||
;MVSTR - Move a counted string.
|
||
;
|
||
; T1/ Source count
|
||
; T2/ Source byte pointer
|
||
; T3/ Destination count
|
||
; T4/ Destination byte pointer
|
||
; CALL MVSTC or MVSTR
|
||
; Return+1: Always
|
||
; T3/ Destination count
|
||
; T4/ Destination byte pointer
|
||
|
||
MVSTC: IDPB T1,T4 ;Put the byte count in the message
|
||
ADDI T3,1 ;Update the length of the message
|
||
MVSTR: SAVEAC <P1> ;
|
||
MVSTR1: SOJL T1,RTN ;Negative: finished
|
||
ILDB P1,T2 ;Get the next character
|
||
IDPB P1,T4 ;Put it in the message
|
||
AOJA T3,MVSTR1 ;Count this character and continue
|
||
|
||
|
||
;[7.1120]
|
||
;MVBY2 - Move two bytes (LO first).
|
||
;
|
||
; T1/ Source
|
||
; T3/ Destination count
|
||
; T4/ Destination byte pointer
|
||
; CALL MVBY2
|
||
; Return+1: Always
|
||
; T3/ Destination count
|
||
; T4/ Destination byte pointer
|
||
|
||
MVBY2: IDPB T1,T4 ;Save the LO byte first
|
||
LSH T1,-^D8 ;Shift the HO byte into position
|
||
IDPB T1,T4 ;Save the HO byte
|
||
ADDI T3,2 ;Update the byte count
|
||
RET ;
|
||
;[7.1120]
|
||
IFN FTOPS20,<
|
||
RESCD
|
||
LATST:: IDIVI T1,^D36 ;Bit number in T1: Calculate the offset in T1
|
||
MOVE T2,BITS(T2) ; and the bit number in T2.
|
||
TDNE T2,PRWMSK(T1) ;Skip if bit clear
|
||
RET ;Keep sleeping
|
||
RETSKP ;Wake user
|
||
> ;End IFN FTOPS20
|
||
|
||
XRESCD
|
||
|
||
;[7.1120]
|
||
;PRWAIT - Wait for a connection.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL PRWAIT
|
||
; Return+1: Always
|
||
|
||
PRWAIT:
|
||
IFN FTOPS20,<
|
||
LOAD T2,PRSTS,(T1) ;Get the status of the connection
|
||
CAIE T2,.LASOL ;Is it being solicited
|
||
CAIN T2,.LAQUE ; or queued?
|
||
TRNA ;Yes, go ahead.
|
||
RET ;No, return
|
||
LOAD T2,PRCID,(T1) ;Get the connect id
|
||
ANDI T2,PR.NDX ;Just keep the index into PRVECT
|
||
HRL T1,T2 ;Save it for later, LH of T1
|
||
HRRI T1,LATST ;Scheduler test in the right
|
||
UNLOCK HN.LOK(Q2) ;Unlock the database so others can use it
|
||
OKINT ;So we can receive interrupts (and type ^C)
|
||
MDISMS ;Wait...
|
||
NOINT ;We woke up, so go NOINT again
|
||
LOCK HN.LOK(Q2) ;Lock the database again
|
||
RET ;All done...
|
||
|
||
>;END IFN FT0PS20
|
||
|
||
IFN FTOPS10,<
|
||
SAVEAC <J,W,P1> ;
|
||
MOVE P1,T1 ;Save address of pending request block
|
||
PRWAI1: LOAD T1,PRSTS,(P1) ;Get the status of the connection
|
||
CAXE T1,.LASOL ;Is it being solicited
|
||
CAXN T1,.LAQUE ; or queued?
|
||
TRNA ;Yes, continue waiting
|
||
RET ;No, return
|
||
MOVX T1,EV.LAT ;LAT event
|
||
LOAD J,PRJOB,(P1) ;Get the job number
|
||
SNCALL (ESLEEP##,MCSEC0) ;[7.yyyy](T1,J)Go to sleep
|
||
JRST PRWAI1 ;Awake for some reason: check connection
|
||
> ;End IFN FTOPS10
|
||
;[7.1120]
|
||
;PRWAKE - Wake up a job.
|
||
;
|
||
; T1/ Address of pending request block
|
||
; CALL PRWAKE
|
||
; Return+1: Always
|
||
|
||
PRWAKE:
|
||
IFN FTOPS20,<
|
||
OPSTR <SKIPN>,PRWAI,(T1);Waiting for the connection?
|
||
IFSKP.
|
||
LOAD T2,PRCID,(T1) ;Yes, Get the connect id
|
||
ANDI T2,PR.NDX ;Strip off the random part
|
||
IDIVI T2,^D36 ;Calculate offset in T2,
|
||
MOVE T3,BITS(T3) ; mask in T3
|
||
ANDCAM T3,PRWMSK(T2) ;Clear the bit
|
||
ELSE.
|
||
LOAD T2,PRFRK,(T1) ;Get the Fork number
|
||
LOAD T1,PRPSI,(T1) ;Get the PSI channel
|
||
CALLX (MSEC1,PSIRQ) ;(T1,T2/)Interrupt him
|
||
ENDIF.
|
||
RET ;All done
|
||
>;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SAVEAC <J> ;
|
||
OPSTR <SKIPN>,PRWAI,(T1);Wait for the connection?
|
||
IFSKP.
|
||
LOAD T1,PRFRK,(T1) ;Get the JCH
|
||
SNCALL (CTXEWK##,MCSEC1) ;(T1)Wake that job
|
||
JFCL ;
|
||
RET ;
|
||
ENDIF.
|
||
LOAD J,PRFRK,(T1) ;Get the JCH
|
||
SIGNAL C$LAT ;Signal a LAT event
|
||
JFCL ;
|
||
RET ;
|
||
> ;End IFN FTOPS10
|
||
;[7.1120]
|
||
;LATXPR - Transmit Command Messages for pending requests.
|
||
;
|
||
; CALL LATXPR
|
||
; Return+1: Always
|
||
|
||
XRENT (LATXPR,G) ;LATXPR:: XLATXP::
|
||
SAVEAC <P1,P2,P3,P4,Q1,Q2>
|
||
STKVAR <MAXCMC,NXTCMT> ;
|
||
IFN FTOPS20,<
|
||
MOVEI T1,^D1000 ;1000 Milliseconds
|
||
MOVEM T1,LATCMT ;Re-initialize the Command Message Timer
|
||
> ;End IFN FTOPS20
|
||
SKIPN P4,LAHNDB ;Get address of host node (HN) data base
|
||
RET ;None, don't transmit
|
||
LOAD T1,HNLAS,(P4) ;Get the LAT access state
|
||
CAXE T1,LS.ON ;Is it ON?
|
||
RET ;No, don't transmit
|
||
LOAD T1,HNCMX,(P4) ;Get the maximum command message
|
||
MOVEM T1,MAXCMC ; retry count
|
||
MOVE P3,TODCLK ;Get the system uptime
|
||
LOAD T1,HNCMT,(P4) ;Calculate the next time to transmit
|
||
ADD T1,P3 ; a command message
|
||
MOVEM T1,NXTCMT ;
|
||
|
||
; Find a PRVECT entry whose timer has expired.
|
||
;
|
||
MOVX P1,PRMAXI ;Get the number of entires
|
||
MOVE P2,PRVECT ;Get address of PRVECT table (minus one)
|
||
XLATP1: SOJL P1,RTN ;None left, return
|
||
SKIPE Q1,1(P2) ;Is there an entry?
|
||
OPSTR <CAMGE P3,>,PRCMT,(Q1) ;Is it time to transmit?
|
||
AOJA P2,XLATP1 ;No, keep looking
|
||
MOVX T1,DLL.FL ;Get a bit to test with
|
||
OPSTR <SKIPE Q2,>,PRXBA,(Q1) ;Get address of transmit buffer
|
||
OPSTR <TDNE T1,>,UNUID,+UNB.OF(Q2) ;Does DLL still have it?
|
||
AOJA P2,XLATP1 ;Yes, can't touch it at this time
|
||
LOAD T1,PRSTA,(Q1) ;Get the current (internal) state
|
||
AOJA P2,@XMTDSP(T1) ;Increment the PRVECT entry address
|
||
; and take care of this entry
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Table of states for the PRVECT entries
|
||
;
|
||
XMTDSP: XADDR. XLATP2 ;(0) Halt
|
||
XADDR. XLATP2 ;(1) Run
|
||
XADDR. XLATP5 ;(2) Solicit Information
|
||
XADDR. XLATP3 ;(3) Solicit Access (initialize first)
|
||
XADDR. XLATP5 ;(4) Solicit Access
|
||
XADDR. XLATP2 ;(5) Queued
|
||
XADDR. XLATP2 ;(6) Rejected
|
||
XADDR. XLATP2 ;(7) Timed Out
|
||
XADDR. XLATP4 ;(8) Cancel (initialize first)
|
||
XADDR. XLATP5 ;(9) Cancel
|
||
XMTMAX==.-XMTDSP-1
|
||
IF1,<IFL <XMTMAX-SS.MAX>,<PRINTX ?Entries missing in XMTDSP>>
|
||
|
||
; Come here to set the retransmit timer to infinity so that this routine
|
||
; will never bother with this PRVECT entry again.
|
||
;
|
||
XLATP2: HRLOI T1,377777 ;Make the retransmit timer so large
|
||
STOR T1,PRCMT,(Q1) ; we will never go through here again
|
||
SETZRO PRCMC,(Q1) ;
|
||
JRST XLATP1 ;Find another PRVECT entry
|
||
|
||
; Come here to set up the Solicit Access message.
|
||
;
|
||
XLATP3: MOVE T1,Q1 ;Get address of pending request block
|
||
CALL FMSAC ;(T1)Format a Solicit Access message
|
||
JRST XLATP1 ;Error, try again later
|
||
MOVX T1,SS.SAC ;Change state to Solicit Access
|
||
STOR T1,PRSTA,(Q1) ;
|
||
JRST @XMTDSP(T1) ;
|
||
|
||
; Come here to set up the Cancel Message.
|
||
;
|
||
XLATP4: MOVE T1,Q1 ;Get address of pending request block
|
||
CALL FMCAN ;(T1)Format a Cancel message
|
||
JRST XLTIMO ;Error, remove this slot block
|
||
MOVX T1,SS.CAN ;Change state to Cancel
|
||
STOR T1,PRSTA,(Q1) ;
|
||
JRST @XMTDSP(T1) ;
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Come here to transmit a message.
|
||
;
|
||
XLATP5: OPSTRM <AOS T1,>,PRCMC,(Q1) ;Increment the retry count
|
||
CAMLE T1,MAXCMC ;Have we retried too many times?
|
||
JRST XLTIMO ;Yes, we have timed out
|
||
MOVE T1,NXTCMT ;Reset the command message timer
|
||
STOR T1,PRCMT,(Q1) ;
|
||
LOAD T1,HNPID,(P4) ;Save the PID
|
||
STOR T1,UNPID,+UNB.OF(Q2)
|
||
STOR Q2,UNRID,+UNB.OF(Q2) ;Save buffer address
|
||
MOVX T1,SAV.FL ;Keep this buffer
|
||
STOR T1,UNUID,+UNB.OF(Q2)
|
||
MOVX T1,UNA.EV ;Use EXEC virtual memory
|
||
STOR T1,UNADS,+UNB.OF(Q2)
|
||
MOVX T1,NU.XMT ;Function = transmit
|
||
XMOVEI T2,UNB.OF(Q2) ;Address of UN block
|
||
IFN FTOPS20,<CALL DLLUNI## ;Call NI service>
|
||
IFN FTOPS10,<SNCALL (DLLUNI##,MCSEC1) ;Call NI service>
|
||
TRN ;Ignore error
|
||
JRST XLATP1 ;Look for another PRVECT entry
|
||
|
||
; Come when we have timed out.
|
||
;
|
||
XLTIMO: LOAD T1,PRSTA,(Q1) ;Get the current (internal) state
|
||
CAXE T1,SS.CAI ;
|
||
CAXN T1,SS.CAN ;Was this request cancelled?
|
||
TRNA ;Yes, delete the PRVECT entry
|
||
IFSKP.
|
||
MOVE T1,Q1 ;Get the address of the slot block
|
||
CALL PRDEL ;Delete the PRVECT entry
|
||
JRST XLATP1 ;Find another PRVECT entry
|
||
ENDIF.
|
||
MOVX T1,SS.TMO ;Change state to Timed Out
|
||
STOR T1,PRSTA,(Q1) ;
|
||
MOVX T1,.LATMO ;
|
||
STOR T1,PRSTS,(Q1) ;
|
||
MOVE T1,Q1 ;Get address of pending request block
|
||
CALL PRWAKE ;(T1)Wake the user's job
|
||
JRST @XMTDSP+SS.TMO ;Make the retransmit timer so large
|
||
; we will never go through here again
|
||
SUBTTL LATOP% JSYS -- Terminate Host-Initiated Connects
|
||
|
||
|
||
XSWAPCD ;[7.1120]
|
||
|
||
;[7.1120]
|
||
;LATHC - Terminate host-initiated connects.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LATHC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LATHC: UMOVE T2,.LAPRM(Q1) ;Get the connect id and flags
|
||
IFN FTOPS20,<
|
||
MOVE T1,FORKX ;Get the current fork number
|
||
> ; End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVE T1,.CPJCH## ;Get the current job number/context
|
||
>; End IFN FTOPS10
|
||
TXNN T2,LA%JOB ;Terminate all server connects for the job?
|
||
IFSKP.
|
||
CALL JBTHC ;(T1)Terminate all pending connects
|
||
RETBAD () ;Uh oh... Open files!
|
||
RETSKP ; for the current fork
|
||
ENDIF.
|
||
HRRZ T3,T2 ;Get the connect id
|
||
ANDI T2,PR.NDX ;Throw away the random portion
|
||
SKIPLE T2 ;Less than or equal to zero
|
||
CAILE T2,PRMAXI ; or greater than the maximum?
|
||
RETBAD (LATX11) ;Yes, invalid or unknown connect id
|
||
ADD T2,PRVECT ;Calculate address of PRVECT entry
|
||
SKIPN T2,(T2) ;Is this entry in use?
|
||
RETBAD (LATX11) ;No, invalid or unknown connect id
|
||
OPSTR <CAME T3,>,PRCID,(T2) ;Is this the RIGHT connect id?
|
||
RETBAD (LATX11) ;No, invalid or unknown connect id
|
||
OPSTR <CAME T1,>,PRFRK,(T2) ;Does this job own the connection?
|
||
RETBAD (LATX11) ;No, invalid or unknown connect id
|
||
IFN FTOPS20,<
|
||
LOAD T1,PRSTS,(T2) ;Get the status
|
||
TRZN T1,.TTDES ;Is this a TTY designator?
|
||
IFSKP. ;Yes, so...
|
||
ADDI T1,DVXTT0 ;Point into the device tables
|
||
MOVX T3,DV%OPN ;Get the open flag?
|
||
TDNE T3,DEVCHR(T1) ;Is there an open file on this device?
|
||
RETBAD (DEVX6) ;Yes!
|
||
ENDIF.
|
||
> ;End IFN FTOPS20
|
||
MOVE T1,T2 ;Get address of pending request block
|
||
CALL PRCAN ;(T1)Cancel this pending request
|
||
RETSKP ;
|
||
;[7.1120]
|
||
;LATRST - This routine is called each time TOPS-10 does a RESET UUO.
|
||
; The TOPS-20 version is called from KSELF.
|
||
; Give up all of the server connections for the specified job.
|
||
;
|
||
; T1/ Fork number (TOPS-20)
|
||
; J/ Job number (JCH) (TOPS-10)
|
||
; CALL LATRST
|
||
; Return+1: Always
|
||
|
||
IFN FTOPS20,<
|
||
XRENT (LATRST,G) ;LATRST::,XLATRS:
|
||
SAVEAC <Q1> ;
|
||
SKIPN Q1,LAHNDB ;Do we have lat?
|
||
RET ;no
|
||
NOINT ;No more interruptions
|
||
LOCK HN.LOK(Q1) ;Lock the database
|
||
CALL JBTHC ;Release reverse lat resources
|
||
NOP ;Don't care
|
||
UNLOCK HN.LOK(Q1) ;Let others have the database
|
||
OKINT ;I'm not busy any more
|
||
RET ;All done
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
RESCD
|
||
LATPSI::SETZ T2, ;Dummy PSI callback routine
|
||
RET
|
||
LATRST::MOVE T1,.CPJCH ;Get the JCH
|
||
SE1ENT ;Return in section 1
|
||
IFN FTXMON,<
|
||
XJRST [JBTHC] ;Do the rest in section 2
|
||
XRESCD
|
||
> ;End IFN FTXMON
|
||
> ;End IFN FTOPS10
|
||
|
||
;[7.1120]
|
||
;JBTHC - Terminate all of the host-initiated connects for a specified job.
|
||
;Note: To be called NOINT with the database locked.
|
||
; T1/ Fork number
|
||
; CALL JBTHC
|
||
; Return+1: At least one device has an open file, and hasn't been terminated
|
||
; Return+2: All connections terminated
|
||
|
||
JBTHC: SAVEAC <P1,P2,P3> ;
|
||
STKVAR <OPFLG> ;"Device is open" Flag
|
||
MOVX P1,PRMAXI ;Get the length of the PRVECT table
|
||
MOVE P2,PRVECT ;Get the address of the PRVECT table
|
||
MOVE P3,T1 ;Copy the fork number
|
||
SETZM OPFLG ;Clear Error flag
|
||
JBTHC1: SOJL P1,JBTHC3 ;Negative: no more PRVECT entries
|
||
SKIPN T1,1(P2) ;Is this table entry in use?
|
||
AOJA P2,JBTHC1 ;No, keep looking
|
||
LOAD T2,PRFRK,(T1) ;Get the fork number for this connection
|
||
CAME T2,P3 ;Do the fork numbers match?
|
||
AOJA P2,JBTHC1 ;Keep looking
|
||
IFN FTOPS20,<
|
||
LOAD T2,PRSTS,(T1) ;Get the status
|
||
TRZN T2,.TTDES ;Is this a TTY designator?
|
||
IFSKP. ;Yes, so...
|
||
ADDI T2,DVXTT0 ;Point into the device tables
|
||
MOVX T3,DV%OPN ;Get the open flag?
|
||
TDNN T3,DEVCHR(T2) ;Is there an open file on this device?
|
||
JRST JBTHC2 ;No, go cancel it
|
||
SETOM OPFLG ;Yes, set the flag
|
||
AOJA P2,JBTHC1 ;and keep looking...
|
||
ENDIF. ;
|
||
> ;End IFN FTOPS20
|
||
JBTHC2: CALL PRCAN ;Cancel this connection
|
||
AOJA P2,JBTHC1 ;Keep going
|
||
JBTHC3:
|
||
IFN FTOPS20,<
|
||
SKIPE OPFLG ;Any errors?
|
||
RETBAD (DEVX6) ;Yes
|
||
> ;End IFN FTOPS20
|
||
RETSKP ;No, all is well...
|
||
ENDSV. ;
|
||
|
||
;PRCAN - Cancel a pending request.
|
||
;[7.1120]
|
||
; T1/ Address of pending request block
|
||
; CALL PRCAN
|
||
; Return+1: Always
|
||
|
||
PRCAN: LOAD T3,PRSTA,(T1) ;Get the current (internal) state
|
||
CALLRET @CANDSP(T3) ;Change state to Cancel or hang up
|
||
|
||
PRCAN1: MOVX T2,SS.CAI ;
|
||
STOR T2,PRSTA,(T1) ;Change to Cancel state
|
||
MOVX T2,.LACAN ; (initialize first)
|
||
STOR T2,PRSTS,(T1) ;
|
||
SETZRO PRCMC,(T1) ;Clear the retransmit timer so that
|
||
SETZRO PRCMT,(T1) ; LATXPR will start right away
|
||
RET ;Return
|
||
|
||
PRCAN2: LOAD T2,PRSBA,(T1) ;Get address of slot block
|
||
JUMPE T2,@CANDSP+SS.SAC ;None: treat it as still soliciting
|
||
IFN FTOPS20,<
|
||
LOAD T2,PRSTS,(T1) ;Get the TTY designator
|
||
TXZN T2,.TTDES ;Do we have one?
|
||
JRST @CANDSP+SS.SAC ;No
|
||
SAVEAC <Q1,Q2,P1,P2,P3,P4,P5>
|
||
CALLRET LTHNGU ;(T2)Yes, hang up the line.
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
SAVEAC <W,M,P1,P2,P3,P4,J>
|
||
LOAD U,SBTDB,(T2) ;Get the LDB address
|
||
JUMPE U,@CANDSP+SS.SAC ;[7.xxxx]None: treat it as still soliciting
|
||
CALL LTHNGU ;[7.xxxx](U)Got it: hang up the line
|
||
NOP ;[7.xxxx]Oh well, we tried
|
||
RET ;[7.xxxx]
|
||
> ;End IFN FTOPS10
|
||
CALLRET @CANDSP+SS.SAC ;None: treat it as still soliciting
|
||
|
||
; Table of states for the PRVECT entries
|
||
;
|
||
CANDSP: XADDR. PRCAN2 ;(0) Halt
|
||
XADDR. PRCAN2 ;(1) Run
|
||
XADDR. PRCAN1 ;(2) Solicit Information
|
||
XADDR. PRCAN1 ;(3) Solicit Access (initialize first)
|
||
XADDR. PRCAN1 ;(4) Solicit Access
|
||
XADDR. PRCAN1 ;(5) Queued
|
||
XADDR. PRDEL ;(6) Rejected
|
||
XADDR. PRDEL ;(7) Timed out
|
||
XADDR. PRCAN1 ;(8) Cancel (initialize first)
|
||
XADDR. PRCAN1 ;(9) Cancel
|
||
CANMAX==.-CANDSP-1
|
||
IF1,<IFL <CANMAX-SS.MAX>,<PRINTX ?Entries missing in CANDSP>>
|
||
SUBTTL LATOP% JSYS -- Show Host-Initiated Connects
|
||
|
||
|
||
XSWAPCD ;[7.1120]
|
||
|
||
;[7.1120]
|
||
;LASHC - Show host-initiated connects.
|
||
;
|
||
; Q1/ User argument block address
|
||
; Q2/ LAT host node data base address
|
||
; P1/ Length of user argument block
|
||
; P2/ LAT function code
|
||
; CALL LASHC
|
||
; Return+1: Failure, T1/ error code
|
||
; Return+2: Success
|
||
|
||
LASHC: XCTU [HRRZ P3,.LABCT(Q1)] ;Get the length of the show buffer
|
||
UMOVE T3,.LABFA(Q1) ;Get address of show buffer
|
||
UMOVE T1,.LAQUA(Q1) ;Get the flags,,connect id
|
||
IDIVI P3,MW.SHC ;Calculate the maximum number
|
||
; of connections that will fit there
|
||
SETO P4, ;Use job number minus one (for the search)
|
||
TXNE T1,LA%SYS ;Show all server connects on the system?
|
||
JRST LASHC1 ;Yes, start the search
|
||
TXNN T1,LA%JOB ;Show all server connects for this job?
|
||
IFSKP.
|
||
IFN FTOPS20,<
|
||
MOVE P4,JOBNO ;Get the current job number
|
||
> ;End IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVE P4,.CPJOB## ;Get the current job number
|
||
> ;End IFN FTOPS10
|
||
JRST LASHC1 ;Find the connections for this job
|
||
ENDIF.
|
||
|
||
; Come here to return the status of a paritcular server connection.
|
||
;
|
||
LDB T4,[POINTR (T1,LA%CID)] ;Get the connect id
|
||
ANDI T4,PR.NDX ;Throw away the random portion
|
||
SKIPLE T4 ;Less than or equal to zero
|
||
CAILE T4,PRMAXI ; or greater than the maximum?
|
||
RETBAD (LATX11) ;Yes, invalid or unknown connect id
|
||
ADD T4,PRVECT ;Calculate address of PRVECT entry
|
||
SKIPN T4,(T4) ;Is this entry in use?
|
||
RETBAD (LATX11) ;No, invalid or unknown connect id
|
||
MOVX T1,MW.SHC ;Save the number of words needed
|
||
XCTU [HRLM T1,.LABCT(Q1)]
|
||
SOSGE P3 ;Is the show buffer large enough?
|
||
RETBAD (ARGX04) ;No, argument block too small
|
||
CALL MVSHC ;(T2,T4/T2)Move the Status block
|
||
RETSKP ;
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Find the all server connections (P4=minus one) or all those for a user
|
||
; job (P4=n).
|
||
;
|
||
LASHC1: MOVX P1,PRMAXI ;Get the length of the PRVECT table
|
||
MOVE P2,PRVECT ;Get the address of the PRVECT table
|
||
LASHC2: SOJL P1,LASHC4 ;Negative: no more PRVECT entries
|
||
ADDI P2,1 ;Increment the address of the entry
|
||
SKIPN T4,(P2) ;Is this table entry in use?
|
||
JRST LASHC2 ;No, keep looking
|
||
JUMPL P4,LASHC3 ;Minus one: take all server connections
|
||
LOAD T1,PRJOB,(T4) ;Get the job number for this connection
|
||
CAME T1,P4 ;Do the job numbers match?
|
||
JRST LASHC2 ;No, keep looking
|
||
LASHC3: SOJL P3,LASHC2 ;Negative: avoid overflowing the buffer
|
||
CALL MVSHC ;(T2,T4/T2)Move the Status block
|
||
JRST LASHC2 ;Find all of the server connections
|
||
|
||
; Return the number of words needed in the show buffer.
|
||
;
|
||
LASHC4: XCTU [SUB T3,.LABFA(Q1)] ;Calculate the number of words written
|
||
JUMPL P3,LASHC5 ;Negative: show buffer is too small
|
||
XCTU [HRLM T3,.LABCT(Q1)] ;Save the number of words written
|
||
RETSKP ;
|
||
LASHC5: MOVMS P3 ;Calculate the additional number
|
||
IMULI P3,MW.SHC ; of words needed
|
||
ADD T3,P3 ;Calculate the total amount needed
|
||
XCTU [HRLM T3,.LABCT(Q1)] ;Save the number of words needed
|
||
RETBAD (LATX04) ;Argument block too small
|
||
;[7.1120]
|
||
;MVSHC - Move the status information for LASHC.
|
||
;
|
||
; T3/ Destination in user address space
|
||
; T4/ Address of pending request block
|
||
; CALL MVSHC
|
||
; Return+1: Always, T3/ Address of next word to write
|
||
|
||
MVSHC: LOAD T2,PRJOB,(T4) ;Get the job number
|
||
LOAD T1,PRCID,(T4) ;Get the connect id
|
||
HRL T1,T2 ;Get job number,,connect id
|
||
UMOVEM T1,(T3) ;Put it in the show buffer
|
||
LOAD T2,PRSTS,(T4) ;Get the status of the connection
|
||
LOAD T1,PRQDP,(T4) ;Get the queue depth
|
||
HRL T1,T2 ;Get status,,queue depth
|
||
UMOVEM T1,1(T3) ;Put it in the show buffer
|
||
LOAD T2,PRSRC,(T4) ;Get the server name count
|
||
LOAD T1,PRPRC,(T4) ;Get the port name count
|
||
HRL T1,T2 ;Get server name count,,port name count
|
||
UMOVEM T1,2(T3) ;Put it in the show buffer
|
||
ADDI T3,3 ;Update the destination address
|
||
MOVEI T1,<ML.SRN+4>/5 ;Get the maximum length of the name
|
||
XMOVEI T2,PR.SRN(T4) ;Get the address of server name
|
||
XBLTXU T1 ;Copy the name into user space
|
||
MOVEI T1,<ML.PRN+4>/5 ;Get the maximum length of the name
|
||
XMOVEI T2,PR.PRN(T4) ;Get the address of the port name
|
||
XBLTXU T1 ;Copy the name into user space
|
||
LOAD T1,PRSVC,(T4) ;Get the service name count
|
||
HRLZ T1,T1 ;Get the service name count,,0
|
||
UMOVEM T1,(T3) ;Put it in the show buffer
|
||
ADDI T3,1 ;Update the destination address
|
||
MOVEI T1,<ML.SVN+4>/5 ;Get the maximum length of the name
|
||
XMOVEI T2,PR.SVN(T4) ;Get the address of the service name
|
||
XBLTXU T1 ;Copy the name into user space
|
||
RET ;
|
||
SUBTTL LATOP% JSYS -- Utility Routines -- FNDSRV
|
||
|
||
;FNDSRV - find the service block requested by the user based on the
|
||
; service name provided.
|
||
|
||
;Call: no arguments
|
||
;Return:
|
||
; RET - error
|
||
; RETSKP - success, T1/ address of service block
|
||
|
||
FNDSRV: SAVEAC <P1,P2>
|
||
MOVEI T1,TMPLNG-1 ;Zero the storage for assembling user's
|
||
XMOVEI T2,TMPBLK ; service name.
|
||
XMOVEI T3,TMPBLK+1 ; ...
|
||
SETZM TMPBLK ; ...
|
||
XBLT. T1 ; ...
|
||
|
||
;Get the Service Name string from the user and put it into the service
|
||
;block build area.
|
||
;
|
||
UMOVE T1,.LABFA(Q1) ;Pointer to user's service name string
|
||
IFN FTOPS10,<
|
||
SNCALL (CKSTR##,MCSEC1) ;Check to see if ASCIZ string is addressable
|
||
RETBAD (LATXAC) ;Nope, lose
|
||
>;end ifn FTOPS10
|
||
IFN FTOPS20,<
|
||
CALL MAKPTR ;(T1/T1)Make a valid ASCIZ pointer
|
||
>
|
||
XMOVEI T2,TMPGB+GB.NAM ;Pointer of where to put it
|
||
TXO T2,<OWGP. 7,0> ; ...
|
||
MOVEI T3,<ML.SVN+4/5> ;[7.1120]Maximum length
|
||
CALL UMVAZS ;(T1-T3/T3)Move the string to exec space
|
||
RETBAD (LATX07) ;Service name too long
|
||
STOR T3,GBNC,+TMPGB ;Store the count of service name from user
|
||
|
||
;Loop through all service blocks looking for a name match.
|
||
;
|
||
XMOVEI P2,HN.SRV(Q2) ;Address of start of service blocks
|
||
OPSTR <SKIPN P1,>,HNNSV,(Q2);Number of currently defined services
|
||
JRST FSFALS ;There are none defined.
|
||
DO.
|
||
XMOVEI T1,GB.NAM(P2) ;Address of service block's service name
|
||
TXO T1,<OWGP. 7,0>
|
||
LOAD T2,GBNC,(P2) ;Count of service block's service name
|
||
XMOVEI T3,TMPGB+GB.NAM;Address of user's service name
|
||
TXO T3,<OWGP. 7,0>
|
||
LOAD T4,GBNC,+TMPGB ;Count of user's service name
|
||
CALL SCMPAR ;Compare the strings
|
||
IFSKP. ;MATCH FOUND
|
||
MOVEI T1,.LASET ;If a SET...
|
||
XCTU [CAME T1,.LAFCN(Q1)]
|
||
IFSKP.
|
||
MOVEI T1,GB.LEN ; then copy entire service block to the
|
||
XMOVEI T2,(P2) ; temporary block so that new values
|
||
XMOVEI T3,TMPGB ; overlay the old.
|
||
XBLT. T1
|
||
ENDIF.
|
||
MOVE T1,P2 ;In both cases (SET/CLEAR) return service
|
||
RETSKP ; block address.
|
||
ENDIF.
|
||
ADDI P2,GB.LEN ;No match here so
|
||
SOJG P1,TOP. ; advance to next service block
|
||
ENDDO.
|
||
|
||
;Service block not found. If function is SET, see if there is room for
|
||
;a new service. If function is CLEAR, nothing further required.
|
||
;
|
||
FSFALS: MOVEI T1,.LASET ;If service name not found and the function
|
||
XCTU [CAME T1,.LAFCN(Q1)]; request is not a SET,
|
||
RETBAD (LATX07) ; then return an error. Otherwise,
|
||
XMOVEI T1,<GB.LEN*MXHSRV+HN.SRV>(Q2); get end of service block address
|
||
CAML P2,T1 ; and compare with first free block address
|
||
RETBAD (LATX08) ;There is no room for new service.
|
||
SETOM TMPBLK ;There is room. Flag to increment # services.
|
||
MOVE T1,P2 ;Return service block address for new entry.
|
||
RETSKP
|
||
|
||
SUBTTL LATOP% JSYS -- Utility Routines -- GTSRVR
|
||
|
||
;GTSRVR - Routine to get the circuit block address for a particular
|
||
; server based on server name.
|
||
;
|
||
;CALL: T1/ Pointer to server name supplied by user
|
||
; Q2/ LAT host node data base address
|
||
;RET - Error, no circuit block with the requested server name
|
||
;RETSKP Success,
|
||
; T1/ Circuit block address for requested server
|
||
|
||
GTSRVR: SAVEAC Q1 ;Get an AC for circuit block address.
|
||
MOVX T2,<POINT 7,TMPBLK>;Pointer to where to move name string.
|
||
MOVEI T3,ML.DSC ;Maximum server name string length.
|
||
CALL UMVAZS ;(T1-T3/T3)Move the ASCIZ string.
|
||
RETBAD (LATX04)
|
||
MOVX T1,<POINT 7,TMPBLK>;Pointer to user's name string in local storage
|
||
MOVE T2,T3 ;Length of the user's name string.
|
||
LOAD Q1,HNQAC,(Q2) ;Get first CB on active queue
|
||
CALL GCBNAM ;See if desired server there
|
||
IFSKP.
|
||
MOVE T1,Q1 ;Return the CB address on successful
|
||
RETSKP ; match.
|
||
ENDIF.
|
||
LOAD Q1,HNQIC,(Q2) ;Get first CB on inactive queue
|
||
CALL GCBNAM
|
||
IFSKP.
|
||
MOVE T1,Q1 ;Return the CB address on successful
|
||
RETSKP ; match.
|
||
ENDIF.
|
||
RETBAD (LATX04) ;Not anywhere, return error.
|
||
|
||
;GCBNUM - searches a particular queue of circuit blocks looking for a match
|
||
; on the server name.
|
||
|
||
GCBNAM: SAVEAC <T1,T2> ;Preserve string pointer and count.
|
||
JUMPE Q1,RTN ;No more circuit blocks on this queue
|
||
DO.
|
||
XMOVEI T3,CB.SNM(Q1) ;Address of server name
|
||
TXO T3,<OWGP. 7,0> ;Make a pointer
|
||
LOAD T4,CBRSC,(Q1) ;Count in name
|
||
CALL SCMPAR ;(T1-T4)Do the compare
|
||
SKIPA ;No match
|
||
RETSKP ;Match
|
||
OPSTR <SKIPN Q1,>,QLFWD,+CB.LNK(Q1)
|
||
RET ;No match for any CBs on queue.
|
||
JRST TOP. ;Try next CB.
|
||
ENDDO.
|
||
SUBTTL LATOP% JSYS -- Utility Routines -- SCMPAR String Compare
|
||
|
||
;SCMPAR - String Compare
|
||
|
||
;Call: T1/ First string byte pointer
|
||
; T2/ First string count
|
||
; T3/ Second string byte pointer
|
||
; T4/ Second string count
|
||
;RET Mismatch
|
||
;RETSKP Match
|
||
|
||
SCMPAR: SAVEAC <T1,T2,T3,T4> ;Preserve the byte pointers.
|
||
STKVAR <PTR1,PTR2>
|
||
CAME T2,T4 ;If lengths don't match then obviously
|
||
RET ; the strings don't either.
|
||
MOVEM T1,PTR1 ;Save the byte pointers
|
||
MOVEM T3,PTR2 ; to the strings.
|
||
DO.
|
||
ILDB T1,PTR1 ;Get next character from
|
||
ILDB T2,PTR2 ; each string.
|
||
CALL UPPERC ;(T1/T1)Uppercase one.
|
||
EXCH T1,T2
|
||
CALL UPPERC ;(T1/T1)Uppercase the other.
|
||
CAME T1,T2 ;Compare the result.
|
||
RET ;Different so return failure.
|
||
SOJG T4,TOP. ;Match, so continue with the next.
|
||
ENDDO.
|
||
RETSKP ;Full match, return success.
|
||
|
||
ENDSV.
|
||
|
||
;UPPERC - Uppercase a character
|
||
|
||
;Call: T1/ Character
|
||
;RET Always with T1/ uppercased character
|
||
|
||
UPPERC: CAIL T1,"a"
|
||
CAILE T1,"z"
|
||
SKIPA
|
||
SUBI T1,40
|
||
RET
|
||
;UBFCHK - Routine to check if user supplied buffer large enough
|
||
;This routine added by 7.1039. It supercedes LABFCK.
|
||
; Call:
|
||
; T1/ Minimum size required of user buffer
|
||
; Q1/ User's argument block address
|
||
; Return:
|
||
; RET ;Too small (LATX01 in T1)
|
||
; RETSKP ;Large enough
|
||
|
||
UBFCHK: XCTU [HRLM T1,.LABCT(Q1)] ;Tell user
|
||
XCTU [HRRZ T2,.LABCT(Q1)] ;Get his buffer count.
|
||
CAMGE T2,T1 ;Has user allocated large enough buffer?
|
||
RETBAD (LATX01) ;No
|
||
RETSKP ;Yes
|
||
|
||
|
||
;MAKPTR- Make a valid ASCIZ pointer if not already
|
||
;
|
||
IFN FTOPS20,<
|
||
MAKPTR: MOVE T2,T1 ;Make a proper pointer in case the user
|
||
TLC T2,-1 ; supplied one of the form
|
||
TLCN T2,-1 ; -1,,address
|
||
HRLI T1,440700 ; ...
|
||
RET
|
||
> ;End IFN FTOPS20
|
||
|
||
;[7.1039] Routine LABFCK was here...
|
||
|
||
|
||
; Last thing in LATOP. UUO code
|
||
;
|
||
IFN FTOPS10,<
|
||
PURGE Q1,Q2 ;undefine TOPS-20 ACs
|
||
> ;End IFN FTOPS10
|
||
SUBTTL TOPS-10 -- SCNSER Interface -- LDBISR Dispatch
|
||
|
||
|
||
RESCD
|
||
|
||
IFN FTOPS10,<
|
||
|
||
LATDSP::RET ;( 0)ILLEGAL NOW. DON'T USE!!
|
||
RET ;( 1)MODEM CONTROL
|
||
XJRST [LATSEC] ;( 2)ONCE A SECOND CALL (NOT PER TTY)
|
||
RET ;( 3)INITIALIZE
|
||
JRST SETCHP## ;( 4)CHANGE HARDWARE PARMS (let SCNSER do it)
|
||
RET ;( 5)LINE PARM CONTROL
|
||
RET ;( 6)SET TERMINAL ELEMENT
|
||
XJRST [LATREM] ;( 7)STUFF FOR REMOTE TERMINALS
|
||
RETSKP ;(10)IS LINE DEFINED ON STATION (YES)
|
||
|
||
> ;End IFN FTOPS10
|
||
SUBTTL TOPS-10 -- NETOP. Functions
|
||
|
||
|
||
;NETDIL - tell user the node and port where his TTY is connected
|
||
;
|
||
;Call: (in section 1 already)
|
||
;
|
||
; U/ LDB of LAT terminal
|
||
; M/ Address of user's NETOP. arg list
|
||
;Return:
|
||
; ECDX? depending on error
|
||
; RETSKP node name stored in string block pointed to by user's arg list
|
||
;
|
||
;Uses P1,P2 (already saved by higher routine), T1-T4, M
|
||
|
||
SWAPCD
|
||
|
||
IFN FTOPS10,<
|
||
|
||
NETDIL::MOVE P1,M ;SAVE ADDRESS OF ARG LIST
|
||
EXCTUX <SKIPN M,5(P1)> ;POINT TO NODE NAME STRING BLOCK
|
||
JRST NTDIL1 ;NO STRING BLOCK FOR NAME
|
||
CALL CHKSTB## ;CHECK STRING BLOCK FOR ADDRESSABILITY
|
||
JRST NOPADC## ;ADDRESS CHECK
|
||
MOVE T3,LDBLAT##(U) ;GET ADDRESS OF SB BLOCK
|
||
MOVE T3,SB.CBA(T3) ;GET ADDRESS OF CORRESPONDING CB BLOCK
|
||
LOAD T1,CBRSC,(T3) ;GET BYTE COUNT FOR NAME
|
||
XMOVEI T3,CB.SNM(T3) ;GET ADDRESS OF NODE NAME
|
||
CALL MOV7T8 ;MOVE THE STRING
|
||
JRST NOPADC## ;NOT ENOUGH ROOM
|
||
NTDIL1: EXCTUX <SKIPN M,6(P1)> ;POINT TO PORT NAME STRING BLOCK
|
||
RETSKP ;BELIEVE IT OR NOT, WE'RE DONE
|
||
CALL CHKSTB## ;CHECK THE STRING BLOCK
|
||
JRST NOPADC## ;NOT THERE
|
||
MOVE T3,LDBLAT##(U) ;GET ADDRESS OF SB BLOCK AGAIN
|
||
LOAD T1,SBPRC,(T3) ;GET BYTE COUNT OF PORT NAME
|
||
JUMPE T1,RSKP ;Nothing to store
|
||
XMOVEI T3,SB.PRN(T3) ;GET ADDRESS OF PORT NAME
|
||
CALL MOV7T8 ;(M,T1,T2,T3)
|
||
JRST NOPADC## ;NOT ENOUGH ROOM
|
||
RETSKP
|
||
> ;End IFN FTOPS10
|
||
;MOV7T8 - Move a 7-bit monitor string to an 8-bit user string.
|
||
;
|
||
; M/ Address of string block
|
||
; T1/ Count of source string
|
||
; T3/ Address of source string
|
||
; T4/ Count of destination string
|
||
; CALL MOV7T8
|
||
; Return+1: Failure, address check
|
||
; Return+2: Success
|
||
|
||
IFN FTOPS10,<
|
||
MOV7T8:
|
||
IFN FTXMON,<
|
||
CALL SSPCS## ;PRESERVE PCS FOR CALLER
|
||
>
|
||
PUSH P,T1 ;SAVE COUNT FOR A BIT
|
||
MOVE T1,M ;COPY POINTER TO STRING BLOCK
|
||
CALL SXPCS## ;SETUP PCS
|
||
JRST TPOPJ## ;I THOUGHT WE KNEW IT WOULD FIT?
|
||
POP P,T1 ;RESTORE BYTE COUNT
|
||
EXCTXU <HRLM T1,(M)> ;STUFF BYTE COUNT INTO STRING BLOCK
|
||
CAILE T1,(T4) ;ENOUGH SPACE TO STORE?
|
||
RET ;NO
|
||
MOVSI T2,(<POINT 7,>!1B12) ;MAKE GLOBAL BYTE POINTER
|
||
PUSH P,T4+1 ;SAVE A COUPLE OF ACS
|
||
PUSH P,T4+2 ; T1 HAD BETTER BE LESS THAN 12
|
||
MOVSI T4+1,(<POINT 8,>!1B12)
|
||
EXCTUX <XMOVEI T4+2,1(M)> ;GLOBAL ADDRESS OF DEST.
|
||
PXCT 11,[EXTEND T1,[MOVSLJ
|
||
0]] ;MOVE THE BYTES (I HOPE)
|
||
JFCL
|
||
POP P,T4+2
|
||
POP P,T4+1
|
||
RETSKP
|
||
> ;End IFN FTOPS10
|
||
SUBTTL LATINI - LAT Initialization
|
||
|
||
XRESCD ;[7.1024]
|
||
|
||
;LATINI - LAT Initialization
|
||
;
|
||
;Call: CALL LATINI
|
||
; Error return - resource failure
|
||
; Normal Return
|
||
|
||
ENTRY LATINI ;Kepp LINK happy in library search mode
|
||
|
||
XRENT (LATINI,G) ;[7.1024]LATINI::, XLATIN::
|
||
|
||
ACVAR <HN,XB,W1,W2> ;Reserve AC for Host Node data base address
|
||
|
||
IFN FTOPS10,<
|
||
PUSHJ P,LAGTCR ;[7.xxxx]Get size of LAT freecore needed
|
||
IFE FTXMON,<
|
||
PUSHJ P,INICOR## ;[7.xxxx]Allocate core
|
||
MOVEM T2,LATLOC ;[7.xxxx]Save starting address
|
||
> ;End IFE FTXMON
|
||
IFN FTXMON,<
|
||
MOVE T2,T1 ;[7.xxxx]Copy here for GFWNZN
|
||
MOVEI T1,(MS.DCN) ;[7.xxxx]Section number
|
||
PUSHJ P,GFWNZN## ;[7.xxxx]Ask ONCMOD for non-zero section core
|
||
HALT . ;[7.xxxx]*** FOR NOW
|
||
MOVEM T1,LATLOC ;[7.xxxx]Save as lowest address in freecore
|
||
> ;End IFN FTXMON
|
||
>; End IFN FTOPS10
|
||
|
||
MOVEI T1,HC.LST ;Get memory for the Host Node (HN) tables
|
||
CALL MMGTZW ;(T1/T1)Get zeroed memory
|
||
JRST INIRES ;Resource failure. Should not happen.
|
||
MOVE HN,T1 ;Base address for host node database references
|
||
MOVEM HN,LAHNDB ;Store the data base address
|
||
SETONE HNRUN,(HN) ;[7.1039]Start with the NI not running
|
||
MOVEI T1,CBMAXI ;Get storage for CBVECT
|
||
CALL MMGTZW ;(T1/T1)
|
||
JRST INIRES ;Resource failure.
|
||
; Circuit block index numbers start with one (not zero).
|
||
; When used as an index into the CBVECT array, the first
|
||
; word of the array is never used, and the address of the
|
||
; last CB is written in some other block.
|
||
SOS T1 ;Save the address minus one:
|
||
MOVEM T1,CBVECT ; circuit block indices start with one.
|
||
MOVEI T1,NTTLAH ;Get storage for SBVECT
|
||
CALL MMGTZW ;(T1/T1)
|
||
JRST INIRES ;Resource failure.
|
||
; Slot block index numbers start with one (not zero).
|
||
; When used as an index into the SBVECT array, the first
|
||
; word of the array is never used, and the address of the
|
||
; last SB is written in some other block.
|
||
SOS T1 ;Save the address minus one:
|
||
MOVEM T1,SBVECT ;slot block indices start with one.
|
||
MOVEI T1,PRMAXI ;[7.1120]
|
||
CALL MMGTZW ;[7.1120]Get storage for PRVECT
|
||
JRST INIRES ;[7.1120]Resource failure
|
||
SOS T1 ;[7.1120]Save the address minus one:
|
||
MOVEM T1,PRVECT ;[7.1120] PR slot indices start with one
|
||
MOVEI T1,PRMAXI ;[7.1120]
|
||
CALL MMGTZW ;[7.1120]Get storage for PRRAND table
|
||
JRST INIRES ;[7.1120]Resource failure
|
||
SOS T1 ;[7.1120]Save address minus one:
|
||
MOVEM T1,PRRAND ;[7.1120] PRRAND indices start with one
|
||
|
||
IFN FTOPS10,<
|
||
;
|
||
; Now carve up the core we got at ONCE time
|
||
; The free core pool will be turned into a
|
||
; linked list of fixed length buffers from which we can allocate
|
||
; transmit and receive buffers.
|
||
|
||
SETZRO QLFWD,+LATFRE ;Clear out the queue
|
||
SETZRO QLBWD,+LATFRE
|
||
CALL LAGTCR ;()Find out how much memory we got at ONCE time
|
||
IDIVI T1,BUFSIZ ;See how many buffers will fit
|
||
MOVE T4,T1 ;Put it where we need it later.
|
||
MOVEM T4,LATNFB ;Remember how many we have at start
|
||
MOVE T2,LATLOC ;Start of first one
|
||
CALL ALCBUF ;Link them together
|
||
MOVE T1,LATNAM## ;Get our node name
|
||
CALL CVTNOD ;Convert to ASCII
|
||
>;END IFN FTOPS10
|
||
DMOVE T1,OURNAM ;Get the local host name
|
||
DMOVEM T1,HN.NAM(HN) ;Store in HN block
|
||
MOVE T1,OURCNT ;Host name length in characters
|
||
STOR T1,HNNMC,(HN) ;Store in HN block
|
||
IFN FTOPS20,<
|
||
MOVX T1,<POINT 7,SVN##> ;Pointer to MONNAM.TXT
|
||
>
|
||
IFN FTOPS10,<
|
||
MOVX T1,<POINT 7,CONFIG##> ;Pointer to Monitor name
|
||
>
|
||
XMOVEI T2,HN.ID(HN) ;Where to put it.
|
||
TXO T2,<OWGP. 7,0> ; ...
|
||
MOVEI T3,ML.DSC ;Maximum length allowed
|
||
CALL MMVAZS ;(T1-3/T3)Move the string
|
||
TRN ;Don't care, take truncated string
|
||
STOR T3,HNIDC,(HN) ;Store real count
|
||
MOVE T1,RTRADR ;Get the default host number
|
||
STOR T1,HNNUM,(HN)
|
||
MOVEI T1,^D60 ;[7.1039]Default Host message retransmit limit
|
||
STOR T1,HNRLI,(HN)
|
||
MOVEI T1,^D1000 ;Default host virtual circuit timer (msec)
|
||
STOR T1,HNTIM,(HN)
|
||
MOVEI T2,^D30 ;Default host multicast timer (sec)
|
||
STOR T2,HNMTI,(HN)
|
||
MOVEI T1,^D10000 ;[7.1120]Default command message retry time (ms)
|
||
STOR T1,HNCMT,(HN) ;[7.1120]
|
||
MOVEI T1,^D5 ;[7.1120]Default command message retry limit
|
||
STOR T1,HNCMX,(HN) ;[7.1120]
|
||
MOVE T1,LASDEF ;[7.1039]Get the default LAT Access State
|
||
STOR T1,HNLAS,(HN) ;[7.1039] and store it
|
||
CAIN T1,LS.OFF ;[7.1039]If def. state = on, start transmitting
|
||
IFSKP. ;[7.1039] multicast messages immediately
|
||
IFN FTOPS20,<
|
||
IMULI T2,^D1000 ;[7.1039]Multicast in milliseconds
|
||
>;END IFN FTOPS20
|
||
MOVEM T2,LATMCT ;[7.1039]Initialize scheduler long timer word
|
||
ENDIF.
|
||
MOVEI T1,MAXACB ;[7.1164]Default max allocatable circuit blocks
|
||
STOR T1,HNMXC,(HN)
|
||
MOVEI T1,MAXACC ;[7.1164]
|
||
STOR T1,HNMAC,(HN) ;[7.1039]And maximum active circuits
|
||
MOVEI T1,CBMAXI ;Get a random number in the range or 1 to
|
||
CALL RANDOM ; (T1/T1)maximum value of circuit block index
|
||
STOR T1,HNNXI,(HN) ;Store as next CB index to assign
|
||
MOVEI T1,NTTLAH ;Default max number of simultaneous connects
|
||
STOR T1,HNMCO,(HN)
|
||
MOVEI T1,^D32 ;Number of access code bytes
|
||
STOR T1,ACLNG,(HN)
|
||
IFN FTOPS20,<
|
||
MOVSI T1,(1B7) ;Set group 0 on
|
||
MOVEM T1,AC.COD(HN) ;Store as first byte of access codes
|
||
> ;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
IFN FTXMON,<
|
||
XMOVEI T3,AC.COD(HN) ;Point to destination of XBLT
|
||
XMOVEI T2,LATIGE## ;From MONGENed groups enabled
|
||
MOVEI T1,^D8 ;Enough room for 32 bytes
|
||
EXTEND T1,[XBLT] ;Move the bytes
|
||
> ;END IFN FTXMON
|
||
IFE FTXMON,<
|
||
MOVEI T1,AC.COD(HN) ;Point to destination of BLT
|
||
HRLI T1,LAT.GE## ;From MONGENed groups enabled
|
||
BLT T1,AC.COD+7(HN) ;Move the bytes
|
||
> ;END IFE FTXMON
|
||
> ;END IFN FTOPS10
|
||
MOVEI T1,1
|
||
STOR T1,HNNSV,(HN) ;Default number of host services offered
|
||
XMOVEI W1,HN.SRV(HN) ;Address of the host service blocks
|
||
STOR T1,GBRAT,(W1)
|
||
MOVE T1,OURCNT ;Default service name is node name so
|
||
STOR T1,GBNC,(W1) ; store the count
|
||
DMOVE T1,OURNAM ; and the name
|
||
DMOVEM T1,GB.NAM(W1)
|
||
LOAD T1,HNIDC,(HN) ;[7.1039]Get Host node id count
|
||
CAILE T1,ML.SID ;[7.1039]Don't exceed the maximum allowed
|
||
MOVEI T1,ML.SID ;[7.1039]
|
||
STOR T1,GBLC,(W1) ;[7.1039]Save it
|
||
ADDI T1,4 ;[7.1039]Convert from bytes to words
|
||
IDIVI T1,5 ;[7.1039]
|
||
XMOVEI T2,HN.ID(HN) ;[7.1039]Get address of host descriptor
|
||
XMOVEI T3,GB.HID(W1) ;[7.1039]And address of service descriptor
|
||
XBLT. T1 ;[7.1039]Make service descriptor same as host
|
||
XMOVEI XB,HN.MCM(HN) ;Address of the multicast message block
|
||
MOVE T1,[BYTE (8)11,0,53,0,(4)0];Store multicast address
|
||
MOVE T2,[BYTE (8)0,17,0,0]; ...
|
||
OPSTRM <DMOVEM T1,>,UNDAD,+UNB.OF(XB);09-00-2B-00-00-0F
|
||
SETO T1,0 ;Use random number for incarnation count
|
||
CALL BMCFXD ;(T1,HN,XB)Build fixed part of message
|
||
CALL BMCACS ;(HN,XB)Enter the host access code string
|
||
CALL BMCNID ;(HN,XB)Enter the host node name and descriptn
|
||
CALL BMCSRV ;(HN,XB)Build the services
|
||
SETONE HNLOK,(HN) ;Initialize database lock
|
||
STOR XB,UNRID,+UNB.OF(XB);Store for xmit complete processing
|
||
CALL BLDSTM ;(HN)Now build the START message template
|
||
MOVX T1,NTTLAH ;[7.1120]Get the number of slot blocks
|
||
MOVEI T2,SBBITS ;[7.1120]Get address of allocation table
|
||
CALL BITON ;[7.1120](T1,T2)Initialize to all ones
|
||
MOVX T1,PRMAXI ;[7.1120]Get the number of PR blocks
|
||
MOVEI T2,PRBITS ;[7.1120]Get address of allocation table
|
||
CALL BITON ;[7.1120](T1,T2)Initialize to all ones
|
||
IFN FTOPS20,<
|
||
MOVX T1,PRMAXI ;[7.1120]Get the number of PR blocks
|
||
MOVEI T2,PRWMSK ;[7.1120]Get addr of scheduler test table
|
||
CALL BITOF ;[7.1120](T1,T2)Initialize to all zeros
|
||
>;END IFN FTOPS20
|
||
SETZRO UNCHN,+UNB.OF(XB);For now, later must read channel list
|
||
SETZRO UNPAD,+UNB.OF(XB);We use padding
|
||
MOVEI T1,^B0110000000000100 ;Protocol ID is 60-04
|
||
STOR T1,UNPRO,+UNB.OF(XB)
|
||
XMOVEI T1,LATCBR ;Callback routine address
|
||
STOR T1,UNCBA,+UNB.OF(XB)
|
||
MOVX T1,NU.OPN ;NISRV Open function
|
||
XMOVEI T2,UNB.OF(XB) ;Use this for open as well
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI##
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1)
|
||
>
|
||
IFSKP.
|
||
XMOVEI T2,UNB.OF(XB) ;Load address of UN block
|
||
CALL LATLSC ;(T1-2)Check to see if NI is running
|
||
LOAD T1,UNPID,+UNB.OF(XB) ;Get the PID return from the DLL
|
||
STOR T1,HNPID,(HN) ; and store for later calls to the DLL.
|
||
CALL GETRBF ;(HN)Get a buffer for receives
|
||
TRN ;Will have to get buffers later
|
||
ENDIF.
|
||
RET
|
||
INIRES:
|
||
BUG. (CHK,LATINE,LATSER,SOFT,<LATINI failed to initialize>,,<
|
||
|
||
Cause: Could not obtain sufficient memory for the LAT host databases.
|
||
|
||
Action: Determine why there is so little resident memory available at system
|
||
startup.
|
||
|
||
Data: HN.LST words for the host node database, CBMAXI words for CBVECT,
|
||
and NTTLAH words for SBVECT.
|
||
|
||
>)
|
||
SKIPE T1,LAHNDB ;Start with a clean slate when we try
|
||
CALL MMFREE ; (T1)to initialize later...
|
||
SKIPE T1,CBVECT ; ...
|
||
CALL MMFREE ; (T1)...
|
||
SKIPE T1,SBVECT ; ...
|
||
CALL MMFREE ; (T1)...
|
||
SKIPE T1,PRVECT ;[7.1120] ...
|
||
CALL MMFREE ;[7.1120] ...
|
||
SKIPE T1,PRRAND ;[7.1120] ...
|
||
CALL MMFREE ;[7.1120] ...
|
||
RET
|
||
|
||
ENDAV.
|
||
;[7.1120]
|
||
;BITON - Set a number of bits in a table.
|
||
;BITOF - Clear a number of bits in a table
|
||
;
|
||
; T1/ Number of bits to set
|
||
; T2/ Address of the array
|
||
; CALL BITON/BITOF
|
||
; Return+1: Always
|
||
|
||
BITOF: TDZA T4,T4 ;Clear T4, and skip
|
||
BITON: SETO T4, ;T4 = 0 implies BITOF was called.
|
||
SAVEAC <P1> ;Don't trash P1
|
||
MOVEM T2,T3 ;Copy the destination address
|
||
IDIVI T1,^D36 ;Calculate the number of whole words
|
||
MOVEM T2,P1 ;Save the number of bits left over
|
||
JUMPLE T1,BITON1 ;No whole words: check for bits left
|
||
MOVEM T4,(T3) ;Initialize the first word
|
||
MOVE T2,T3 ;Make that the source address
|
||
AOS T3 ;The destination is the next word
|
||
SOSLE T1 ;Do we need to set more than one word?
|
||
XBLT. T1 ;Yes, use a block transfer
|
||
BITON1: JUMPE P1,RTN ;Zero bits left: return
|
||
MOVEI T1,1 ;Calculate the negative number
|
||
SUB T1,P1 ; of bits to shift plus one
|
||
MOVX T2,1B0 ;Get a bit to be shifted
|
||
ASH T2,(T1) ;Build a bit mask for the last word
|
||
SKIPN T4 ;BITOF?
|
||
SETCA T2, ;Yes. T2 = ~T2
|
||
MOVEM T2,(T3) ;Use it
|
||
RET ;
|
||
SUBTTL Subroutine -- CWHLAT - Type a server spec for WHERE command
|
||
|
||
;CWHLAT - Types a server spec given a LATSER-owned LDB.
|
||
;
|
||
; Call:
|
||
; U/ Target LDB address
|
||
; 0(P)/ Command LDB address
|
||
;
|
||
; Return:
|
||
; RET ;If success
|
||
; via CWHNCN ;If line is not owned by LATSER
|
||
;
|
||
; Used: T1-T4
|
||
|
||
RESCD
|
||
|
||
IFN FTOPS10,<
|
||
CWHLAT::POP P,T1 ;Can't call SE1ENT with junk on stack!
|
||
SE1ENT ;So we can access NZS data
|
||
PUSH P,T1 ;RE-save LDB of command term
|
||
SKIPN T1,LDBLAT##(U) ;Get slot block associated with target TTY
|
||
PJRST CWHNCN## ;Not connected now.
|
||
POP P,U ;Point to command terminal for typeout
|
||
PUSH P,DEVNAM(F) ;Save TTY name
|
||
PUSH P,SB.CBA(T1) ; and Circuit Block address.
|
||
CALL TTYKLQ## ;ZAP useless TTY DDB
|
||
CALL INLMES## ;Type out an intro
|
||
ASCIZ /LAT / ; guess what!
|
||
MOVE T2,(P) ;Get LAT circuit block address
|
||
LOAD T1,CBRSC,(T2) ;Get server name count from it
|
||
ADD T2,[OWGP. 7,CB.SNM] ;Make byte pointer to name
|
||
CALL TCSTR ;(T1-T2)Type a counted string
|
||
MOVEI T3,"(" ;Separate it
|
||
CALL COMTYO## ; from location
|
||
POP P,T2 ;Get CB address for last time
|
||
LOAD T1,CBRLC,(T2) ;Get server location count from it
|
||
ADD T2,[OWGP. 7,CB.LOC] ;Make byte pointer to location
|
||
CALL TCSTR ;(T1-T2)Type a counted string
|
||
CALL INLMES## ;Close it off
|
||
ASCIZ /) / ;and separate it.
|
||
POP P,T2 ;Get TTY name
|
||
CALL PRNAME## ; and type it.
|
||
CALLRET PCRLF## ;and return
|
||
;Still in IFN FTOPS10
|
||
|
||
; Routine TCSTR - type a counted ASCII string
|
||
;
|
||
;Call: T1/ byte count
|
||
; T2/ byte pointer
|
||
;
|
||
TCSTR: SOJL T1,CPOPJ## ;No chars to type
|
||
PUSH P,T1 ;save the count in a safe place
|
||
TCST1: ILDB T3,T2 ;Get a character
|
||
CALL COMTYO## ; and type it
|
||
SOSL (P) ;Count them down
|
||
JRST TCST1 ; and do them all
|
||
POP P,T1 ;trim the stack
|
||
RET ; and return
|
||
|
||
XRESCD
|
||
|
||
; Once-A-Second code
|
||
;
|
||
LATSEC: SKPCPU (0) ;SKIP IF WE'RE ON POLICY CPU
|
||
RET ;NO, ONLY RUN ONCE A SECOND!
|
||
CALL XLATXP ;[7.1120]Transmit Command messages
|
||
SKIPLE LATMCT ;IS the timer non-zero?
|
||
SOSLE LATMCT ;Count down the timer
|
||
RET ;Not time to do anything yet
|
||
; CALLRET LATXMC ;()Fall into multicast transmit code
|
||
>;end IFN FTOPS10
|
||
SUBTTL Multicast Transmitter
|
||
|
||
;LATXMC - Transmit Multicast Message
|
||
|
||
;CALL: CALL LATXMC
|
||
; Normal Return
|
||
|
||
XRENT (LATXMC,G) ;[7.1024]LATXMC::, XLATXM::
|
||
|
||
ACVAR <HN,XB,W1,W2>
|
||
MOVE HN,LAHNDB ;Get the HN data base address
|
||
LOAD T1,HNMTI,(HN) ;Reset the multicast timer
|
||
IFN FTOPS20,<
|
||
IMULI T1,^D1000 ;Convert from seconds to milliseconds
|
||
>;END IFN TOPS20
|
||
MOVEM T1,LATMCT ;
|
||
CALL CHKXMC ;(HN)Transmit the multicast this time?
|
||
RET ;No.
|
||
CALL GETRBF ;(HN)Post more receive buffers if necessary.
|
||
TRN ;Not necessary.
|
||
CALL DYNRAT ;(HN)Check if dynamic rating needs update.
|
||
XMOVEI XB,HN.MCM(HN) ;Get the address of the multicast msg
|
||
OPSTR <SKIPE W1,>,HNCFL,(HN);If nothing changed in HN database
|
||
OPSTR <SKIPL>,HNLOK,(HN); or something changed by db id locked
|
||
JRST SNDMNC ; then send the old image of mc msg
|
||
CAIE W1,HN%SVR ;Did only the ratings change?
|
||
JRST LATXM0 ;No, something else changed
|
||
CALL BMCRAT ;(HN,XB)Go update the ratings
|
||
JRST LATXM2 ; and send the mc msg
|
||
LATXM0: SETZ T1,0 ;So BMCFXD will increment incarnation count
|
||
TRNE W1,HN%OTH ;Did something in fixed part of mc change?
|
||
CALL BMCFXD ;(T1,HN,XB)Yes, go rebuild fixed part of mc msg
|
||
TRNE W1,HN%ACS ;Did any access codes change?
|
||
CALL BMCACS ;(HN,XB)Yes, go rebuild access code field
|
||
TRNE W1,HN%NDD ;Did the host node description change?
|
||
CALL BMCNID ;(HN,XB)Rebuild the node description
|
||
TRNN W1,HN%NDD ; and the service fields
|
||
LATXM1: TRNE W1,HN%SVN!HN%SVD!HN%SVR;Did anything in any service change?
|
||
CALL BMCSRV ;(HN,XB)Yes, reconstruct all service fields
|
||
LATXM2: SETZRO HNCFL,(HN) ;Clear data base change flags
|
||
SENDMC: MOVX T1,<POINT 8,<SBF.OF+1>(XB),23>;Pointer msg change flags
|
||
LDB T2,T1 ;Message incarnation field
|
||
AOS T2 ;Add one
|
||
DPB T2,T1 ; and put back into msg
|
||
ILDB T2,T1 ;Load current change flag settings from msg
|
||
TDC T2,W1 ;Complement those bits which represent change
|
||
DPB T2,T1 ; and put back into msg
|
||
SNDMNC: XMOVEI T1,<SBF.OF>(XB) ;Set up one word global to buffer for
|
||
TXO T1,<OWGP. 8,0> ; NISRV and
|
||
STOR T1,UNBFA,+UNB.OF(XB); store in UN block
|
||
LOAD T1,HNPID,(HN) ;Get the PID for the DLL
|
||
STOR T1,UNPID,+UNB.OF(XB)
|
||
MOVX T1,NU.XMT ;Set NI function to transmit
|
||
XMOVEI T2,UNB.OF(XB) ;Address of arguement block for NISRV
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI## ;Call NI service
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1) ;Call NI service
|
||
>
|
||
TRN ;Ignore error
|
||
RET ;Return
|
||
SUBTTL Routine to check/compute the Dynamic Rating
|
||
|
||
;DYNRAT - Routine to check/compute the Dynamic Rating
|
||
|
||
DYNRAT:
|
||
IFN FTOPS20,<
|
||
MOVE T1,RJAV+2 ;15 minute load average
|
||
FSC T1,2 ;Multiply by 4
|
||
FIXR T1,T1 ;and convert/round to integer
|
||
SUBI T1,^D255 ;Subtract from 255 to give negative rating.
|
||
SKIPLE T1 ;Assure rating
|
||
MOVX T1,-1 ; is at least 1
|
||
MOVMS T1 ;Make rating positive
|
||
OPSTR <CAMN T1,>,HNRAT,(HN) ;Compare with current dynamic rating
|
||
RET ;No change; return.
|
||
STOR T1,HNRAT,(HN) ;Store new rating in HN block
|
||
SETONE HNSVR,(HN) ;Indicate rating has changed.
|
||
>;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVEI T1,1 ;No dynamic rating for TOPS-10
|
||
>;END IFN FTOPS10
|
||
RET
|
||
SUBTTL Routines to Build the Host Multicast Message -- BMCFXD
|
||
|
||
;BMCFXD - Build fixed portion of the multicast message
|
||
|
||
;Call: T1/ Incarnaction count flag
|
||
; HN/ Host Node Data Base Address
|
||
; XB/ Address of the multicast message block in HN
|
||
; CALL BMCFXD
|
||
;
|
||
; This routine builds the first ^D12 bytes of the multicast message. It is
|
||
; called either to build a new message or to update the fixed portion if any
|
||
; of the parameters in the fixed portion have changed since the last multicast
|
||
; message was transmitted. This routine does not modify the message count.
|
||
|
||
BMCFXD: STKVAR <INCFLG> ;Save the incarnaction
|
||
MOVEM T1,INCFLG ; flag.
|
||
MOVX T1,<POINT 8,<SBF.OF>(XB)> ;Byte pointer to start of msg
|
||
STOR T1,UNBFA,+UNB.OF(XB); is needed to fill in the msg header
|
||
MOVEI T1,MT.MCA_2 ;Message type for multicast message
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
MOVEI T1,^D8 ;Set 80ms preferred server circuit timer
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
MOVEI T1,LALPV_^D8+LAHPV;Highest and lowest permitted protocol version
|
||
CALL LAP2B0 ;(T1)
|
||
MOVEI T1,PROECO_^D8+PROVER ;Enter current protocol version and ECO
|
||
CALL LAP2B0 ;(T1)
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(XB);Get old incarnation count and assume
|
||
AOS T1 ; we just want to increment it.
|
||
SKIPN INCFLG ;If this is initialization, we want a "random"
|
||
IFSKP. ; incarnation count instead.
|
||
MOVEI T1,^D255 ;Maximum value incarnation count can have.
|
||
CALL RANDOM ; (T1/T1)the initial message incarnation count.
|
||
ENDIF.
|
||
OPSTRM <DPB T1,>,UNBFA,+UNB.OF(XB); and put back
|
||
LOAD T1,HNCFL,(HN) ;Get the change flags
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
MOVEI T1,LMRFSI+^D14 ;Receive buffer size (including E-net header)
|
||
CALL LAP2B0 ;(T1)
|
||
LOAD T1,HNMTI,(HN) ;Get the multicast timer interval
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
MOVEI T1,0 ;Set status indicating accepting new sessions.
|
||
LOAD T2,HNLAS,(HN) ;Get the current LAT access state
|
||
CAIE T2,LS.ON ;Is it on?
|
||
MOVEI T1,1 ;No, indicate not accepting new sessions.
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
RET
|
||
SUBTTL Routines to Build the Host Multicast Message -- BMCFXD
|
||
|
||
;BMCACS - Enter Access Codes into the Multicast Message - BMCACS
|
||
|
||
;Call: HN/ Host Node Data Base Address
|
||
; XB/ Address of the multicast message block in HN
|
||
; CALL BMCACS
|
||
; Normal Return
|
||
;
|
||
; This routine builds ^D32 bytes of host access codes. It is called either to
|
||
; build a new message or to update the fixed length access code field if any of
|
||
; the access codes have changed since the last multicast message was
|
||
; transmitted. This routine does not modify the message count.
|
||
|
||
BMCACS:
|
||
MOVX T1,<POINT 8,<SBF.OF+^D12/4>(XB)> ;ACs start at a fixed location
|
||
STOR T1,UNBFA,+UNB.OF(XB) ;Store as byte pointer to message buffer
|
||
LOAD T1,ACLNG,(HN) ;Count of the access code string
|
||
MOVX T2,<POINT 8,AC.COD(HN)> ;Source string byte pointer
|
||
CALL PTCST0 ;(XB,T1,T2)Transfer the string to the message
|
||
RET
|
||
SUBTTL Routines to Build the Host Multicast Message -- BMCNID
|
||
|
||
;BMCNID - Enter Access Codes into the Multicast Message - BMCNID
|
||
|
||
;Call: HN/ Host Node Data Base Address
|
||
; XB/ Address of the multicast message block in HN
|
||
; CALL BMCNID
|
||
; Normal Return
|
||
;
|
||
; This routine enters the host node name and descriptor strings into the
|
||
; multicast message block. It is called either to build a new message or to
|
||
; update the fixed length access code field if the node name or descriptor
|
||
; has changed since the last multicast message was transmitted. If this
|
||
; routine is called, the rest of the multicast message must be rebuilt. This
|
||
; routine does not modify the message count.
|
||
|
||
BMCNID:
|
||
MOVX T1,<POINT 8,<SBF.OF+^D12/4+^D32/4>(XB),7> ;Node name starts here
|
||
STOR T1,UNBFA,+UNB.OF(XB) ;Store as byte pointer to message buffer
|
||
LOAD T1,HNNMC,(HN) ;Host name count
|
||
MOVX T2,<POINT 7,HN.NAM(HN)> ;Source string byte pointer
|
||
CALL PTCST0 ;(XB,T1,T2)Transfer host node name to m.c.msg
|
||
LOAD T1,HNIDC,(HN) ;Count of host node description string
|
||
MOVX T2,<POINT 7,HN.ID(HN)> ;Move the host node id string to the
|
||
CALL PTCST0 ; (XB,T1,T2)m.c. message
|
||
RET
|
||
SUBTTL Routines to Build the Host Multicast Message -- BMCSRV
|
||
|
||
;BMCSRV - Build the Available Host Services Data - BMCSRV
|
||
|
||
;Call: HN/ Host Node Data Base Address
|
||
; XB/ Address of the multicast message block in HN
|
||
; CALL BMCSRV
|
||
; Normal Return
|
||
;
|
||
; This routine enters all service blocks and the service classes into the
|
||
; multicast message block. It is called either to build a new message or to
|
||
; update the message when any service name or description has changed since
|
||
; the last multicast message was transmitted. This routine does modify the
|
||
; message count.
|
||
|
||
BMCSRV: SAVEAC <W1,W2>
|
||
LOAD W1,HNNSV,(HN) ;Get the total number of offered services
|
||
SKIPN W1 ;Must be at least one service to offer
|
||
RET ;Nope.
|
||
MOVEI T4,^D12+^D33+1 ;Initialize msg count
|
||
MOVX T3,<POINT 8,<SBF.OF+^D12/4+^D32/4>(XB),7>;Get pointer to node name
|
||
ILDB T1,T3 ;Get node name count
|
||
ADDI T4,1(T1) ;Include in total msg count
|
||
ADJBP T1,T3 ;Adjust to node descriptor
|
||
ILDB T3,T1 ;Get the node description count
|
||
ADDI T4,1(T3) ;Include in total msg count
|
||
ADJBP T3,T1 ;Adjust pointer to start of Service Block
|
||
STOR T4,UNBSZ,+UNB.OF(XB);Store msg count so far
|
||
STOR T3,UNBFA,+UNB.OF(XB);Current message byte pointer
|
||
OPSTRM <IDPB W1,>,UNBFA,+UNB.OF(XB);Already counted
|
||
XMOVEI W2,HN.SRV(HN) ;Address of start of service blocks
|
||
SRVLP: OPSTR <SKIPGE T1,>,GBRAT,(W2) ;Get the service rating
|
||
LOAD T1,HNRAT,(HN) ;If negative, load current host dynamic rating.
|
||
OPSTRM <AOS>,UNBSZ,+UNB.OF(XB);Account for rating in the byte count
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB);Store in mc msg
|
||
LOAD T1,GBNC,(W2) ;Get the service name count
|
||
MOVX T2,<POINT 7,GB.NAM(W2)> ;Pointer to service name
|
||
CALL PTCSTR ;(XB,T1,T2)Move name string to mc msg
|
||
LOAD T1,GBLC,(W2) ;Get the service description count
|
||
MOVX T2,<POINT 7,GB.HID(W2)>;Pointer to the service description string
|
||
CALL PTCSTR ;(XB,T1,T2)Move to mc msg
|
||
ADDI W2,GB.LEN ;Address of next block
|
||
SOJN W1,SRVLP ;Loop through all services
|
||
MOVEI T1,1_^D8+1 ;Service class 1 only
|
||
CALL LAP2BY ;(XB,T1)
|
||
RET
|
||
SUBTTL Routines to Build the Host Multicast Message -- BMCRAT
|
||
|
||
;BMCRAT - Update the MC Msg with the current service ratings - BMCRAT
|
||
|
||
;Call: HN/ Host Node Data Base Address
|
||
; XB/ Address of the multicast message block in HN
|
||
; CALL BMCRAT
|
||
; Normal Return
|
||
;
|
||
; This routine loops though all the service blocks and updates the
|
||
; corresponding service rating in the multi-cast message. This routine does
|
||
; NOT modify the message count itself.
|
||
|
||
BMCRAT: SAVEAC <W1,W2>
|
||
MOVX T3,<POINT 8,<SBF.OF+^D12/4+^D32/4>(XB),7>;Get pointer to node name
|
||
ILDB T1,T3 ;Get node name count
|
||
ADJBP T1,T3 ;Adjust to node descriptor
|
||
ILDB T3,T1 ;Get the node description count
|
||
ADJBP T3,T1 ;Adjust pointer to start of Service Block
|
||
ILDB W1,T3 ;Get number of services from msg
|
||
XMOVEI W2,HN.SRV(HN) ;Address of start of service blocks
|
||
RATLP: OPSTR <SKIPGE T1,>,GBRAT,(W2) ;Get the service rating
|
||
LOAD T1,HNRAT,(HN) ;If negative, load current host dynamic rating.
|
||
IDPB T1,T3 ;Store updated rating in mc msg
|
||
LOAD T1,GBNC,(W2) ;Get the service name count
|
||
OPSTR <ADD T1,>,GBLC,(W2);Add the service description count
|
||
ADDI T1,2 ;Account for the 2 count fields
|
||
ADJBP T1,T3 ;Adjust the pointer
|
||
MOVE T3,T1 ;Put adjusted pointer back where we want it
|
||
ADDI W2,GB.LEN ;Address of next block
|
||
SOJN W1,RATLP ;Loop through all services
|
||
RET
|
||
SUBTTL Multicast Transmit Check Routine
|
||
|
||
;CHKXMC - Check for Transmit of Multicast Message
|
||
|
||
;Call: HN/ Address of the Host Node Data Base
|
||
;RET - Don't transmit
|
||
;RETSKP Transmit
|
||
|
||
CHKXMC: LOAD T1,HNLAS,(HN) ;Transmit only if LAT access state is ON and
|
||
LOAD T2,HNNMC,(HN) ; there is a host name defined.
|
||
CAIN T1,LS.ON ; is ON.
|
||
SKIPN T2
|
||
RET
|
||
TMNE HNRUN,(HN) ;Is the NIA running?
|
||
RET ;No, don't send any messages.
|
||
RETSKP
|
||
SUBTTL Build the START Message Template
|
||
|
||
;BLDSTM - Build the START Message Template
|
||
|
||
;Call: HN/ Address of the Host Node Data Base
|
||
; CALL BLDSTM
|
||
; Normal Return
|
||
;
|
||
; This routine builds the "static" portions of the start message: those
|
||
; fields which do not change very frequently. Fields which change frequently
|
||
; are set up by the transmitting routines. This routine also sets up the
|
||
; message size in UNBSZ of the NISRV UN block.
|
||
|
||
BLDSTM: SAVEAC <W1>
|
||
XMOVEI XB,HN.SMT(HN) ;Address of START message template
|
||
MOVX T1,<POINT 8,<SBF.OF+<SZ.MHD>/4>(XB)>;Point beyond the msg header
|
||
STOR T1,UNBFA,+UNB.OF(XB); since it will change with each transmission.
|
||
MOVEI W1,^D12 ;Count of fixed fields (including count fields)
|
||
MOVEI T1,LMRFSI+^D14 ;Minimum receive buffer size
|
||
CALL LAP2B0 ;(XB,T1)Store in msg
|
||
MOVEI T1,PROECO_^D8+PROVER ;Enter current LAT protocol version
|
||
CALL LAP2B0 ;(XB,T1) and ECO
|
||
LOAD T1,HNMCO,(HN) ;System-wid maximum LAT connects allowed
|
||
CAILE T1,MXSLTS ; compared to max slots per virtual circuit
|
||
MOVEI T1,MXSLTS ;Get the smaller of the two
|
||
CALL LAP2B0 ;(XB,T1)
|
||
MOVEI T1,0 ;Timers are non-zero when from server
|
||
CALL LAP2B0 ;(XB,T1) only.
|
||
LOAD T1,HNNUM,(HN) ;Get the host number
|
||
CALL LAP2B0 ;(XB,T1) and store as 2 bytes in msg
|
||
MOVEI T1,LHPRID ;LAT Host product ID is TOPS-20 Host
|
||
CALL LAP2B0 ;(XB,T1) and store as 2 bytes in msg
|
||
LOAD T1,HNNMC,(HN) ;Host Node Name count
|
||
ADDI W1,1(T1) ;Add to the total message byte count
|
||
MOVX T2,<POINT 7,HN.NAM(HN)>;Host node name source string
|
||
CALL PTCST0 ;(XB,T1,T2)Put into start message as NODE NAME
|
||
LOAD T1,HNNMC,(HN) ;Host Node Name count
|
||
ADDI W1,1(T1) ;Add to the total message byte count
|
||
MOVX T2,<POINT 7,HN.NAM(HN)>;Host node name source string
|
||
CALL PTCST0 ;(XB,T1,T2)Put in start message as SYSTEM NAME
|
||
LOAD T1,HNIDC,(HN) ;Count of description string
|
||
ADDI W1,1(T1) ;Add to the total message byte count
|
||
MOVX T2,<POINT 7,HN.ID(HN)>;Description string source pointer
|
||
CALL PTCST0 ;(XB,T1,T2)Put into start message
|
||
MOVEI T1,0 ;There are no parameters
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB); is zero
|
||
ADDI W1,1 ;Include in total count
|
||
CAIG W1,MINXBF ;Send at least the minimum
|
||
MOVEI W1,MINXBF ; size.
|
||
STOR W1,UNBSZ,+UNB.OF(XB);Store message byte count
|
||
STOR XB,UNRID,+UNB.OF(XB);Store buffer address for completion routines.
|
||
RET
|
||
|
||
ENDAV.
|
||
SUBTTL LAINTR -- LAT DLL Callback Routinea
|
||
|
||
;LATCBR - dispatch to routine to handle DLL callback
|
||
|
||
;Call: T1/ NU.RCV
|
||
; T2/UN block address
|
||
; CALL LATCBR
|
||
; Normal return
|
||
|
||
LATCBR: ACVAR <HN,XB,RB> ;Reserve some registers
|
||
MOVE HN,LAHNDB ;Get the host node data base address
|
||
MOVE T4,T3 ;Save NISRV's error register
|
||
CAIL T1,MINCBF ;Validate the callback function code
|
||
CAIG T1,MAXCBF
|
||
CALLRET @CBRDSP-MINCBF(T1) ;Valid, call the proper routine
|
||
BUG. (CHK,LATICB,LATSER,SOFT,<LATCBR called from NISRV with illegal callback function code>,<<T1,CODE>>,<
|
||
|
||
Cause: NISRV has called the LATSER callback routine with an invalid function
|
||
code.
|
||
|
||
Data: CODE - Function code
|
||
|
||
>)
|
||
;[7.1024]
|
||
;[7.1024] **WARNING** If ILLCBR is moved out of PSECT XRCOD then the
|
||
;[7.1024] "IFIW ILLCBR" in the CBRDSP dispatch table must be changed.
|
||
;[7.1024]
|
||
ILLCBR:
|
||
RET
|
||
|
||
MIN. (MINCBF,<NU.XMT,NU.RCV,NU.RCI,NU.SCA,NU.RCC>) ;Minimum callback function
|
||
MAX. (MAXCBF,<NU.XMT,NU.RCV,NU.RCI,NU.SCA,NU.RCC>) ;Maximum callback function
|
||
|
||
CBRDSP: XADDR. LAINTR ;[7.1052]Datagram received
|
||
XADDR. LAINTX ;[7.1052]Datagram transmit complete
|
||
XADDR. ILLCBR ;[7.1052]Enable Multicast (Not used)
|
||
XADDR. ILLCBR ;[7.1052]Disable Multicast (Not used)
|
||
XADDR. ILLCBR ;[7.1052]Read Portal Cntrs (Not used)
|
||
XADDR. LATLSC ;[7.1052]Link state changed
|
||
XADDR. ILLCBR ;[7.1052]NU.RPL
|
||
XADDR. ILLCBR ;[7.1052]NU.RCL
|
||
XADDR. ILLCBR ;[7.1052]NU.RPI
|
||
XADDR. ILLCBR ;[7.1052]Set Channel Address (Not used)
|
||
XADDR. ILLCBR ;[7.1052]Read Channel Cntrs (Not used)
|
||
|
||
SUBTTL LAINTR -- Interrupt Level Virtual Circuit Message Receiver
|
||
|
||
;LAINTR - Processes a circuit message at NI interrupt level
|
||
|
||
;Call: T1/ NU.RCV
|
||
; T2/UN block address
|
||
; T4/NISRV's T3
|
||
; CALL LAINTR
|
||
; Normal return
|
||
|
||
LAINTR: LOAD RB,UNRID,(T2) ;Get address of message block
|
||
JUMPE T4,LANTR1 ;[7.1039]If error code is 0 proceed
|
||
|
||
; Here, there was an error on receive. Don't wait for tick time
|
||
; to turn the buffer around.
|
||
;
|
||
MOVE T1,RB ;[7.1039]Get address of receive buffer
|
||
CALL RBPOSS ;[7.1039](T1)Repost it now (preserving T1-T4)
|
||
TRNA ;[7.1039]Couldn't re-post. Process it later.
|
||
RET ;[7.1039]Buffer re-posted. We're done for now.
|
||
|
||
LANTR1: MOVEI T1,UN.LEN ;[7.1039]Length of the block to copy
|
||
XMOVEI T3,UNB.OF(RB) ;Address of where to copy the UN block
|
||
XBLT. T1 ;Copy the UN block to buffer header
|
||
MOVEI T1,NU.RCV ;Scheduler needs to know buffer type.
|
||
MOVE T2,RB ;Address of element to put onto queue
|
||
CALL LAINT0 ;(T1,T2,T4)Do common actions
|
||
RET ;And return to NISRV dismissing interrupt
|
||
SUBTTL LAINTX - Interrupt Level Virtual Circuit Message Receiver
|
||
|
||
;LAINTX - Processes a circuit message at NI interrupt level
|
||
|
||
;Call: T1/ NU.XMT
|
||
; T2/UN block address
|
||
; T4/NISRV's T3
|
||
; CALL LAINTX
|
||
; Normal return
|
||
|
||
LAINTX: LOAD XB,UNRID,(T2) ;Get the buffer address
|
||
LOAD T3,UNDAD,+UNB.OF(XB);Get first 4 bytes (low order) of NI address
|
||
TXNE T3,1B7 ;Is the multicast bit on?
|
||
RET ;Yes, nothing to do
|
||
MOVX T3,<POINT 8,<SBF.OF>(XB)>;Point to the msg header
|
||
ILDB T2,T3 ; and get the message type
|
||
LSH T2,-2 ;Shift off M and RRF bits
|
||
CAIE T2,MT.STA ;If a START message,
|
||
IFSKP. ; then release lock on the START message
|
||
SETZRO HNCIP,(HN) ; template and return.
|
||
RET
|
||
ENDIF.
|
||
MOVE T2,XB
|
||
CALL LAINT0 ;(T1,T2,T4)Do common actions
|
||
RET
|
||
|
||
; Routine to perform interrupt level actions common to both receive data and
|
||
; transmit complete.
|
||
;
|
||
LAINT0: STOR T1,UNCBA,+UNB.OF(T2);Store callback type for scheduler processing
|
||
STOR T4,UNSPI,+UNB.OF(T2);Save NISRV's error return
|
||
IFN FTOPS10,<
|
||
ETHLOK ;Interlock queue access
|
||
>
|
||
OPSTR <SKIPN T3,>,HNNIQ,+1(HN);Is the Q currently empty?
|
||
IFSKP. ;NO
|
||
STOR T2,UELW1,(T3) ;New forward for old Q tail element
|
||
SETZRO UELW1,(T2) ;New tail's forward link is zero.
|
||
ELSE. ;YES
|
||
STOR T2,HNNIQ,(HN) ;New queue header forward pointer
|
||
ENDIF.
|
||
STOR T2,HNNIQ,+1(HN) ;New queue header tail pointer
|
||
IFN FTOPS10,<
|
||
ETHULK ;Release interlock
|
||
>
|
||
RET
|
||
|
||
ENDAV.
|
||
SUBTTL LARSCH - Scheduler Level Virtual Circuit Message Receiver
|
||
|
||
;LARSCH - Complete circuit message processing at scheduler level
|
||
|
||
IFN FTOPS10,< ;[7.yyyy]
|
||
RESCD ;[7.yyyy]
|
||
LATSTO::SKPCPU (0) ;[7.yyyy]On policy CPU?
|
||
RET ;[7.yyyy]No, do nothing
|
||
; CALLRET LARSCH ;[7.yyyy]Yes, fall into LARSCH
|
||
> ;End IFN FTOPS10
|
||
|
||
XRENT (LARSCH,G) ;[7.1024]LARSCH::, XLARSC::
|
||
|
||
ACVAR <HN,XB,RB,CB,SB,W1,W2>;Get a set of dedicated ACs
|
||
TRVAR <MSGDID,MSGSID,MSGACK,STPCOD>;Message hdr variable, etc.
|
||
SETZ CB, ;[7234] No circuit block yet
|
||
SKIPN HN,LAHNDB ;Get the host node database address
|
||
RET ;If none, not initialized yet.
|
||
CALL MOVNIQ ;(T1,T2)Move all messages from NI to Sched que
|
||
IFN FTOPS10,<
|
||
SETZM LATWFB ;Say we don't want more buffers yet
|
||
>
|
||
|
||
MSGNXT: OPSTR <SKIPN T2,>,HNSCQ,(HN);Get first element on the scheduler Q
|
||
CALLRET LAMUX ;No more so call the slot multiplexor
|
||
OPSTR <SKIPN T3,>,UELW1,(T2);Get new head or queue if any
|
||
STOR T3,HNSCQ,+1(HN) ;None, so clear the queue header tail pointer
|
||
STOR T3,HNSCQ,(HN) ;Set new queue header forward pointer
|
||
SETZRO UELW1,(T2) ;Clear link word
|
||
LOAD T1,UNCBA,+UNB.OF(T2)
|
||
CAIE T1,NU.XMT ;Is this a transmit complete?
|
||
IFSKP. ;Yes...
|
||
CALL XMTDON ;(T1,T2)Do scheduler level transmit done stuff
|
||
JRST MSGNXT ; and continue with next message
|
||
ENDIF.
|
||
MOVE RB,T2 ;Message address obtained
|
||
SKIPE T1,UN.SPI+UNB.OF(RB);Was there an error?
|
||
JRST MSGDON ;Re-post and ignore
|
||
OPSTRM <AOS>,HCRCV,(HN) ;Increment count of received messages
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB) ;[7.1120]Get the message type from the buffer
|
||
MOVE T1,T2 ;[7.1120]
|
||
LSH T1,-2 ;Shift off the M and RRF bits
|
||
CAIL T1,MINMTY ;Range check message type
|
||
CAILE T1,MAXMTY ;...
|
||
IFNSK.
|
||
BUG. (CHK,LATIMT,LATSER,SOFT,<LAT Illegal Message Type>,<<T1,MSGTYP>>,<
|
||
|
||
Cause: The LAT virtual circuit message was received with a message type out
|
||
of range.
|
||
|
||
Data: MSGID - Message type
|
||
|
||
>)
|
||
ELSE.
|
||
TRNE T2,MSB.FL ;[7.1155]Test the Master/Slave bit
|
||
IFSKP. ;[7.1155]If it's a slave message...
|
||
CAIE T1,MT.RIN ;[7.1155]Is it a Response Information Message
|
||
CAIN T1,MT.STS ;[7.1155] or a status message?
|
||
TRNA ;[7.1155] Yes, skip
|
||
JRST MSGDON ;[7.1155] No. Ignore for now
|
||
ENDIF. ;[7.1155]
|
||
CALL @MSGDSP-MINMTY(T1) ;Dispatch to process the message
|
||
ENDIF.
|
||
MSGDON: CALL RELRBF ;(RB)Ignore for now
|
||
JRST MSGNXT
|
||
|
||
|
||
MIN. (MINMTY,<MT.RUN,MT.STA,MT.STP,MT.STS,MT.RIN>) ;[7.1120]Minimum message type code
|
||
MAX. (MAXMTY,<MT.RUN,MT.STA,MT.STP,MT.STS,MT.RIN>) ;[7.1120]Maximum message type code
|
||
|
||
|
||
MSGDSP: XADDR. HMRUN ;[7.1052]RUN message received
|
||
XADDR. HMSTRT ;[7.1052]START message received
|
||
XADDR. HMSTOP ;[7.1052]STOP message received
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. HMSTAT ;[7.1120]STATUS message received
|
||
XADDR. RTN ;[7.1120]
|
||
XADDR. HMINFO ;[7.1120]RESPONSE INFORMATION received
|
||
;MOVNIQ - Move all messages on the NI queue to the Scheduler queue
|
||
|
||
;Call: T1/ Pointer to head of NIQ
|
||
; T2/ Pointer to tail of NIQ
|
||
; CALL MOVNIQ
|
||
; Normal return
|
||
;
|
||
;Uses: T3,T4
|
||
|
||
MOVNIQ:
|
||
IFN FTOPS20,<
|
||
CHNOFF NIPIA ;Turn off NI interrupts
|
||
>
|
||
IFN FTOPS10,<
|
||
ETHLOK ;Turn off NI interrupts
|
||
>
|
||
DMOVE T1,HN.NIQ(HN) ;Get the header contents
|
||
SETZM HN.NIQ(HN) ;Clear the queue begin pointer
|
||
SETZM HN.NIQ+1(HN) ;Clear the end pointer
|
||
IFN FTOPS20,<
|
||
CHNON NIPIA ;Turn NI back on
|
||
>
|
||
IFN FTOPS10,<
|
||
ETHULK ;Turn NI back on
|
||
>
|
||
OPSTR <SKIPN T3,>,HNSCQ,+1(HN);Is there anything on the queue?
|
||
IFSKP. ;YES
|
||
STOR T1,UELW1,(T3) ;Add new elements at the queue tail.
|
||
ELSE. ;NO
|
||
STOR T1,HNSCQ,(HN) ;New queue header forward pointer
|
||
ENDIF.
|
||
STOR T2,HNSCQ,+1(HN) ;New queue header tail pointer.
|
||
RET
|
||
SUBTTL LATLSC - Ethernet Link State Change Callback
|
||
|
||
;LATLSC - Process an asynchronous link state change
|
||
|
||
;Call: T1/ NU.RCI
|
||
; T2/ UN block address
|
||
; Normal return
|
||
;
|
||
|
||
LATLSC: MOVX T3,HNRUN
|
||
TMNN UNRUN,(T2) ;[7.1039]Is the NI running?
|
||
IFSKP. ;[7.1039]
|
||
ANDCAM T3,HN.FLG(HN) ;[7.1039]NI is up
|
||
MOVEI T1,1 ;[7.1039]So if multicast timer
|
||
SKIPLE LATMCT ;[7.1039] is running...
|
||
MOVEM T1,LATMCT ;[7.1039] set it to ring soon.
|
||
ELSE. ;[7.1039]
|
||
IORM T3,HN.FLG(HN) ;NI went down.
|
||
ENDIF.
|
||
RET
|
||
;[7.1120]
|
||
;MSBGN - Parse the beginning of the RUN, START, and STOP messages.
|
||
;
|
||
; RB/ Address of message block
|
||
; CALL MSBGN
|
||
; Return+1: Always
|
||
|
||
MSBGN: OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB)
|
||
MOVEM T1,NSLOTS ;Get number of slots in message
|
||
DECR UNBSZ,+UNB.OF(RB) ;Reduce byte count by two
|
||
DECR UNBSZ,+UNB.OF(RB)
|
||
CALL LAG2BY ;Get the destination ID from msg
|
||
MOVEM T1,MSGDID ; (2 bytes, unsigned)
|
||
CALL LAG2BY ;Get the source id from the msg
|
||
MOVEM T1,MSGSID ; (2 bytes, unsigned)
|
||
CALL LAG2BY ;Get the ACK/SEQ field from msg
|
||
MOVEM T1,MSGACK ; (2 bytes, unsigned)
|
||
RET ;
|
||
SUBTTL Message Receiver - HMSTRT
|
||
|
||
|
||
;HMRUN - Process a Host START Message
|
||
;
|
||
; RB/ Address of receive buffer
|
||
; CB/ Address of circuit block
|
||
; HN/ Address of host node data base
|
||
; CALL HMSTRT
|
||
; Return+1: Always
|
||
|
||
HMSTRT: CALL MSBGN ;[7.1120](RB)Parse the beginning
|
||
TMNN HNCIP,(HN) ;If the START message template is locked
|
||
SKIPN MSGSID ;or source's message handle is 0
|
||
RET ; ignore since server will persist.
|
||
LOAD T1,HNLAS,(HN) ;[7.1039]If LAT access state is not ON, ignore
|
||
CAIE T1,LS.ON ;[7.1039] the START message.
|
||
RET ;[7.1039] ...
|
||
LOAD T1,HNNAC,(HN) ;If the addition of this circuit brings total
|
||
OPSTR <CAML T1,>,HNMAC,(HN); over the maximum number of active circuits
|
||
JSP T2,NOCRE0 ;[7234] then reject it.
|
||
CALL HSTRCB ;(RB/CB)Find CB associated with this circuit.
|
||
RET ;None. Error action already taken.
|
||
LOAD T1,CBSTA,(CB) ;Get the current circuit state
|
||
CAIE T1,CS.RUN ;[7.1039]If the state is running,
|
||
IFSKP. ;[7.1039]
|
||
CALL RELSBS ;[7.1039](CB)Release all current slots
|
||
CALL RFXBFS ;[7.1039](CB)Release all buffers on free queue
|
||
CALL MDLXBF ;[7.1039](CB)Make all buffers on ACK queue for later release
|
||
ENDIF. ;[7.1039]
|
||
CALL GETXBH ;(CB)Get necessary number of transmit buffer
|
||
SKIPA ; headers (+MSD pointers)
|
||
CALL GETRBF ;(HN)Go see if we need more receive buffers
|
||
JSP T2,NOCRES ;Could not get the necessary buffer quota
|
||
CALL CBINIT ;(CB,RB)Initialize all host CB parameters
|
||
RET ;START message format bad. Error action done.
|
||
CALL MTTSTR ;()Send a START message
|
||
MOVEI T1,CS.STA ;Put the circuit into the
|
||
STOR T1,CBSTA,(CB) ; STARTING state.
|
||
IFN FTOPS10,<
|
||
MOVEI T1,MAXXBF+1 ;New circuit, add some buffers
|
||
CAMLE T1,LATNFB ;Are there already enough free buffers?
|
||
ADDM T1,LATWFB ;No, ask for some more
|
||
>;END IFN FTOPS10
|
||
RET
|
||
SUBTTL HSTRCB
|
||
|
||
;HSTRCB - Find the circuit block for a received START msg on a LAT host.
|
||
|
||
;Call: RB/ address of received message block
|
||
; CALL HSTRCB
|
||
; Error Return - CB not found
|
||
; Normal Return
|
||
; CB/ Circuit Block address
|
||
|
||
HSTRCB: XMOVEI T1,HN.QIC(HN) ;Search the inactive CB queue first
|
||
CALL CMNIAD ;(T1,RB/CB)Look for NI address match
|
||
SKIPA ;Not found on the inactive CB queue
|
||
JRST CBIFND ;Correct CB found on inactive CB queue
|
||
NFND1: XMOVEI T1,HN.QAC(HN) ;Not on inactive Q, try active Q
|
||
CALL CMNIAD ;(T1,RB/CB)Look for NI address match
|
||
SKIPA ;Not on active queue either
|
||
JRST CBAFND ;Active CB has been found
|
||
NFND2: LOAD T2,HNNAC,(HN) ;Get number of currently active CBs
|
||
OPSTR <CAML T2,>,HNMXC,(HN) ;Compare with maximum allowed
|
||
IFSKP. ;Not at maximum number of CBs allowed
|
||
MOVEI T1,CC.LST ;The number of words to get for a CB
|
||
CALL MMGTZW ;(T1/T1)Go get them
|
||
JSP T2,NOCRES ;Failed
|
||
MOVE CB,T1 ;This is the new CB address
|
||
MOVEI T1,CS.HLT ;Don't assume that the halted state
|
||
STOR T1,CBSTA,(CB) ; is zero.
|
||
OPSTRM <AOS>,HNNCC,(HN);Increment number of allocated CBs.
|
||
JRST CBALNW ;Allocated new CB successfully
|
||
ENDIF.
|
||
OPSTR <SKIPN CB,>,QLBWD,+HN.QIC(HN);Check inactive Q for free CB
|
||
JSP T2,NOCRES ;None, so can't reuse an inactive CB
|
||
CBIFND: MOVE T2,CB ;Remove from inactive CB queue
|
||
CALL LAUNQ ;(T1,T2)
|
||
CBALNW: CALL CBGNIX ;(CB)Get next assignable index for the CB
|
||
XMOVEI T1,HN.QAC(HN) ;Put at the front of the active
|
||
MOVE T2,CB ; CB
|
||
CALL LAQUE ;(T1,T2) queue
|
||
OPSTRM <AOS>,HNNAC,(HN) ;New active circuit. Count it.
|
||
SETONE CBSTA,(CB) ;Set state to non-HALTED since now active
|
||
OPSTRM <AOS>,CCRCV,(CB) ;Increment per server count
|
||
OPSTR <DMOVE T1,>,UNSAD,+UNB.OF(RB);Move the source NI address from
|
||
OPSTRM <DMOVEM T1,>,CBDNI,(CB) ; message to the CB
|
||
CBAFND: RETSKP ;Return success
|
||
SUBTTL CBINIT - Circuit Block Initialization
|
||
|
||
;CBINIT - Initialize a Circuit Block from the Contents of a START Message
|
||
|
||
;Call: CB/ Address of Circuit Block
|
||
; RB/ Address of Message Block
|
||
; CALL CBINIT
|
||
; Error Return - START Message content in error.
|
||
; Normal Return
|
||
|
||
CBINIT: MOVEI T1,MSTMSI ;Check to see if the message is at least
|
||
OPSTR <CAMLE T1,>,UNBSZ,+UNB.OF(RB); the minimum size for a START msg
|
||
JSP T2,ILLMES ;No, too short.
|
||
SETZM CLRBEG(CB) ;Clear the region which must be initialized
|
||
MOVEI T1,<CLREND-CLRBEG>; to zero when a circuit block is
|
||
XMOVEI T2,CLRBEG(CB) ; re-used.
|
||
XMOVEI T3,CLRBEG+1(CB) ; ...
|
||
XBLT. T1 ; ...
|
||
MOVE T1,MSGSID ;Move source's circuit ID from message
|
||
STOR T1,CBRID,(CB) ; to circuit block
|
||
CALL LAG2BY ;(MA/T1)Get maximum transmit frame size which
|
||
STOR T1,CBMTF,(CB) ; the remote will allow
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);LAT protocol version used by remote
|
||
CAIL T1,LALPV ;Check if in the range of version supported
|
||
CAILE T1,LAHPV ; by this node
|
||
JSP T2,LVSKEW ;Out of range, return error
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Remote's protocol ECO level
|
||
LSH T2,^D9 ;Shift protocol version
|
||
IOR T1,T2 ;OR version and ECO level
|
||
STOR T1,CBRPV,(CB) ; and store as single unit
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Maximum number of slots in VC message
|
||
STOR T1,CBMSL,(CB) ; permitted by remote
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Number of additional receive buffers
|
||
STOR T1,CBNBF,(CB) ; queued by remote for this circuit
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Remote's circuit timer value
|
||
STOR T1,CBCTI,(CB) ;
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Remote's keep-alive timer value
|
||
STOR T1,CBKTI,(CB) ;
|
||
IMULI T1,^D2000 ;[7.xxxx]Convert to ms and multiply by 2 (fudge factor)
|
||
STOR T1,CBKAV,(CB) ; and store in keep alive value field.
|
||
MOVX T1,-^D6 ;Decrement residual message count by what we
|
||
OPSTRM <ADDM T1,>,UNBSZ,+UNB.OF(RB); have read so far.
|
||
CALL LAG2BY ;(MA/T1)Get the "facility number"
|
||
STOR T1,CBNUM,(CB)
|
||
CALL LAG2BY ;(MA/T1)Get the product type code
|
||
STOR T1,CBPTC,(CB)
|
||
MOVEI T1,0 ;Skip the circuit name
|
||
CALL GTCSTR ;(T1,T2,RB)
|
||
JSP T2,ILLMES ;Illegally formatted message
|
||
MOVEI T1,ML.SYS ;Maximum length of system's name string
|
||
XMOVEI T2,CB.SNM(CB) ;Where copy the name string
|
||
TXO T2,<OWGP. 7,0>
|
||
CALL GTCSTR ;(T1,T2,RB)
|
||
JSP T2,ILLMES ;Illegally formatted message
|
||
STOR T1,CBRSC,(CB) ;Save the length of the name string
|
||
MOVEI T1,ML.LOC ;Maximum length of the system's location string
|
||
XMOVEI T2,CB.LOC(CB) ;Where to copy the location string
|
||
TXO T2,<OWGP. 7,0>
|
||
CALL GTCSTR ;(T1,T2,RB)
|
||
JSP T2,ILLMES ;Illegally formatted message
|
||
STOR T1,CBRLC,(CB) ;Save the length of the location string
|
||
RETSKP
|
||
SUBTTL CMNIAD - Find CB base on NI address
|
||
|
||
;CMNIAD - search the CBs on a CB queue looking for one which has the same
|
||
; NI address as the source NI address in the incoming message.
|
||
|
||
;Call: T1/ Queue header of CB queue to search
|
||
; RB/ Address of the circuit message
|
||
; CALL CMNIAD
|
||
; Not found return
|
||
; Success return
|
||
; T1/ unchanged
|
||
; CB/ circuit block address if found, 0 otherwise
|
||
|
||
CMNIAD: LOAD CB,QLFWD,(T1) ;Get the first queue entry
|
||
CMLOOP: JUMPE CB,RTN ;Is this last entry?
|
||
LOAD T3,CBDNI,(CB) ;First 4 bytes of remote NI address from CB
|
||
LOAD T4,CBDNI,+1(CB) ;Last 2 bytes
|
||
OPSTR <CAMN T3,>,UNSAD,+UNB.OF(RB);Compare with message destination adr
|
||
OPSTR <CAME T4,>,UNSAD,+<UNB.OF+1>(RB) ;...
|
||
IFNSK.
|
||
LOAD CB,QLFWD,+CB.LNK(CB); Get next forward CB
|
||
JRST CMLOOP ;Try again
|
||
ENDIF.
|
||
RETSKP ;Return success
|
||
;CBGNIX - Get the next assignable index for a CB
|
||
|
||
;Call: CB/ address of circuit block
|
||
; CALL CBGNIX
|
||
; Normal Return
|
||
;
|
||
; This routine is called each time a CB is to be used for a new LAT
|
||
; virtual circuit. The old index vector (CBVECT) pointer to the CB
|
||
; is deleted and a new index is generated.
|
||
|
||
CBGNIX: MOVE W1,CBVECT ;Get the address of the CB index vector
|
||
OPSTR <SKIPN T2,>,CBLID,(CB);Get the old circuit index, if any.
|
||
IFSKP.
|
||
ADD T2,W1 ;Get the address of the pointer to this CB
|
||
SETZM (T2) ; in the CB index vector and clear it.
|
||
ENDIF.
|
||
LOAD T2,HNNXI,(HN) ;Get the next available index to assign
|
||
STOR T2,CBLID,(CB) ;Set the new index in the CB
|
||
MOVE T1,W1 ;Address of teh CB index vector
|
||
ADD T1,T2 ;Offset into this vector for new index
|
||
MOVEM CB,(T1) ;Set the new pointer to point to new CB
|
||
CBGNX0: AOS T2 ;Increment the next available index
|
||
AOS T1 ; and the corresponding index vector pointer
|
||
CAIG T2,CBMAXI ;Time to wrap around?
|
||
IFSKP. ;Yes
|
||
MOVEI T2,1 ;Always start at 1
|
||
MOVE T1,W1
|
||
ENDIF.
|
||
SKIPE (T1) ;Is this vector entry free?
|
||
JRST CBGNX0 ;No, try next
|
||
STOR T2,HNNXI,(HN) ;Store new "next assignable index"
|
||
RET
|
||
SUBTTL HMRUN
|
||
|
||
|
||
;HMRUN - Process a Host RUN Message
|
||
;
|
||
; RB/ Address of receive buffer
|
||
; CB/ Address of circuit block
|
||
; HN/ Address of host node data base
|
||
; CALL HMRUN
|
||
; Return+1: Always
|
||
|
||
HMRUN: CALL MSBGN ;[7.1120](RB)Parse the beginning
|
||
CALL HRUNCB ;(RB/CB)Get the circuit block address
|
||
RET ;None, error action already comleted
|
||
SKIPE T2,MSGDID ;Destination and source circuit IDs from
|
||
SKIPN T1,MSGSID ; the message may not be zero
|
||
JSP T2,ILLMES ;If so, it is illegal
|
||
LOAD T3,CBRID,(CB) ;Get the remote's circuit index from the CB
|
||
LOAD T4,CBLID,(CB) ; and our circuit index from the CB must match
|
||
CAMN T1,T3 ; the source id and
|
||
CAME T2,T4 ; the destination id from the msg.
|
||
JSP T2,INVRUN ;Invalid RUN msg, go terminate the circuit.
|
||
MOVE T1,TODCLK ;Get current time
|
||
STOR T1,CBKAT,(CB) ;Save time for keep-alive process
|
||
MOVEI T1,CS.RUN ;Put in RUNNING state if not there already
|
||
STOR T1,CBSTA,(CB) ;Store state in CB
|
||
MOVE T1,MSGACK ;Get the SEQ/ACK number
|
||
MOVE W1,T1 ;
|
||
ANDI T1,377 ;Received message sequence number
|
||
LSH W1,-^D8 ;Last message ack'd by remote
|
||
LOAD T3,CBRSQ,(CB) ;Previous recv SEQ number
|
||
AOS T3 ;Increment
|
||
ANDI T3,377 ;Modulo 256
|
||
CAME T1,T3 ;Is is the expected sequence number
|
||
IFSKP.
|
||
STOR T1,CBRSQ,(CB) ;Update expected sequence number for next time
|
||
ELSE.
|
||
SETZM NSLOTS ;No, ignore any slots in this message
|
||
OPSTRM <AOS>,HCSEQ,(HN);Increment Host's count
|
||
OPSTRM <AOS>,CCSEQ,(CB);Increment per-server count
|
||
ENDIF.
|
||
LOAD T3,CBLRA,(CB) ;Previous "last ACK from remote"
|
||
STOR W1,CBLRA,(CB) ;New "last ACK from remote"
|
||
CAMGE W1,T3 ;Is new ACK less than old ACK?
|
||
ADDI W1,^D256 ;Yes, new ACK has wrapped around
|
||
SUB W1,T3 ;Number of messages ACK'd by this msg
|
||
CAILE W1,MAXXBF ;Range check it and if out of range
|
||
JSP T2,ILLMES ; treat as an illegal message
|
||
SKIPN W1 ;If anything got ACK'd
|
||
IFSKP.
|
||
SETZRO CBRTC,(CB)
|
||
ENDIF.
|
||
NXTACK: JUMPE W1,ACKDON ;No new messages ACK'd
|
||
MOVE XB,CB.AKQ(CB) ;Sneak look at buffer at head of Q
|
||
CALL RELXBF ;(XB)Free large MSD buffer.
|
||
XMOVEI T1,CB.AKQ(CB) ;Unqueue the now acknowledged buffers
|
||
CALL UNQ1WF ;(T1/T2) from the ACK wait queue
|
||
JSP T2,ILLMES ;Should not happen
|
||
XMOVEI T1,CB.XBQ(CB) ;Queue them back to the transmit buffer
|
||
CALL QUE1WB ;(T1,T2) queue.
|
||
SOJA W1,NXTACK
|
||
ACKDON: OPSTR <SKIPN>,CBAKQ,(CB);If all messages ack'd
|
||
SETZRO CBTIM,(CB) ; clear the circuit timer.
|
||
SETONE CBMRS,(CB) ;Indicate we must respond to this msg "soon"
|
||
CALL LSDMUX ;(RB)Go process all slots in the RUN message
|
||
IFNSK. ;Invalid slot type returned.
|
||
BUG. (INF,LATIST,LATSER,SOFT,<LAT Illegal Slot Type>,<<T2,SLTID>>,<
|
||
|
||
Cause: LAT Slot received with Slot type out of range.
|
||
|
||
Data: SLTID - Slot ID
|
||
|
||
>)
|
||
MOVEI T1,CE.ILL ;Set up stop reason code.
|
||
CALL MTTSTP ;(T1,XB,RB,CB)Illegal slot, kill the circuit
|
||
ENDIF.
|
||
RET ;All slots processed, return receive buffer
|
||
SUBTTL HSTRCB
|
||
|
||
;HRUNCB - Find the circuit block for a received RUN/STOP msg on a LAT host.
|
||
|
||
;Call: RB/ address of received message block
|
||
; CALL HRUNCB
|
||
; Error Return - CB not found
|
||
; Normal Return
|
||
; CB/ Circuit Block address
|
||
;
|
||
|
||
HRUNCB: SKIPN CB,MSGDID ;Index to CB from received message
|
||
JSP T2,ILLMS0 ;Zero message destination index is illegal
|
||
CAIG CB,CBMAXI ;If CB index is greater than our max
|
||
IFSKP.
|
||
SETZ CB, ;it's also illegal, so flag no circuit
|
||
JSP T2,ILLMS0 ;and go send a stop message
|
||
ENDIF.
|
||
ADD CB,CBVECT ;Add address of vector of pointers to CBs
|
||
SKIPN CB,(CB) ;The real circuit block address
|
||
JSP T2,INVRUN ;Circuit probably went away.
|
||
OPSTR <DMOVE T3,>,CBDNI,(CB);All 6 bytes of remote NI address from CB
|
||
OPSTR <CAMN T3,>,UNSAD,+UNB.OF(RB);Compare with message destination adr
|
||
OPSTR <CAME T4,>,UNSAD,+<UNB.OF+1>(RB)
|
||
SKIPA ;Not the right CB
|
||
JRST HRNFND ;Found the CB
|
||
XMOVEI T1,HN.QAC(HN) ;Try searching the active Q
|
||
CALL CMNIAD ;(T1,RB/CB)
|
||
SKIPA ;Not there either
|
||
JRST HRNFND ;Found the CB
|
||
XMOVEI T1,HN.QIC(HN) ;Try searching the inactive Q
|
||
CALL CMNIAD ;(T1,RB/CB)
|
||
JSP T2,ILLMES ;Non-existent CB. Treat as illegal message.
|
||
HRNFND: OPSTRM <AOS>,CCRCV,(CB) ;Increment per-server count
|
||
RETSKP ;Found the CB
|
||
SUBTTL HMSTOP
|
||
|
||
|
||
;HMSTOP - Process a Host STOP Message
|
||
;
|
||
; RB/ Address of receive buffer
|
||
; CB/ Address of circuit block
|
||
; HN/ Address of host node data base
|
||
; CALL HMSTOP
|
||
; Return+1: Always
|
||
|
||
HMSTOP: CALL MSBGN ;[7.1120](RB)Parse the beginning
|
||
CALL HRUNCB ;(RB/CB)Get the CB for this STOPS message
|
||
RET ;None, error action already done
|
||
SKIPE MSGSID ;Is the source ID in MSG non-zero?
|
||
JSP T2,ILLMES ;Yes, that's not legal
|
||
LOAD T1,CBLID,(CB) ;Get our remote ID for circuit. It must be
|
||
LOAD T2,CBSTA,(CB) ;Current circuit state
|
||
CAIE T2,CS.HLT ;[7481]Is it halted or
|
||
CAME T1,MSGDID ; an invalid STOP message?
|
||
RET ;[7481]Yes, just ignore it.
|
||
CALLRET CBKILL ;[7481](CB)Release all CB resources and
|
||
;[7481] put it on the inactive queue
|
||
|
||
|
||
; Routines to terminate a circuit because of some error. T1 contains
|
||
; the error to be entered into the STOP message.
|
||
|
||
ILLMES: OPSTRM <AOS>,CCIMR,(CB) ;Increment per-server count
|
||
ILLMS0: OPSTRM <AOS>,HCIMR,(HN) ;Increment host count
|
||
MOVEI T1,CE.ILL ;Illegally formatted message received
|
||
JRST INFSTP ;Join common code to kill off circuit
|
||
|
||
LVSKEW: MOVEI T1,CE.SKW ;Version skew between server and host,
|
||
JRST INFSTP ; cannot support connection.
|
||
|
||
NOCRES: OPSTRM <AOS>,CCIMR,(CB) ;Increment per-server count
|
||
NOCRE0: OPSTRM <AOS>,HCIMR,(HN) ;Increment host count
|
||
MOVEI T1,CE.RES ;Insufficient resources to support new circuit.
|
||
JRST INFSTP
|
||
|
||
XMTLIM: MOVEI T1,CE.LIM ;Retransmit limit exceeded. Server probably
|
||
JRST INFSTP ; has gone away.
|
||
|
||
IDLHLT: MOVEI T1,CE.NSL ;Circuit halted because there are no more slots
|
||
JRST MTTSTP
|
||
|
||
LCLHLT: MOVEI T1,CE.HLT ;Circuit halted by local system. Either stopped
|
||
JRST MTTSTP ; by operator or last slot has disconnected.
|
||
|
||
IFN FTOPS20,<
|
||
NIHALT: MOVEI T1,CE.NIH ;NI halted
|
||
SETZ T2,0 ;PC meaningless
|
||
JRST INFSTP
|
||
>;END IFN FTOPS20
|
||
|
||
INVRUN: MOVEI T1,CE.INV ;Invalid message
|
||
JRST INFSTP
|
||
INFSTP: OPSTR <DMOVE T3,>,CBDNI,(CB) ;[7369]GET ADDRESS IN T3 AND T4
|
||
BUG. (INF,LATNSC,LATSER,SOFT,<LAT Host node stopped circuit>,<<T1,CODE>,<T2,PC>,<T3,HIADDR>,<T4,LOADDR>>,<
|
||
|
||
Cause: LAT Host node stopped the circuit.
|
||
|
||
Action: Look at the Reason Code in T1 and the PC in T2. This error, if
|
||
relatively infrequent is nothing to be concerned about. If it occurs
|
||
frequently, use the CODE and PC to determine further action.
|
||
HIADDR and LOADDR specify the Ethernet address of the remote
|
||
server whose circuit has been stopped.
|
||
|
||
Data: CODE - Reason code
|
||
PC - PC
|
||
HIADDR - High order 32 bits of Ethernet address
|
||
LOADDR - Low order 16 bits of Ethernet address
|
||
>) ;[7369]
|
||
JRST MTTSTP
|
||
SUBTTL HMSTAT -- Receive Status Message
|
||
|
||
|
||
;[7.1120]
|
||
;HMSTAT - Receive a Status Message
|
||
;
|
||
; RB/ Address of message block
|
||
; CALL HMSTAT
|
||
; Return+1: Always
|
||
|
||
HMSTAT: STKVAR <NENTRY> ;
|
||
LOAD W1,UNBSZ,+UNB.OF(RB) ;Get the length of the message
|
||
CAIGE W1,^D12 ;Is it at least this big?
|
||
RET ;No, invalid message
|
||
LOAD W2,UNBFA,+UNB.OF(RB) ;Get the byte pointer for the message
|
||
MOVEI T4,3 ;Point to the current protocol version
|
||
ADJBP T4,W2 ;
|
||
ILDB T1,T4 ;Get the current protocol version
|
||
ILDB T2,T4 ;Get the current protocol ECO
|
||
CAXL T1,PROVER ;
|
||
CAXGE T2,PROECO ;Is it what we expect?
|
||
RET ;No, invalid message
|
||
ADDI T4,1 ;Point to the number of entries
|
||
ILDB T1,T4 ;Get the number of entries
|
||
JUMPE T1,RTN ;No entries: nothing to be done
|
||
MOVEM T1,NENTRY ;
|
||
ILDB W2,T4 ;Get the length of the subject name
|
||
TRNE W2,1 ;Is it an even number?
|
||
ADDI W2,1 ;No, it has a pad character
|
||
ADJBP W2,T4 ;Build a byte pointer to the entry
|
||
HMSTA1: ILDB W1,W2 ;Get the length of the entry
|
||
CAIL W1,^D14 ;Is it at least this big?
|
||
CALL RDSTA ;(W1,W2)Yes, handle this status entry
|
||
SOSGE NENTRY ;Is there another entry?
|
||
RET ;No, finished
|
||
ADJBP W1,W2 ;Point to the next entry
|
||
MOVEM W1,W2 ;
|
||
JRST HMSTA1 ;Parse the next entry
|
||
;[7.1120]
|
||
;RDSTA - Handle an entry for a Status message
|
||
;
|
||
; W1/ Length of this entry
|
||
; W2/ Byte pointer to this entry
|
||
; RB/ Address of message block
|
||
; CALL RDSTA
|
||
; Return+1: Always
|
||
|
||
RDSTA: SAVEAC <W2> ;Don't trash W2...
|
||
ILDB T3,W2 ;Get the entry status
|
||
ILDB T4,W2 ;Get the entry error
|
||
IBP W2 ;
|
||
ILDB SB,W2 ;Get the LO byte of the request id
|
||
ILDB T1,W2 ;Get the HO byte of the request id
|
||
LSH T1,^D8 ;Assemble the request id
|
||
ADD SB,T1 ;
|
||
MOVEM SB,T1 ;Save a copy for later
|
||
ANDI SB,PR.NDX ;Throw away the random portion
|
||
SKIPE SB ;
|
||
CAILE SB,PRMAXI ;Is it a valid request id?
|
||
RET ;No, invalid message
|
||
ADD SB,PRVECT ;Calculate address of PRVECT entry
|
||
SKIPN SB,(SB) ;Is this pending request block in use?
|
||
RET ;No, invalid request id
|
||
OPSTR <CAME T1,>,PRCID,(SB) ;Does it match this connect id?
|
||
RET ;No, invalid request id
|
||
ILDB T1,W2 ;Get the LO byte of the entry id
|
||
ILDB T2,W2 ;Get the HO byte of the entry id
|
||
LSH T2,^D8 ;Assemble the entry id
|
||
ADD T1,T2 ;
|
||
SKIPE T1 ;Is there an entry id?
|
||
STOR T1,PREID,(SB) ;Yes, save it
|
||
TXNE T3,1_7 ;Is the request rejected?
|
||
JRST RDSTA1 ;Yes, special handling
|
||
|
||
; ..
|
||
; ..
|
||
|
||
; Come here when the request is accepted: save the queue depth.
|
||
;
|
||
LOAD T1,PRSTA,(SB) ;Get the current (internal) state
|
||
CAXE T1,SS.SAC ;Solicit Access state
|
||
CAXN T1,SS.QUE ; or Queued state?
|
||
TRNA ;Yes, save the queue depth
|
||
RET ;No, ignore this message
|
||
IBP W2 ;Skip past the queue timer
|
||
IBP W2 ;
|
||
ILDB T1,W2 ;Get the LO byte of the queue position
|
||
ILDB T2,W2 ;Get the HO byte of the queue position
|
||
LSH T2,^D8 ;Assemble the queue position
|
||
ADD T1,T2 ;
|
||
STOR T1,PRQDP,(SB) ;Save the queue depth
|
||
MOVX T1,SS.QUE ;
|
||
LOAD T2,PRSTA,(SB) ;Get the current (internal) state
|
||
CAXE T2,SS.SAC ;Is this the Soliciting Access state?
|
||
RET ;No, return (do not change state)
|
||
STOR T1,PRSTA,(SB) ;Yes, change to Queued state
|
||
MOVX T1,.LAQUE ;[7.1155]Set the external status to queued
|
||
STOR T1,PRSTS,(SB) ;
|
||
HRLOI T1,377777 ;Set the retransmit timer so large
|
||
STOR T1,PRCMT,(SB) ; that LATXPR will never see it
|
||
SETZRO PRCMC,(SB) ;
|
||
RET ;
|
||
|
||
; ..
|
||
;..
|
||
|
||
; Come here for a rejection code.
|
||
;
|
||
RDSTA1: MOVX T1,SS.REJ ;
|
||
LOAD T2,PRSTA,(SB) ;Get the current (internal) state
|
||
CALLRET @REJDSP(T2) ;Change state to Reject or delete entry
|
||
|
||
RDSTA2: STOR T1,PRSTA,(SB) ;Change to Reject state
|
||
STOR T4,PRSTS,(SB) ;Return the rejection code
|
||
MOVE T1,SB ;
|
||
CALLRET PRWAKE ;(T1)Wake the job
|
||
|
||
RDSTA3: MOVE T1,SB ;
|
||
CALLRET PRDEL ;(T1)Delete this PRVECT entry
|
||
|
||
; Table of states for the PRVECT entries
|
||
;
|
||
REJDSP: XADDR. RTN ;(0) Halt
|
||
XADDR. RTN ;(1) Run
|
||
XADDR. RTN ;(2) Solicit Information
|
||
XADDR. RTN ;(3) Solicit Access (initialize first)
|
||
XADDR. RDSTA2 ;(4) Solicit Access
|
||
XADDR. RDSTA2 ;(5) Queued
|
||
XADDR. RTN ;(6) Rejected
|
||
XADDR. RTN ;(7) Timed Out
|
||
XADDR. RDSTA3 ;(8) Cancel (initialize first)
|
||
XADDR. RDSTA3 ;(9) Cancel
|
||
REJMAX==.-REJDSP-1
|
||
IF1,<IFL <REJMAX-SS.MAX>,<PRINTX ?Entries missing in REJDSP>>
|
||
SUBTTL HMINFO -- Receive Response Information Message
|
||
|
||
|
||
;[7.1120]
|
||
;HMINFO - Receive a Response Information Message
|
||
;
|
||
; RB/ Address of message block
|
||
; CALL HMINFO
|
||
; Return+1: Always
|
||
|
||
HMINFO: LOAD W1,UNBSZ,+UNB.OF(RB) ;Get the length of the message
|
||
CAIGE W1,^D20 ;Is it at least this long?
|
||
RET ;No, invalid message
|
||
LOAD W2,UNBFA,+UNB.OF(RB) ;Get the byte pointer for the message
|
||
MOVEI T4,3 ;Point to the current protcol version
|
||
ADJBP T4,W2 ;
|
||
ILDB T1,T4 ;Get the current protcol version
|
||
ILDB T2,T4 ;Get the current protocol ECO
|
||
CAXL T1,PROVER ;
|
||
CAXGE T2,PROECO ;Is it what we expect?
|
||
RET ;No, invalid message
|
||
IBP T4 ;Skip data link frame size
|
||
IBP T4 ;...
|
||
ILDB SB,T4 ;Get the LO byte of the solicit id
|
||
ILDB T1,T4 ;Get the HO byte of the solicit id
|
||
LSH T1,^D8 ;Assemble the solicit id
|
||
ADD SB,T1 ;
|
||
MOVE T1,SB ;Save a copy of it.
|
||
ANDI SB,PR.NDX ;Throw away the random portion
|
||
SKIPE SB ;
|
||
CAILE SB,PRMAXI ;Is it a valid solicit id?
|
||
RET ;No, invalid message
|
||
ADD SB,PRVECT ;Calculate address of PRVECT entry
|
||
SKIPN SB,(SB) ;Is this pending request block in use?
|
||
RET ;No, invalid solicit id
|
||
OPSTR <CAME T1,>,PRCID,(SB) ;Is it this one?
|
||
RET ;No, invalid solicit id
|
||
ILDB T2,T4 ;Get LO byte of the Response Status
|
||
ILDB T1,T4 ;Get HI byte of the Response Status
|
||
LSH T1,^D8 ;Assemble the response status
|
||
ADD T1,T2 ;
|
||
TXNE T1,RI%NSS ;Does the node offer the requested service?
|
||
JRST HMIRJ1 ;No. Go reject this request
|
||
ILDB T2,T4 ;Get LO byte of Source Node Status
|
||
ILDB T1,T4 ;Get HI byte of Source Node Status
|
||
LSH T1,^D8 ;Assemble the source node status
|
||
ADD T1,T2 ;
|
||
TXNN T1,RI%NDS ;Is the node disabled?
|
||
TXNN T1,RI%CMD ;No, Can we send a command message?
|
||
JRST HMIRJ2 ;No. Go reject this request
|
||
;
|
||
;
|
||
|
||
; The message has been verified. Save the Ethernet address and set up
|
||
; to transmit the Solicit Access message.
|
||
;
|
||
MOVEI T1,6 ;Get the length of the Ethernet address
|
||
MOVE T2,T4 ;Get the source byte pointer
|
||
XMOVEI T4,PR.DNI(SB) ;Get address of destination
|
||
TXO T4,<OWGP. 8,0> ;Make it a global byte pointer
|
||
CALL MVSTR ;(T1-T4/T3,T4)Move the Ethernet address
|
||
MOVX T1,SS.SAI ;
|
||
LOAD T2,PRSTA,(SB) ;Get the current (internal) state
|
||
CAXE T2,SS.SIN ;Is this the Solicit Information state?
|
||
RET ;No, return
|
||
STOR T1,PRSTA,(SB) ;Yes, change to Solicit Access (init first)
|
||
SETZRO PRCMT,(SB) ;Clear the command message timer
|
||
SETZRO PRCMC,(SB) ; and the retry count
|
||
RET ;
|
||
HMIRJ1: MOVX T1,.LANSS ;Frump up a "No such service" response
|
||
TRNA ;skip
|
||
HMIRJ2: MOVX T1,.LASCS ;Frump up a "Start slot can not be sent"
|
||
STOR T1,PRSTS,(SB) ;Store this in the status field
|
||
MOVX T1,SS.REJ ;Reject the request
|
||
STOR T1,PRSTA,(SB) ;Change state
|
||
HRLOI T2,377777 ;[7.1120]Set the timer to infinity
|
||
STOR T2,PRCMT,(SB) ;[7.xxxx][7.1120] so that LATXPR won't see it
|
||
SETZRO PRCMC,(SB) ;[7.xxxx][7.1120]Clear the command message count
|
||
MOVE T1,SB ;[7.xxxx]
|
||
CALLRET PRWAKE ;[7.1120](T1)Wake the job
|
||
SUBTTL Message Transmit Routines
|
||
|
||
;MTTSTR - transmit a START message
|
||
|
||
;Call: CALL MTTSTR
|
||
; Normal Return
|
||
;
|
||
; This routine builds the START message header in the template from the host
|
||
; node data base and transmits it. It sets the interlock so that the template
|
||
; cannot be changed at process level by the LATOP% JSYS. The message count
|
||
; is not changed since it is already correct (hence LAP2B0 is called instead of
|
||
; LAP2BY). Cannot fail after this point since sending a STOP will clobber
|
||
; the START msg template.
|
||
|
||
MTTSTR: SETONE HNCIP,(HN) ;Set interlock on the msg template
|
||
XMOVEI XB,HN.SMT(HN) ;Address of start message template
|
||
MOVX T1,<POINT 8,<SBF.OF>(XB)>;Set pointer to the message header
|
||
STOR T1,UNBFA,+UNB.OF(XB); for BMSGHD.
|
||
MOVEI T1,<MT.STA_2> ;Build a START
|
||
CALL BMSGHD ;(T1,XB,CB) message header
|
||
XMOVEI T1,<SBF.OF>(XB) ;Build the one word global
|
||
TLO T1,(<OWGP. 8,0>) ;[7.1039] byte pointer.
|
||
STOR T1,UNBFA,+UNB.OF(XB);
|
||
OPSTR <DMOVE T1,>,CBDNI,(CB);
|
||
OPSTRM <DMOVEM T1,>,UNDAD,+UNB.OF(XB);
|
||
LOAD T1,HNPID,(HN) ;Get the Portal ID for NISRV
|
||
STOR T1,UNPID,+UNB.OF(XB)
|
||
MOVX T1,NU.XMT ;Go transmit but don't
|
||
XMOVEI T2,UNB.OF(XB) ; use the usual routine
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI##
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1)
|
||
>
|
||
IFSKP.
|
||
OPSTRM <AOS>,HCXMT,(HN);Increment host count
|
||
OPSTRM <AOS>,CCXMT,(CB);Increment per-server count
|
||
ELSE.
|
||
SETZRO HNCIP,(HN) ;Release the lock
|
||
ENDIF.
|
||
RET
|
||
|
||
|
||
;[7481]
|
||
;CBKILL - Kill a circuit by releasing all slots and buffers
|
||
;
|
||
;Call: CB/ address of the circuit block
|
||
; CALL CBKILL
|
||
; Normal return
|
||
|
||
CBKILL: CALL RELSBS ;(CB/)Release all slots for this CB
|
||
CALL RFXBFS ;(CB/)Release all buffers on
|
||
CALL MDLXBF ;(CB/)free queue and mark all those in DLL
|
||
; CALLRET CBDACT ; and move CB to the inactive queue
|
||
|
||
|
||
;CBDACT - Deactivate CB by moving to inactive queue
|
||
;
|
||
;Call: CB/ address of the circuit block
|
||
; CALL CBDACT
|
||
; Normal return
|
||
|
||
CBDACT: JUMPE CB,RTN ;If there is no CB, don't do the following
|
||
SETZRO CBRID,(CB) ;Clear remote circuit index
|
||
MOVEI T1,CS.HLT ;If the current circuit state is not halted
|
||
OPSTR <CAMN T1,>,CBSTA,(CB); move CB from active to inactive queue
|
||
RET ; otherwise CB is already on inactive queue
|
||
STOR T1,CBSTA,(CB) ;Set the state to halted now
|
||
XMOVEI T1,HN.QAC(HN) ;Remove
|
||
MOVE T2,CB ; the circuit block
|
||
CALL LAUNQ ;(T1,T2) from the active queue
|
||
XMOVEI T1,HN.QIC(HN) ; and queue to
|
||
MOVE T2,CB ;Need the CB address again.
|
||
CALL LAQUE ;(T1,T2) the inactive queue
|
||
OPSTRM <SOS>,HNNAC,(HN) ;Reduce the number of active circuits
|
||
RET
|
||
|
||
;MDLXBF - Remove all buffers from ACK Wait queue, and mark them
|
||
; for deletion at transmit complete.
|
||
|
||
;Call: CB/ circuit block address
|
||
; CALL MDLXBF
|
||
; Normal return
|
||
|
||
MDLXBF: SETZRO CBDLL,(CB) ;No buffers in DLL now
|
||
MDLXB1: XMOVEI T1,CB.AKQ(CB) ;Address of the ACK wait queue
|
||
CALL UNQ1WF ;(T1/T2)Unqueue next buffer on Q
|
||
RET ;Done
|
||
MOVEI T1,0 ;Mark buffer for freeing at xmit done
|
||
EXCH T1,UN.UID+UNB.OF(T2) ;and get current "DLL" flag
|
||
JUMPL T1,MDLXB1 ;If in DLL, it will be freed at XMTDON
|
||
MOVE XB,T2 ; else we have to free it now.
|
||
CALL RELXBH ;(XB)
|
||
JRST MDLXB1
|
||
;MTTSTP - transmit a STOP message
|
||
|
||
;Call: T1/ stop reason code
|
||
; XB/ address of transmit buffer
|
||
; RB/ address of recieve buffer
|
||
; CB/ address of circuit block (may be 0)
|
||
; CALL MTTSTP
|
||
; Normal return
|
||
|
||
MTTSTP: MOVEM T1,STPCOD ;Save the stop reason.
|
||
JUMPE CB,MTTSP0 ;If there is not CB, just send stop msg.
|
||
STOR T1,CBERR,(CB) ;Store reason for the stop in the CB
|
||
LOAD T1,CBRID,(CB) ;Get the id to which to send the STOP
|
||
SKIPE T1 ;[7.1039]If it is zero, assume MSGSID already
|
||
MOVEM T1,MSGSID ;[7.1155][7.1039] has the correct ID. This may
|
||
;[7.1039] prevent sending an illegal STOP with
|
||
;[7.1039] zero in the destination ID field.
|
||
CALL CBKILL ;[7481](CB/)Release all CB resources and
|
||
;[7481] put it on the inactive queue
|
||
;
|
||
; Here to actually send a stop message
|
||
; Always get a temp xmit buffer.
|
||
; Then send the message with a 0 in UNUID so that
|
||
; XMTDON will always just release the buffer.
|
||
;
|
||
MTTSP0: MOVX T1,HNRUN ;If the NI
|
||
TDNE T1,HN.FLG(HN) ; is no longer running
|
||
RET ;We're done.
|
||
MOVEI T1,SZMSTP ;There will be no buffers so get one
|
||
CALL MMGTZW ;(T1/T1)
|
||
RET ;Couldn't. Assume we did.
|
||
MOVE XB,T1 ;Transmit buffer for STOP message
|
||
MOVX T1,<POINT 8,<XBF.OF>(XB)>;Byte pointer to start of msg
|
||
STOR T1,UNBFA,+UNB.OF(XB);Store byte ptr to use building STOP msg
|
||
MOVEI T1,MT.STP_2 ;Message type (STOP) and number of slots (=0)
|
||
CALL LAP2B0 ;(XB,T1) to message
|
||
MOVE T1,MSGSID ;Get the source ID from the received message
|
||
CALL LAP2B0 ;(XB,T1) and enter as dest. ID to msg to send.
|
||
MOVEI T1,0 ;Get a 0 source ID
|
||
CALL LAP2B0 ;(XB,T1) and enter into msg to send
|
||
CALL LAP2B0 ;(XB,T1)Ack and sequence number must be zero.
|
||
MOVE T1,STPCOD ;Enter Disconnect reason and Reason text byte
|
||
CALL LAP2B0 ;(XB,T1) (=0 since text field not used) to msg.
|
||
XMOVEI T1,<XBF.OF>(XB) ;Set up 1 word global byte pointer
|
||
TLO T1,(<OWGP. 8,0>) ; to the transmit data for NISRV
|
||
STOR T1,UNBFA,+UNB.OF(XB); and store in UN block
|
||
MOVEI T1,MINXBF ;Initialize to zero
|
||
STOR T1,UNBSZ,+UNB.OF(XB); the message count
|
||
CALLRET XMTMSN ;(CB,XB,RB)Go give the message to the DLL.
|
||
; It will be freed at XMTDON
|
||
;MTTRUN - transmit a RUN message
|
||
|
||
;Call: XB/ address of the transmit buffer
|
||
; CALL MTTRUN
|
||
; Normal return
|
||
|
||
MTTRUN: JUMPE XB,RTN ;No message to transmit
|
||
XMOVEI T1,CB.XBQ(CB) ;Unqueue the transmit buffer
|
||
CALL UNQ1WF ;(T1/T2) from the free Q
|
||
NOP ;Would not be here if queue empty.
|
||
OPSTR <SKIPE>,CBXBQ,(CB);Is this our last transmit buffer?
|
||
IFSKP.
|
||
SETONE CBRRF,(CB) ;Yes, set the reply requested flag
|
||
LOAD T1,HNTIM,(HN) ;[7.xxxx][7.1120]Value for circuit timer (jiffies)
|
||
ADD T1,TODCLK ;Plus current time
|
||
STOR T1,CBTIM,(CB) ;Store in circuit timer
|
||
ENDIF.
|
||
XMOVEI T1,CB.AKQ(CB) ; and queue to the end
|
||
CALL QUE1WB ;(T1,T2) of the ACK queue
|
||
LOAD T1,CBTSQ,(CB) ;Get the transmit sequence number
|
||
AOJ T1, ; and increment it by one before
|
||
STOR T1,CBTSQ,(CB) ; using it in the next transmitted msg.
|
||
MOVX T1,<POINT 8,<XBF.OF>(XB)>;Set message pointer to point to
|
||
STOR T1,UNBFA,+UNB.OF(XB); the RUN message header.
|
||
MOVEI T1,MT.RUN_2 ;Message type for the header.
|
||
CALL BMSGHD ;(T1,XB,CB)Build the message header
|
||
MOVEI T1,SZ.MHD ;Store the message header length
|
||
OPSTR <SKIPN>,MDNXT,+MDB.OF(XB); which if there is no slot data
|
||
MOVEI T1,MINXBF ; must be the minimum NI datagram size.
|
||
STOR T1,MDBYT,+MDB.OF(XB); in the appropriate place
|
||
SETZRO UNBSZ,+UNB.OF(XB);MBZ for MSD type transmits
|
||
XMOVEI T1,<MDB.OF>(XB) ;Address of the first MSD block
|
||
STOR T1,UNBFA,+UNB.OF(XB);stored where usually byte pointer goes.
|
||
CALL XMTMSG ;(CB,XB,RB)No, go transmit a single buffer XB
|
||
RET
|
||
;TMRCHK - Host circuit timer check routine. This routine performs actions
|
||
; base on the state of the circuit timer.
|
||
;Call: CB/ circuit block address
|
||
;Return:
|
||
; RET - no further action required for this circuit
|
||
; RESKSP - continue processing
|
||
|
||
TMRCHK: OPSTR <SKIPN T1,>,CBTIM,(CB);Is the circuit timer running?
|
||
RETSKP ;No, continue processing circuit
|
||
SUB T1,TODCLK ;Account for current time
|
||
SKIPL T1 ;Any time still left?
|
||
IFSKP. ;Circuit timer has expired.
|
||
LOAD T1,HNRLI,(HN) ;Get the retransmit limit.
|
||
OPSTR <CAMG T1,>,CBRTC,(CB);Have we reached the limit?
|
||
IFSKP. ;No, so
|
||
CALL XUNAKQ ;(CB,HN) retransmit the unack queue
|
||
LOAD T1,HNTIM,(HN) ;[7.xxxx][7.1120] and reset the timer from now.
|
||
ADD T1,TODCLK ;
|
||
STOR T1,CBTIM,(CB) ;Restore reset timer to CB
|
||
ELSE.
|
||
JSP T2,XMTLIM ; otherwise, terminate the circuit
|
||
ENDIF. ; cause communication broken with remote.
|
||
RET
|
||
ENDIF.
|
||
RETSKP
|
||
;XUNAKQ - Transmit all messages on the unacknowledged queue
|
||
|
||
XUNAKQ: OPSTR <SKIPN>,CBDLL,(CB);Don't retransmit if already transmitting
|
||
OPSTR <SKIPN XB,>,QLFWD,+CB.AKQ(CB) ;First msg to retransmit
|
||
RET ;Should be
|
||
OPSTRM <AOS>,HCRTR,(HN) ;Increment host count
|
||
OPSTRM <AOS>,CCRTR,(CB) ; and per-server count
|
||
OPSTRM <AOS>,CBRTC,(CB) ;Increment retransmit count
|
||
XMTALL: OPSTRM <AOS>,CBDLL,(CB) ;Increment buffers in DLL
|
||
LOAD T1,HNPID,(HN) ;Reset the portal ID
|
||
STOR T1,UNPID,+UNB.OF(XB)
|
||
MOVX T1,NU.XMT ;Transmit function
|
||
XMOVEI T2,UNB.OF(XB) ;UN block
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI##
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1)
|
||
>
|
||
IFNSK.
|
||
OPSTRM <SOS>,CBDLL,(CB)
|
||
ENDIF.
|
||
SKIPE XB,UE.LW0(XB) ;Next XB on queue to (re)transmit
|
||
JRST XMTALL ;Still more, continue to give buffers to DLL
|
||
RET
|
||
; BMSGHD - Build a LAT Virtual Circuit Message Header
|
||
|
||
;Call: T1/ <Message type>_2
|
||
; XB/ Message buffer address
|
||
; CB/ Address of the Circuit Block
|
||
|
||
BMSGHD: MOVE T2,NSLOTS ;Number of slots in message
|
||
LSH T2,^D8 ;Shift to left byte position
|
||
IOR T1,T2 ;Or in message type (shifted)
|
||
OPSTR <SKIPE>,CBRRF,(CB);If the Reply Request Flag is set
|
||
IORI T1,1 ; set it in message header
|
||
CALL LAP2B0 ;(XB,T1)Enter as 1st 2 bytes of header
|
||
LOAD T1,CBRID,(CB) ;Get the remote's circuit index
|
||
CALL LAP2B0 ;(XB,T1) and enter as 2 byte field
|
||
LOAD T1,CBLID,(CB) ;Get our circuit index
|
||
CALL LAP2B0 ;(XB,T1) and enter as 2 byte field
|
||
LOAD T1,CBRSQ,(CB) ;ACK number
|
||
LSH T1,^D8 ;Shift to left byte position
|
||
LOAD T2,CBTSQ,(CB) ;Send Seq Number
|
||
ANDI T2,377 ;Modulo 256
|
||
IOR T1,T2
|
||
CALL LAP2B0 ;(XB,T1)
|
||
RET
|
||
SUBTTL Message Transmitter -- XMTMSG
|
||
|
||
;XMTMSG - Transmit a LAT Message
|
||
|
||
;Call: CB/ 0 or Circuit Block Address
|
||
; XB/ Address of the UN block/Transmit Buffer
|
||
; RB/ Address of Receive Buffer if XB/0
|
||
; UNBSZ/ Message byte count
|
||
; CALL XMTMSG
|
||
; Normal Return
|
||
;
|
||
; This routine sets up the UN block for NISRV and issues the transmit
|
||
; function. Only UNBSZ must be set by the caller. If there is no CB,
|
||
; the information is taken from the receive buffer, otherwise from the
|
||
; circuit block.
|
||
;
|
||
; If there is no possibility of an ACK (such as sending a STOP message),
|
||
; then call XMTMSN, which will set UNUID to 0 so that the buffer will
|
||
; just be returned to free memory after NISRV has sent it.
|
||
;
|
||
|
||
XMTMSN: TDZA T1,T1 ;Enter here if you just want to free the buffer
|
||
; when transmit is done.
|
||
XMTMSG: MOVE T1,CB
|
||
TXO T1,DLL.FL ;Set "buffer-in-DLL" flag
|
||
STOR T1,UNUID,+UNB.OF(XB) ;Save the CB address for completion action
|
||
JUMPE CB,XMNOCB ;Case with no assigned circuit block
|
||
LOAD T1,HNPID,(HN) ;Portal ID
|
||
OPSTR <DMOVE T2,>,CBDNI,(CB) ;Get destination NI adr from CB
|
||
OPSTRM <AOS>,CBDLL,(CB) ;Increment # buffers in the DLL
|
||
JRST XMTMS0 ;Go do common code
|
||
XMNOCB: LOAD T1,UNPID,+UNB.OF(RB);Get the portal ID
|
||
OPSTR <DMOVE T2,>,UNSAD,+UNB.OF(RB) ;Source NI address from recvd msg
|
||
XMTMS0: STOR T1,UNPID,+UNB.OF(XB);Store in xmit buffer
|
||
OPSTRM <DMOVEM T2,>,UNDAD,+UNB.OF(XB) ; to the xmit buffer
|
||
STOR XB,UNRID,+UNB.OF(XB);Remember the buffer address
|
||
MOVEI T1,UNA.EV
|
||
STOR T1,UNADS,+UNB.OF(XB);Tell NISRV we are using EXEC virtual memory
|
||
MOVX T1,NU.XMT ;NI transmit function code
|
||
XMOVEI T2,UNB.OF(XB) ;UN block address
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI##
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1)
|
||
>
|
||
IFSKP.
|
||
OPSTRM <AOS>,HCXMT,(HN)
|
||
JUMPE CB,RTN
|
||
OPSTRM <AOS>,CCXMT,(CB)
|
||
ELSE.
|
||
MOVX T1,DLL.FL ;Get "buffer-in-DLL" flag
|
||
ANDCAB T1,UN.UID+UNB.OF(XB) ;clear it in message
|
||
SKIPN T1
|
||
CALL RELXBH ;(XB)
|
||
JUMPN CB,RTN
|
||
OPSTRM <SOS>,CBDLL,(CB);Failed so put back count where is was
|
||
ENDIF.
|
||
RET
|
||
SUBTTL Message Transmitter -- XMTDON
|
||
|
||
;XMTDON - Message Transmitter Transmit Done Scheduler Level Routine
|
||
|
||
;Call: T1/ NU.XMT
|
||
; T2/ UN block address
|
||
; CALL XMTDON
|
||
; Normal return
|
||
;
|
||
; If the UNRID is zero, there is no longer a CB for this buffer because the
|
||
; circuit went away and we don't care what happens at transmit complete. Just
|
||
; release the buffer. If the CB state is stopping, complete the stopping of
|
||
; the circuit which could not be done earlier because all xmit buffers were in
|
||
; the DLL.
|
||
|
||
XMTDON: SAVEAC <CB>
|
||
MOVE XB,T2 ;Move transmit buffer adr to conventional AC.
|
||
LOAD CB,UNUID,+UNB.OF(T2) ;Get the CB address
|
||
TXZ CB,DLL.FL ;Clear the "buffer-in-DLL" flag
|
||
STOR CB,UNUID,+UNB.OF(T2) ; and store back this way
|
||
TXNE CB,SAV.FL ;[7.1120]Keep this buffer?
|
||
RET ;[7.1120]Yes, return
|
||
JUMPE CB,RELXBH ;If there is no CB, release buffer and header and return
|
||
OPSTRM <SOS>,CBDLL,(CB) ;One less buffer in the DLL
|
||
RET
|
||
SUBTTL Receive Message Handling Routines
|
||
|
||
;LAG2BY - obtains two bytes from the message which is assumed to be a 16-bit
|
||
; quantity.
|
||
|
||
;Call: MA/ Message base address
|
||
; CALL LAG2BY
|
||
; Normal Return
|
||
;Changes T2
|
||
; T1/ 16-bit quantity
|
||
|
||
LAG2BY: MOVX T1,-2 ;Amount to decrement the count by
|
||
OPSTRM <ADDM T1,>,UNBSZ,+UNB.OF(RB);Update message count
|
||
OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Get low order byte
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get high order byte
|
||
LSH T2,^D8 ;Shift high order byte left
|
||
IOR T1,T2 ;Make a 16-bit quantity
|
||
RET ;Return with result
|
||
|
||
;GTCSTR - Move Counted String from a Message
|
||
|
||
;Call: T1/ Maximum count to move
|
||
; T2/ Destination byte pointer for string
|
||
; RB/ Message base address
|
||
;Changes T1,T2,T3,T4
|
||
|
||
IGCSTR: SETZ T1, ;[7.1039]Here to ignore a counter string
|
||
GTCSTR: SAVEAC <W1,W2> ;Get two work registers
|
||
OPSTR <SKIPN T3,>,UNBSZ,+UNB.OF(RB);Byte count left in message
|
||
RET ;Return error. Message unexpectedly truncated
|
||
OPSTR <ILDB W1,>,UNBFA,+UNB.OF(RB);Count of the counted string
|
||
SUBI T3,1(W1) ;Calculate new residual message count
|
||
JUMPL T3,RTN ;Message truncated
|
||
STOR T3,UNBSZ,+UNB.OF(RB);Store back into message header
|
||
SKIPE W1 ;A null string?
|
||
IFSKP.
|
||
MOVEI T1,0 ;Yes, return zero count
|
||
RETSKP ; successfully
|
||
ENDIF.
|
||
MOVE T3,W1 ;Copy of the actual string count
|
||
CAMLE T3,T1 ;Get the minimum of (actual string count,
|
||
MOVE T3,T1 ; maximum string count) for copy loop index
|
||
MOVEM T3,T1 ; and store as actual count copied
|
||
LOAD T4,UNBFA,+UNB.OF(RB);Save initial value of byte pointer
|
||
JUMPE T1,GTCDON ;Skipping over this field
|
||
GTCSLP: OPSTR <ILDB W2,>,UNBFA,+UNB.OF(RB);Fetch a source byte
|
||
IDPB W2,T2 ;Store as destination byte
|
||
SOJN T3,GTCSLP ;Loop till all bytes copied
|
||
GTCDON: ADJBP W1,T4 ;Adjust byte pointer properly in case less than
|
||
STOR W1,UNBFA,+UNB.OF(RB); the full string was copied
|
||
RETSKP ;Return success, T1/ count of string fetched
|
||
SUBTTL Transmit Message Handling Routines
|
||
|
||
;LAP2BY - Put 2 bytes to message
|
||
|
||
;Call: XB/ Address of the transmit buffer
|
||
; T1/ 16-bit quantity to ouput
|
||
; CALL LAP2BY or CALL LAP2B0
|
||
; Normal return
|
||
;T1 perserved, T2 used
|
||
;
|
||
; This routine enters a 16-bit quantity as two bytes from T1 into the transmit
|
||
; buffer with the least significant entered first. It assumes that UNBFA is
|
||
; set up with the proper byte pointer to the message buffer. The alternate
|
||
; entry LAP2B0 differs from LAP2BY in that LAP2B0 does not increment the
|
||
; message byte count whereas LAP2BY does.
|
||
|
||
LAP2BY: MOVEI T2,2 ;Amount to increment the message count by
|
||
OPSTRM <ADDM T2,>,UNBSZ,+UNB.OF(XB);Update the count in message header
|
||
LAP2B0: MOVE T2,T1 ;In order to return T1 preserved.
|
||
OPSTR <IDPB T2,>,UNBFA,+UNB.OF(XB);Low order byte entered first
|
||
LSH T2,-^D8 ;Shift hi byte into position
|
||
OPSTR <IDPB T2,>,UNBFA,+UNB.OF(XB);High order byte goes to b buffer
|
||
RET
|
||
|
||
;PTCSTR - put counted string to message buffer
|
||
|
||
;Call: XB/ Address of the transmit buffer
|
||
; T1/ Count to enter into buffer
|
||
; T2/ Source string byte pointer
|
||
|
||
PTCSTR: MOVEI T3,1(T1) ;Increment to include count byte
|
||
OPSTRM <ADDM T3,>,UNBSZ,+UNB.OF(XB);Increment count in buffer
|
||
PTCST0: OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);Put the string count to buffer
|
||
MOVE T3,T1 ;Save copy of count for decrementing
|
||
PTCSTL: JUMPE T3,RTN ;If count exhausted, done with copying
|
||
ILDB T4,T2 ;Get the next source string byte
|
||
OPSTR <IDPB T4,>,UNBFA,+UNB.OF(XB);Put it to buffer
|
||
SOJA T3,PTCSTL ;Continue til string count zero
|
||
|
||
;PTUSTR - put uncounted string to message buffer
|
||
|
||
;Call: XB/ Address of the transmit buffer
|
||
; T1/ Count to enter into buffer
|
||
; T2/ Source string byte pointer
|
||
|
||
PTUSTR: OPSTRM <ADDM T1,>,UNBSZ,+UNB.OF(XB);Increment count in buffer
|
||
MOVE T3,T1 ;Save copy of count for decrementing
|
||
PTUSTL: JUMPE T3,RTN ;If count exhausted, done with copying
|
||
ILDB T4,T2 ;Get the next source string byte
|
||
OPSTR <IDPB T4,>,UNBFA,+UNB.OF(XB);Put it to buffer
|
||
SOJA T3,PTUSTL ;Continue til string count zero
|
||
;RBPOST - Return Receive Buffer to DLL
|
||
|
||
;Call: T1/ Message block address
|
||
; CALL RBPOST
|
||
; Normal Return
|
||
;
|
||
|
||
RBPOSS: SAVEAC <T1,T2,T3,T4> ;[7.1039]Preserve T1-T4
|
||
RBPOST: MOVEI T2,LMRFSI ;Size of the buffer
|
||
STOR T2,UNBSZ,+UNB.OF(T1);Store in UN block for NISRV
|
||
XMOVEI T2,<SBF.OF>(T1) ;Set up 1 word global byte pointer
|
||
TLO T2,(<OWGP. 8,0>) ;[7.1039] to the transmit data for NISRV
|
||
STOR T1,UNRID,+UNB.OF(T1);Store the buffer address for callback
|
||
STOR T2,UNBFA,+UNB.OF(T1); and store in UN block
|
||
LOAD T2,HNPID,(HN) ;Get the Portal ID for NISRV
|
||
STOR T2,UNPID,+UNB.OF(T1)
|
||
MOVEI T2,UNA.EV
|
||
STOR T2,UNADS,+UNB.OF(T1);Tell NISRV we are using EXEC virtual memory
|
||
XMOVEI T2,UNB.OF(T1) ;UN block address
|
||
MOVX T1,NU.RCV ;Post receive buffer function code
|
||
IFN FTOPS20,<
|
||
CALL DLLUNI##
|
||
>
|
||
IFN FTOPS10,<
|
||
SNCALL (DLLUNI##,MCSEC1)
|
||
>
|
||
IFNSK.
|
||
IFN FTOPS20,<
|
||
BUG. (CHK,LAPRBF,LATSER,SOFT,<Specify Receive Buffer Failure>,<<T1,DLLERC>>,<
|
||
|
||
Cause: LATSER received an error from NISRV while attempting to post a
|
||
receive buffer.
|
||
|
||
Data: DLLERC - Error code returned by NISRV
|
||
|
||
>)
|
||
>;END IFN FTOPS20
|
||
RET
|
||
ENDIF.
|
||
RETSKP
|
||
SUBTTL Slot Demultiplexor - LSDMUX
|
||
|
||
;LSDMUX - Process all slots in a received RUN message
|
||
;
|
||
;Call: RB/ Address of RUN message
|
||
; CALL LSDMUX
|
||
; Error return - illegal slot encountered
|
||
; Normal return
|
||
|
||
MIN. (MINSTY,<ST.DTA,ST.STA,ST.STP,ST.DTB,ST.ATT,ST.REJ>) ;Minimum slot type code
|
||
MAX. (MAXSTY,<ST.DTA,ST.STA,ST.STP,ST.DTB,ST.ATT,ST.REJ>) ;Maximum slot type code
|
||
|
||
LSDMUX: TRVAR <SLTDID,SLTSID,SLTCNT,SLTTYP,SLTEPT> ;Assign some variables on stack
|
||
SKIPN T1,NSLOTS ;Any slots left to process?
|
||
RETSKP ;No, return successfully
|
||
NXTSLT: OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get the destination id
|
||
MOVEM T2,SLTDID
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get the source id
|
||
MOVEM T2,SLTSID
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get the slot data count
|
||
LOAD T3,UNBSZ,+UNB.OF(RB);Get the current message count
|
||
STOR T2,UNBSZ,+UNB.OF(RB) ;[7.1120]Save the slot data count
|
||
AOS T1,T2 ;Round up to the nearest even number
|
||
TRZ T1,1 ; since they may be 1 pad byte in slot
|
||
SUBI T3,SLHDSZ(T1) ;Subtract the total slot size
|
||
MOVEM T3,SLTCNT ;[7.1120]Save the byte count left in message
|
||
JUMPL T3,ILLSLT ;Error if message has ended prematurely
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get the slot type/credits/reason
|
||
MOVEM T2,SLTTYP
|
||
ADJBP T1,UN.BFA+UNB.OF(RB);Point to next slot
|
||
MOVEM T1,SLTEPT ;in case we need to skip later
|
||
LSH T2,-4 ;Shift off the credits field
|
||
CAIL T2,MINSTY ;Range check slot type
|
||
CAILE T2,MAXSTY
|
||
CALLRET ILLSLT ;Slot ID out of range, illegal slot
|
||
CALL @SLTDSP-MINSTY(T2) ;Dispatch to proper routine
|
||
JRST ILLSLT
|
||
SOSG NSLOTS ;Indicate one less slot to process
|
||
RETSKP ;Count went to zero, so done.
|
||
MOVE T1,SLTCNT ;[7.1120]Restore the byte count
|
||
STOR T1,UNBSZ,+UNB.OF(RB) ;[7.1120] left in this message
|
||
MOVE T1,SLTEPT ;Get pointer to next slot's data
|
||
MOVEM T1,UN.BFA+UNB.OF(RB);and force pointer to there
|
||
JRST NXTSLT ;Still some left, go do next
|
||
|
||
SLTDSP: XADDR. HSDATA ;[7.1052]Data A slot
|
||
XADDR. RTN ;[7.1052]Undefined
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. RTN ;[7.1052] "
|
||
XADDR. HSSTRT ;[7.1052]Start Slot
|
||
XADDR. HDRDAT ;[7.1052]Data B Slot
|
||
XADDR. IGNSLT ;[7.1052]Attention Slot
|
||
XADDR. RTN ;[7.1052]Reject Slot
|
||
XADDR. HSSTOP ;[7.1052]Stop Slot
|
||
|
||
SUBTTL HSSTRT - Process a START SLOT Message
|
||
|
||
|
||
;HSSTRT - Process a START SLOT message.
|
||
;
|
||
; HN/ Address of host node data base
|
||
; CB/ Address of circuit block
|
||
; RB/ Address of receive buffer
|
||
; CALL HSSTRT
|
||
; Return+1: Failure, invalid slot (cease parsing RUN message)
|
||
; Return+1: Success, SB/ Address of slot block (or zero)
|
||
|
||
HSSTRT: SKIPE SLTSID ;Source ID 0 is illegal
|
||
SKIPE SLTDID ;Destination ID of non-0 is illegal
|
||
CALLRET ILLSLT ;Report an illegal slot received
|
||
MOVNI T1,3 ;[7.1120]Number of bytes to be read
|
||
ADDB T1,UN.BSZ+UNB.OF(RB) ;[7.1120]Update the byte count
|
||
JUMPL T1,ILLSLT ;[7.1120]Negative: illegal slot
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB);Get the service class requested
|
||
CAIE T2,SCITTY ;Only interactive terminal class permitted
|
||
CALLRET ILLSLT ;If not, slot is illegal.
|
||
CALL SBALOC ;(CB/SB)Allocate a slot block
|
||
RETSKP ;Ignore since server should persist and we
|
||
; assume we should almost always get an SB
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB)
|
||
STOR T2,SBATS,(SB) ;Attention slot size maximum
|
||
OPSTR <ILDB T2,>,UNBFA,+UNB.OF(RB)
|
||
STOR T2,SBMDS,(SB) ;Data slot size maximum
|
||
LOAD T1,CBRSC,(CB) ;[7.1120]Get the server name count
|
||
CAILE T1,ML.SRN ;[7.1120]Is it too big for a slot block?
|
||
MOVEI T1,ML.SRN ;[7.1120]Yes, this is the maximum length
|
||
STOR T1,SBSRC,(SB) ;[7.1120]Save the server name count
|
||
ADDI T1,4 ;[7.1120]Convert fro bytes to words
|
||
IDIVI T1,5 ;[7.1120]
|
||
XMOVEI T2,CB.SNM(CB) ;[7.1120]Get address of source
|
||
XMOVEI T3,SB.SRN(SB) ;[7.1120]Get address of descriptor
|
||
XBLT. T1 ;[7.1120]Copy the string
|
||
MOVEI T1,ML.SVN ;[7.1120]Max length of service name
|
||
MOVX T2,<POINT 7,<SB.SVN>(SB)> ;[7.1120]Point to slot name string
|
||
CALL GTCSTR ;[7.1039](T1,T2,RB)Get a counted string
|
||
SETZ T1, ;[7.1039]Ran out of message
|
||
STOR T1,SBSVC,(SB) ;[7.1120]Store actual length of name
|
||
CALL IGCSTR ;[7.1039](T1,T2,RB)Ignore subject service name
|
||
JRST HSSTR2 ;[7.1039]No more data in message
|
||
; Now we are into the variable parameter part of the START SLOT message.
|
||
; Loop and record whatever fields we think are important.
|
||
;
|
||
HSSTR1: SOSL T1,UN.BSZ+UNB.OF(RB) ;[7.1039]Count down bytes in slot
|
||
ILDB T1,UN.BFA+UNB.OF(RB) ;[7.1039]Get Parameter number
|
||
JUMPLE T1,HSSTR2 ;[7.1039]Ran out of bytes, or hit end of parms
|
||
CAILE T1,SBPRMX ;[7.1039]Greater than max parm we know about?
|
||
SETZ T1, ;[7.1039]Yes, we will just ignore it.
|
||
CALL @SBPRTB(T1) ;[7.1039]Call routine to deal with parameter
|
||
JRST HSSTR2 ;[7.1039]Ran out of message
|
||
JRST HSSTR1 ;[7.1039]Get next parameter from slot
|
||
|
||
|
||
; Come here when the START SLOT has been parsed. Check to see whether
|
||
; or not the values are correct and the resources are available.
|
||
;
|
||
HSSTR2: OPSTRM <AOS>,HNCON,(HN) ;[7.1120]Increment the number of connects
|
||
LOAD T2,SBREA,(SB) ;[7.1120]Get a reject code (if any)
|
||
JUMPN T2,SLREJ0 ;[7.1120]Got one: reject this connection
|
||
OPSTR <SKIPN T1,>,SBPRA,(SB) ;[7.1120]Host initiated connect?
|
||
IFSKP. ;[7.1120]
|
||
SKIPG T1 ;[7.1120]Is this a duplicate?
|
||
IFSKP. ;[7.1120]No:
|
||
LOAD T2,PRSTA,(T1) ;[7.1120]Get the (internal) state
|
||
CALLRET @HSSDSP(T2) ;[7.1120]Accept if in SAC or QUE state
|
||
ELSE. ;[7.1120]
|
||
OPSTRM <SOS>,HNCON,(HN) ;[7.1120]
|
||
CALL RELSB ;[7.1120](SB,CB)Release this slot block
|
||
RETSKP ;[7.1120] (it is a dulplicate)
|
||
ENDIF. ;[7.1120]
|
||
ENDIF. ;[7.1120]
|
||
HSSTR3: LOAD T1,HNCON,(HN) ;[7.1120]Get the number of connects.
|
||
OPSTR <CAMLE T1,>,HNMCO,(HN);Check if maximum exceeded.
|
||
JRST SLRESF ;No additional sessions permitted.
|
||
IFN FTOPS10,<
|
||
MOVE T1,STATES## ;Get system states word
|
||
TRNE T1,ST.NRT ;Are remote TTYs allowed?
|
||
JRST SLSHUT ;Nope, reject the connection
|
||
> ;End IFN FTOPS10
|
||
CALL GETTDB ;(SB)Get a terminal data block and start a job
|
||
JRST SLRESF ;No terminal data blocks available
|
||
OPSTR <SKIPN T1,>,SBPRA,(SB) ;[7.1120]Host initiated connect?
|
||
IFSKP. ;[7.1120]
|
||
MOVX T2,SS.RUN ;[7.1120]Change to the RUN state
|
||
STOR T2,PRSTA,(T1) ;[7.1120]
|
||
MOVX T2,377777 ;[7.1120]Set the timer to infinity
|
||
STOR T2,PRCMT,(T1) ;[7.1120] so that LATXPR won't see it
|
||
SETZRO PRCMC,(T1) ;[7.1120]Clear the command message count
|
||
CALL PRWAKE ;[7.1120](T1)Wake the job
|
||
ENDIF. ;[7.1120]
|
||
MOVX T1,SBSTR!SBFCC ;Flag this slot as waiting to send a START
|
||
CALL SSBDAV ;(T1/SB) and a DATA_B slot when MUX runs.
|
||
RETSKP ;Return success
|
||
|
||
|
||
; Table of states for the PRVECT entries
|
||
;
|
||
HSSDSP: XADDR. SLCSRF ;(0) Halt
|
||
XADDR. SLCSRF ;(1) Run
|
||
XADDR. SLCSRF ;(2) Solicit Information
|
||
XADDR. SLCSRF ;(3) Solicit Access (initialize first)
|
||
XADDR. HSSTR3 ;(4) Solicit Access
|
||
XADDR. HSSTR3 ;(5) Queued
|
||
XADDR. SLCSRF ;(6) Rejected
|
||
XADDR. SLCSRF ;(7) Timed out
|
||
XADDR. SLUSRF ;(8) Cancel (initialize first)
|
||
XADDR. SLUSRF ;(9) Cancel
|
||
HSSMAX==.-HSSDSP-1
|
||
IF1,<IFL <HSSMAX-SS.MAX>,<PRINTX ?Entries missing in HSSDSP>>
|
||
; Come here to reject the START SLOT for various reasons.
|
||
;
|
||
SLUSRF: SKIPA T2,[SE.USR] ;[7.1120]User requested disconnect
|
||
SLSHUT: MOVX T2,SE.SHU ;[7.1120]System shutdown in progress
|
||
JRST SLREJ0 ;[7.1120]
|
||
SLRESF: SKIPA T2,[SE.RES] ;[7.1120]Insufficient resources
|
||
SLCSRF: MOVX T2,SE.CSR ;[7.1120]Corrupted solicit request
|
||
SLREJ0: STOR T2,SBREA,(SB) ;[7.1120]Save the rejection code
|
||
OPSTR <SKIPG T1,>,SBPRA,(SB) ;[7.1120]Get address of PR block
|
||
IFSKP. ;[7.1120]
|
||
STOR T2,PRSTS,(T1) ;[7.1120]Save the rejection code
|
||
MOVX T2,SS.REJ ;[7.1120]
|
||
STOR T2,PRSTA,(T1) ;[7.1120]Change state to Rejected
|
||
HRLOI T2,377777 ;[7.1120]Set the timer to infinity
|
||
STOR T2,PRCMT,(T1) ;[7.1120] so that LATXPR won't see it
|
||
SETZRO SBPRA,(SB) ;[7.1120]Clear the SB's pointer to the PR
|
||
SETZRO PRSBA,(T1) ;[7.1120]Clear the PR's pointer to the SB
|
||
SETZRO PRCMC,(T1) ;[7.1120]Clear the command message count
|
||
CALL PRWAKE ;[7.1120](T1)Wake the job
|
||
ENDIF. ;[7.1120]
|
||
MOVX T1,SBREJ ;[7.1120]Make this slot waiting to send
|
||
CALL SSBDAV ;[7.1120](T1,SB) a REJECT SLOT
|
||
RETSKP ;[7.1120]
|
||
;[7.1039]
|
||
; Dispatch table of routines to deal with parameters from start slot
|
||
;
|
||
SBPRTB: XADDR. IGCSTR ;[7.1039](0)Ignore ones we don't know about
|
||
XADDR. GETFLG ;[7.1120](1)Flag word
|
||
XADDR. LINKPR ;[7.1120](2)Queue entry
|
||
XADDR. IGCSTR ;[7.1039](3)Reserved
|
||
XADDR. IGCSTR ;[7.1120](4)Server name
|
||
XADDR. GETPRN ;[7.1039](5)Port name
|
||
SBPRMX=.-SBPRTB-1
|
||
|
||
|
||
;[7.1120]
|
||
;GETFLG - Get pertinent START SLOT flags.
|
||
;
|
||
; SB/ Address of slot block
|
||
; RB/ Address of receive buffer
|
||
; CALL GETFLG
|
||
; Return+2: Always
|
||
|
||
GETFLG: SOS UN.BSZ+UNB.OF(RB) ;Ignore the byte count
|
||
IBP UN.BFA+UNB.OF(RB) ;
|
||
CALL LAG2BY ;(RB/T1)Get 2 bytes (unsigned)
|
||
TRNN T1,1 ;Is this a dial-up line?
|
||
RETSKP ;No, return
|
||
SETONE SBDLP,(SB) ;Yes, set the bit in the SB
|
||
RETSKP ;
|
||
|
||
|
||
;[7.1120]
|
||
;LINKPR - Link this start slot to a pending request block.
|
||
;
|
||
; SB/ Address of slot block
|
||
; CALL LINKPR
|
||
; Return+2: Always, SBPRA/ Address of PR block (or minus one)
|
||
; or SBREA/ Reject code SE.ENQ (entry not in queue)
|
||
|
||
LINKPR: SOS UN.BSZ+UNB.OF(RB) ;Ignore the byte count
|
||
IBP UN.BFA+UNB.OF(RB) ;
|
||
CALL LAG2BY ;(RB/T1)Get two bytes (unsigned)
|
||
MOVEM T1,T2 ;Save the connect id
|
||
ANDI T1,PR.NDX ;Throw away the random portion
|
||
ADD T1,PRVECT ;Get address of PRVECT entry
|
||
SKIPN T1,(T1) ;Get address of pending request block
|
||
JRST LINKP1 ;None: invalid connect id
|
||
LOAD T3,PRCID,(T1) ;Get the connect id
|
||
CAME T3,T2 ;Is it what we expected?
|
||
JRST LINKP1 ;No, invalid connect id
|
||
LOAD T2,PRSBA,(T1) ;Is there already a slot block?
|
||
JUMPN T2,LINKP2 ;Yes: ignore this duplicate
|
||
STOR SB,PRSBA,(T1) ;Save address of slot block
|
||
STOR T1,SBPRA,(SB) ;Save address of pending request block
|
||
RETSKP ;
|
||
LINKP1: MOVX T1,SE.ENQ ;Reject code: entry not in queue
|
||
STOR T1,SBREA,(SB) ;
|
||
RETSKP ;
|
||
LINKP2: SETONE SBPRA,(SB) ;Invalid connect id: return with
|
||
RETSKP ; minus one as the address
|
||
|
||
|
||
REPEAT 0,<
|
||
;[7.1120]Delete this routine
|
||
;GETSRN - Get server name.
|
||
;
|
||
; SB/ Address of slot block
|
||
; CALL GETSRN
|
||
; Return+1: Error, couldn't get counted string
|
||
; Return+2: Success, T1/ character count
|
||
|
||
GETSRN: MOVE T2,[POINT 7,SB.SRN(SB)] ;Get server name
|
||
MOVEI T1,ML.SRN ;Set up max length of server name
|
||
CALL GTCSTR ;(T1,T2,RB)Go get the string
|
||
IFSKP.
|
||
STOR T1,SBSRC,(SB) ;Save the server name count
|
||
RETSKP ;Skip return
|
||
ENDIF.
|
||
SETZ T1, ;Error: return with character count zero
|
||
RET ;
|
||
> ;End REPEAT 0
|
||
|
||
|
||
;[7.1120]
|
||
;GETPRN - Get object port name.
|
||
|
||
; SB/ Address of slot block
|
||
; CALL GETPRN
|
||
; Return+1: Error, couldn't get counted string
|
||
; Return+2: Success, T1/ character count
|
||
|
||
GETPRN: MOVE T2,[POINT 7,SB.PRN(SB)] ;Get object port name
|
||
MOVEI T1,ML.PRN ;Set up max length of port name
|
||
CALL GTCSTR ;(T1,T2,RB)Go get the string
|
||
IFSKP.
|
||
STOR T1,SBPRC,(SB) ;Save the port name count
|
||
RETSKP ;Skip return
|
||
ENDIF.
|
||
SETZ T1, ;Error: return with character count zero
|
||
RET ;
|
||
SUBTTL Slot Processing Routines - STOP Slots
|
||
|
||
;HSSTOP - Process a STOP Slot.
|
||
;
|
||
;Call: SB/ Slot block address
|
||
; CALL HSSTOP
|
||
; Error return -
|
||
; Normal return
|
||
|
||
HSSTOP: SKIPN T2,SLTDID ;Destination ID cannot be zero
|
||
CALLRET IGNSLT ; but if it is zero, just ignore it.
|
||
SKIPN SLTSID ;Source ID must be zero
|
||
CAILE T2,NTTLAH ;Is the SBVECT index in range?
|
||
CALLRET ILLSLT ;No. Slot is illegal
|
||
MOVE T1,SBVECT ;Get the slot block address from
|
||
ADD T1,T2 ; the destination slot id
|
||
SKIPE SB,(T1) ;If the SB address is zero
|
||
OPSTR <CAME CB,>,SBCBA,(SB); or CB address has changed then
|
||
JRST IGNSLT ; ignore the slot since already gone.
|
||
CALL RELSB ;(CB,SB)Release all slot resources
|
||
RETSKP ;Return success
|
||
SUBTTL Slot Processing Routines - DATA_A,DATA_B Slots
|
||
|
||
;HSDATA - Process a DATA_A Slot
|
||
;
|
||
;Call: SB/ Slot block address
|
||
; CALL HSDATA
|
||
; Error return - illegal slot
|
||
; Normal return
|
||
|
||
HSDATA: CALL HDRDAT ;Go process data slot header
|
||
RET ;Illegal slot, error return
|
||
SKIPN W1,UN.BSZ+UNB.OF(RB) ;[7.1120]Get the number of characters in the slot
|
||
RETSKP ;None, return
|
||
IFN FTOPS20,<
|
||
LOAD T2,SBTDB,(SB) ;Terminal dynamic data base
|
||
DYNST ;Get the line number
|
||
NXSLCH: OPSTR <ILDB T1,>,UNBFA,+UNB.OF(RB);Get a character.
|
||
CALLX (MSEC1,TTCHI) ;[7.1024]Call TTYSRV to enter into input buffer
|
||
TRN ;Ignore error
|
||
>;end IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
LOAD U,SBTDB,(SB) ;Get line data block address
|
||
NXSLCH: OPSTR <ILDB T3,>,UNBFA,+UNB.OF(RB);Get a character.
|
||
SNCALL (RECPTY##,MCSEC1);Call SCNSER to enter into input buffer
|
||
>;end IFN FTOPS10
|
||
|
||
SOJG W1,NXSLCH ;If still more, continue
|
||
RETSKP ;Otherwise return success
|
||
HSDATB: ;Process received DATA_B slot (NOP)
|
||
|
||
HDRDAT: SKIPE T2,SLTDID ;Destination ID cannot be zero
|
||
CAILE T2,NTTLAH ; or greater than maximum slot index
|
||
CALLRET ILLSLT ;Illegal slot
|
||
MOVE T3,SLTSID ;Source ID from the slot
|
||
MOVE T1,SBVECT ;Get the address of the SB
|
||
ADD T1,T2 ; based on the remote slot id from
|
||
SKIPN SB,(T1) ; the message
|
||
CALLRET IGNSLT ;No slot block.
|
||
OPSTR <CAME T3,>,SBRID,(SB) ;Is slot source ID equal to SB remote ID?
|
||
CALLRET IGNSLT ;No, ignore the slot
|
||
LOAD T3,SBSTA,(SB) ;Get the slot state
|
||
CAIN T3,SS.RUN ;If the slot state is not running or
|
||
OPSTR <CAME CB,>,SBCBA,(SB) ; the circuit block address has changed
|
||
CALLRET IGNSLT ; then slot disappeared already so ignore.
|
||
MOVE T3,SLTTYP ;See if remote extended us any transmit
|
||
ANDI T3,17 ; credits. If so, add them to what we already
|
||
OPSTRM <ADDM T3,>,SBXCR,(SB); have.
|
||
SKIPN UN.BSZ+UNB.OF(RB) ;[7.1120]Do remote credit check only if there was
|
||
RETSKP ; data in the slot.
|
||
OPSTR <SOSGE T3,>,SBRCR,(SB) ;Decrement the receive credits
|
||
JRST ILLSLT ;Illegal, server sent data with no credits
|
||
STOR T3,SBRCR,(SB) ;Store back updated credits count
|
||
SKIPE T3 ;If receive credits have gone to zero,
|
||
IFSKP. ; then indicate we need to grant more credits
|
||
MOVX T1,SBOUT ; by setting setting data available
|
||
CALL SSBDAV ; for MUX when it runs next time.
|
||
ENDIF.
|
||
RETSKP
|
||
SUBTTL Slot Block Allocation and Deallocation Routines
|
||
|
||
|
||
;SBALOC - Slot Block Allocation Routine
|
||
;
|
||
;Call: CB/ circuit block address
|
||
; CALL SBALOC
|
||
; Error Return
|
||
; Normal Return
|
||
; SB/ Address of allocated slot block
|
||
;
|
||
; This routine allocates and initializes a new slot block.
|
||
|
||
SBALOC: MOVEI T1,SB.LEN ;Number of words to allocate for a slot blk
|
||
CALL MMGTZW ;Try to get them
|
||
RET ;Can't
|
||
MOVE SB,T1 ;Put address in proper AC
|
||
MOVSI T4,-SBBWDS ;Look for a free slot block index
|
||
SBANXT: SKIPE T1,SBBITS(T4) ; by examining the free slot block words
|
||
JFFO T1,SBAGO ; for the first 1 bit. This represents
|
||
AOBJN T4,SBANXT ; the first free slot block index
|
||
RET ;No slot block available
|
||
SBAGO: HRRZS T4 ;Clear out left half
|
||
MOVE T3,BITS(T2) ;Clear the bit since the index is
|
||
ANDCAM T3,SBBITS(T4) ; no longer free
|
||
IMULI T4,^D36 ;Compute the slot block index
|
||
ADDI T2,1(T4) ;Cannot be zero
|
||
STOR T2,SBLID,(SB) ;Store in SB as local slot index
|
||
MOVE T1,SBVECT ;Now store the address of the slot block
|
||
ADD T1,T2 ; in the vector of slot block address, which
|
||
MOVEM SB,(T1) ; is indexed by slot block index
|
||
XMOVEI T1,CB.SBQ(CB) ;Queue the SB to the circuit block's
|
||
MOVE T2,SB ; queue of slot blocks.
|
||
CALL LAQUE ;
|
||
MOVEI T1,CS.STA ;Set the slot state
|
||
STOR T1,SBSTA,(SB) ; to starting.
|
||
STOR CB,SBCBA,(SB) ;Store the circuit block address in SB
|
||
MOVE T1,SLTSID ;Get the remote's slot id
|
||
STOR T1,SBRID,(SB) ;Store as our remote id
|
||
MOVE T1,SLTTYP ;Get the Slot type/credits from recv's slot
|
||
ANDI T1,17 ;Keep only the number of credits extended to us
|
||
STOR T1,SBXCR,(SB) ;Store is slot block as our transmit credits
|
||
MOVEI T1,MAXCRE ;Maximum credits to extend to remote
|
||
STOR T1,SBRCR,(SB) ; to current number of remote credits
|
||
RETSKP ;Return successfully
|
||
;SSBDAV - Set Slot BLock Data Available
|
||
;
|
||
;Call: T1/ Bit to set in SB.FLG
|
||
; SB/ Slot block address
|
||
; CALL SSBDAV
|
||
; Normal Return
|
||
|
||
SSBDAV: SKIPGE T2,SB.FLG(SB) ;Is there already data available?
|
||
IFSKP. ;No, so set it now
|
||
OPSTRM <AOS>,CBSDC,(CB);Increment number of slots waiting
|
||
TLO T2,400000 ; and indicate this slot now waiting
|
||
ENDIF.
|
||
IOR T2,T1 ;OR in new reason for waiting
|
||
MOVEM T2,SB.FLG(SB) ; and store back
|
||
RET ;Return
|
||
|
||
;CSBDAV - Clear Slot BLock Data Available
|
||
;
|
||
;Call: T1/ Bit to clear in SB.FLG
|
||
; SB/ Slot block address
|
||
; CALL SSBDAV
|
||
; Normal Return
|
||
|
||
CSBDAV: SKIPL T2,SB.FLG(SB) ;Is "data available" already clear?
|
||
RET ;Yes
|
||
ANDCM T2,T1 ;Clear the desired bit
|
||
TXNE T2,SBSMSK ;Are all bits off now?
|
||
IFSKP.
|
||
OPSTRM <SOS>,CBSDC,(CB)
|
||
MOVEI T2,0
|
||
ENDIF.
|
||
HLLM T2,SB.FLG(SB)
|
||
RET
|
||
;RELSBS - Release all Slot Blocks and their Resources for a virtual circuit
|
||
;
|
||
;Call: CB/ Address of the circuit block
|
||
; CALL RELSBS
|
||
; Normal Return
|
||
|
||
RELSBS: JUMPE CB,RTN ;No slots to release if no circuit block
|
||
OPSTR <SKIPN SB,>,QLFWD,+CB.SBQ(CB);Get the address of first SB on Q
|
||
RET ;If zero, there are no more on the queue
|
||
CALL RELSB ;Release the slot block
|
||
JRST RELSBS ;Go do the next
|
||
RET
|
||
|
||
;RELSB - Release a Slot Block and its Resources
|
||
;
|
||
;Call: CB/ Address of the circuit block for slot
|
||
; SB/ Address of the slot block to release
|
||
; CALL RELSB
|
||
; Normal Return
|
||
; SB/ address of previous slot or listhead
|
||
|
||
RELSB:
|
||
IFN FTOPS20,<
|
||
OPSTR <SKIPN T2,>,SBTDB,(SB) ;Is there a terminal data base
|
||
JRST RELSB0 ;No, go just release the SB resources
|
||
SETZM TTDEV(T2) ;Clear the slot block address in the TDB.
|
||
SETZRO TTPRM,(T2) ;TDB no longer permanent
|
||
SETZRO TTOTP,(T2) ;Clear output in progress so sched tests work.
|
||
OPSTR <SKIPE T1,>,SBPRA,(SB) ;[7.1120]Was this "host initiated"?
|
||
IFSKP. ;[7.1120]-No
|
||
DYNST ;Get the static line number
|
||
CALLX (MSEC1,NTYCOF) ;[7.1024]Go detach the job
|
||
LOAD T2,SBTDB,(SB) ;Get the TDB address again.
|
||
LOAD T1,TCJOB,(T2) ;If there is a controlling job, don't release
|
||
CAIE T1,-1 ; the TDB since this will be done
|
||
JRST RELSB0 ; later by JOBCOF.
|
||
ELSE.
|
||
LOAD T3,PRSTS,(T1) ;[7.1120]Get the status
|
||
TRZN T3,.TTDES ;[7.1120]Do we have a tty-designator?
|
||
JRST RELTT ;[7.1120]No. (That's odd...)
|
||
ADDI T3,DVXTT0 ;[7.1120]Get the device index
|
||
MOVX T1,DV%ASN ;[7.1120]Indicate device is
|
||
ANDCAM T1,DEVCHR(T3) ;[7.1120] no longer assigned.
|
||
MOVEI T1,-1 ;[7.1120]Mark the device as free.
|
||
HRLM T1,DEVUNT(T3) ;[7.1120]
|
||
ENDIF. ;[7.1120]
|
||
RELTT: DYNST ;No controlling job so we must release the
|
||
CALLX (MSEC1,TTYDE0) ;[7.1024] the dynamic data base here.
|
||
TRN ;TTYSRV already reports this.
|
||
>;end IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
OPSTR <SKIPN U,>,SBTDB,(SB) ;Is there a terminal data base
|
||
JRST RELSB0 ;No, go just release the SB resources
|
||
PUSH P,J ;NGVLDB blows J (our W2)
|
||
CALL NGVLDB ;Give the LDB back to SCNSER
|
||
POP P,J ;Get our AC back
|
||
>;end IFN FTOPS10
|
||
RELSB0: OPSTR <SKIPN T1,>,SBPRA,(SB) ;[7.1120]Is there a pending request block?
|
||
IFSKP. ;[7.1120]
|
||
SETZRO PRSBA,(T1) ;[7.1120]Yes, clear its slot block address
|
||
CALL PRDEL ;[7.1120](T1)Delete the pending request block
|
||
ENDIF. ;[7.1120]
|
||
OPSTR <XMOVEI T1,>,CBSBQ,(CB) ;Point to the CB SBQ header
|
||
MOVE T2,SB ; and
|
||
CALL LAUNQ ; release the SB from this queue
|
||
SKIPL SB.FLG(SB) ;Did this SB have any data waiting?
|
||
IFSKP. ;Yes
|
||
OPSTRM <SOS>,CBSDC,(CB) ;Reduce number of slots with data waiting
|
||
ENDIF.
|
||
OPSTRM <SOS>,HNCON,(HN) ;Reduce number of active connects.
|
||
CALL RLSBID ;Release the SB local id.
|
||
MOVE T1,SB
|
||
OPSTR <SKIPN SB,>,QLBWD,(SB);Set up so the slot mux gets the correct
|
||
XMOVEI SB,CB.SBQ(CB) ; next slot.
|
||
CALL MMFREE ;Free the memory
|
||
RET
|
||
;RLSBID - Release a Slot Block's local id.
|
||
;
|
||
;Call: SB/ Address of the SB
|
||
; CALL RLSBID
|
||
; Normal Return
|
||
|
||
RLSBID: OPSTR <SKIPN T1,>,SBLID,(SB);Get the SB local index
|
||
RET ;Already zero. Nothing to do.
|
||
MOVE T2,SBVECT ;Clear the pointer to SB
|
||
ADD T2,T1 ; in the vector of SB addresses
|
||
SETZM (T2) ; ...
|
||
SOS T1 ;Normalize to zero
|
||
IDIVI T1,^D36 ;Now clear the bit to indicate that the
|
||
MOVE T3,BITS(T2) ; slot block index is now free
|
||
IORM T3,SBBITS(T1) ; ...
|
||
SETZ T1, ;Clear the local
|
||
STOR T1,SBLID,(SB) ; SB ID.
|
||
RET
|
||
;GETTDB - get terminal dynamic data base
|
||
;
|
||
;Call: SB/ slot block address
|
||
; CALL GETTDB
|
||
; Error return
|
||
; Normal return
|
||
|
||
IFN FTOPS20,<
|
||
GETTDB: SAVEAC <W1,W2>
|
||
MOVE W1,TT1LIN+TT.LAH
|
||
GTTDB0: LOAD T1,TTSTY,(W1) ;Get the line type
|
||
CAIE T1,TT.LAH
|
||
RET
|
||
MOVE T2,W1
|
||
CALLX (MSEC1,STADYN) ;[7.1024]
|
||
JUMPE T2,GTTDB2
|
||
GTTDB1: AOJA W1,GTTDB0 ;Try next line
|
||
GTTDB2: MOVE T2,W1
|
||
CALLX (MSEC1,TTYASC) ;[7.1024]
|
||
JRST GTTDB1
|
||
CALLX (MSEC1,STADYN) ;[7.1024]
|
||
JRST GTTDB1
|
||
STOR T2,SBTDB,(SB)
|
||
MOVEM SB,TTDEV(T2)
|
||
SETONE TCJOB,(T2)
|
||
SETONE TTPRM,(T2)
|
||
OPSTR <SKIPE W2,>,SBPRA,(SB) ;[7.1120]
|
||
IFSKP. ;[7.1120]
|
||
MOVEI T1,.CHCNC
|
||
MOVE T2,W1
|
||
CALLX (MSEC1,TTCHI) ;[7.1024]
|
||
NOP
|
||
ELSE. ;[7.1120]
|
||
MOVEI T1,.TTDES(W1) ;[7.1120]Make a TTY Designator
|
||
STOR T1,PRSTS,(W2) ;[7.1120]Stash it away
|
||
ADDI W1,DVXTT0 ;[7.1120]DVXTT0 + TTY Number = device index
|
||
LOAD T1,PRJOB,(W2) ;[7.1120]Get the real controlling job number
|
||
STOR T1,TCJOB,(T2) ;[7.1120]Set it in the TDB...
|
||
HRLM T1,DEVUNT(W1) ;[7.1120]...And here too
|
||
MOVX T1,DV%ASN ;[7.1120]Mark it as assigned
|
||
IORM T1,DEVCHR(W1) ;[7.1120]
|
||
MOVE T1,W2 ;[7.1120]PR address in T1
|
||
CALL PRWAKE ;[7.1120]Tell the user
|
||
ENDIF. ;[7.1120]
|
||
RETSKP
|
||
>;END IFN FTOPS20
|
||
; Get a remote LDB and make it mine
|
||
;
|
||
; Return:
|
||
; RET ;FAILED
|
||
; RETSKP ;SUCCESS
|
||
|
||
IFN FTOPS10,<
|
||
GETTDB: SAVEAC <F,J,W> ;[7.1120]SCNSER/NETSER WILL USE THESE
|
||
|
||
;Allocate an LDB
|
||
;
|
||
MOVSI T1,LTLLAT## ;FLAG A NEW LAT TERMINAL
|
||
MOVEI T3,LATDSP ;LAT'S ISR DISPATCH TABLE
|
||
SNCALL (GETLDB##,MCSEC1) ;GET A REMOTE TTY LDB, POINTER IN U
|
||
RET ;GO ANNOUNCE THE FAILURE
|
||
|
||
;Finish making this a LAT LDB
|
||
;
|
||
MOVEI T1,LATRTQ ;GET POINTER TO OUTPUT Q HEADER
|
||
HRLZM T1,LDBQUH##(U) ;STORE FOR SCNSER (TOPOKE/TOTAKE)
|
||
STOR U,SBTDB,(SB) ;REMEMBER OUR LDB
|
||
MOVEM SB,LDBLAT##(U) ;STORE SB PTR IN LDB TOO
|
||
MOVEI T1,APCLAT## ;GET LATSRV CODE
|
||
DPB T1,@[IW MCSEC1,LDPAPC##] ;SET ASYNC PORT CHARACTERISTIC
|
||
MOVEI T1,M.LIDL## ;GET MAX. IDLE TIME FOR LAT LINES
|
||
SNCALL (SCNADT##,MCSEC1) ;SET THE TIMER GOING
|
||
LDB T1,@[IW MCSEC1,LDPXNF##] ;Find out our XON/XOF setting
|
||
STOR T1,SBXNF,(SB) ;And make LAT's setting agree (we will also
|
||
; send a DATA_B slot to inform LATbox).
|
||
|
||
;If it is a host-initiated connect, set up a DDB.
|
||
;
|
||
OPSTR <SKIPN>,SBPRA,(SB) ;[7.1120]Is it a host-initiated connect?
|
||
IFSKP. ;[7.1120]
|
||
SNCALL (TTYNAM##,MCSEC1) ;[7.1120](U/T2)Get physical name of TTY
|
||
LOAD T1,SBPRA,(SB) ;[7.1120]Get address of PR block
|
||
LOAD J,PRFRK,(T1) ;[7.1120]Get the JCH of the requestor
|
||
MOVE T1,T2 ;[7.1120]Copy the TTY's physical name
|
||
SNCALL (GETDDJ##,MCSEC1) ;[7.1120](U,J,T1/F,U)Get a DDB for the TTY
|
||
RET ;[7.1120]Can't: no DDB's available
|
||
MOVSI T1,DEPRAS ;[7.xxxx]Make it restricted assignment
|
||
IORM T1,DEVSTA(F) ;[7.xxxx]
|
||
LOAD T1,SBPRA,(SB) ;[7.1120]Get address of PR block
|
||
LDB T2,@[IW MCSEC1,LDPLNO##] ;[7.1120]Get the TTY number
|
||
ADDI T2,.UXTRM ;[7.1120]
|
||
STOR T2,PRSTS,(T1) ;[7.1120]Copy it in the status field
|
||
RETSKP ;[7.xxxx]Success (do not run INITIA)
|
||
ENDIF. ;[7.1120]
|
||
|
||
;Initialize the TTY with .HELLO force command
|
||
;
|
||
SNCALL (TTFGRT##,MCSEC1) ;GO FORCE .HELLO/.RESTART
|
||
RETSKP ;SUCCESS RETURN
|
||
SUBTTL Subroutines -- NGVLDB - Give an LDB back to SCNSER
|
||
|
||
;Still in IFN FTOPS10
|
||
|
||
;NGVLDB - Give an LDB back to SCNSER
|
||
;
|
||
; Call: U/ Pointer to LDB
|
||
;
|
||
; Return:
|
||
; RET ;ALWAYS
|
||
|
||
NGVLDB: SETZM LDBLAT##(U) ;CLEAR OUT BY-NOW-STALE POINTER
|
||
MOVEI T1,IONND% ;"NODE DOWN" (PATH LOST/ETC) ERROR
|
||
SNCALL (DETLDB##,MCSEC1) ;DETACH THE LDB/DDB
|
||
XJRST [MCSEC1+FRELDB##] ;RETURN LDB TO SCNSER FREE POOL
|
||
|
||
>;END IFN FTOPS10
|
||
;LHRRH - LAT device dependent "return remote host" code
|
||
;
|
||
; Given the line #, returns the originating hostname, line and
|
||
; network type. Places this info in the users NTINF% .NWRRH
|
||
; argument block. NTINF has already checked the user arguments
|
||
; for validity.
|
||
;
|
||
; Call with T1/ address of internal arg block
|
||
;
|
||
; ARG+.NWABC/ # of bytes available for host name
|
||
; ARG+.NWFNC/ not used
|
||
; ARG+.NWNNP/ byte pointer to store hostname string
|
||
; ARG+.NWLIN/ address of dynamic data for line
|
||
; ARG+.NWTTF/ flags, and network and terminal types
|
||
; ARG+.NWNNU/ node # word 1
|
||
; ARG+.NWNU1/ node # word 2
|
||
;
|
||
; Returns + 1 on error with T1/ error code
|
||
; + 2 on success
|
||
|
||
IFN FTOPS20,<
|
||
XRENT (LHRRH,G) ;[7.1024]LHRRH::, XLHRR::
|
||
|
||
SASUBR <UAB>
|
||
MOVEM T1,UAB ;SAVE OUTPUT POINTER
|
||
MOVX T4,NW%LAT ;SET NETWORK TYPE
|
||
DPB T4,[POINT 9,.NWTTF(T1),17] ;STORE NETWORK TYPE
|
||
MOVE T2,.NWLIN(T1) ;GET DYNAMIC DATA ADR
|
||
NOSKED ;PROTECT SB/CB FROM CHANGING BENEATH US
|
||
MOVE T2,TTDEV(T2) ;GET SB ADDRESS
|
||
JUMPE T2,LHRRH3
|
||
LOAD T3,SBCBA,(T2) ;GET CB ADDRESS
|
||
JUMPE T3,LHRRH3
|
||
LOAD T4,CBDNI,(T3) ;GET NI ADDRESS (WORD 1)
|
||
MOVEM T4,.NWNNU(T1)
|
||
LOAD T4,CBDNI,+1(T3) ;GET NI ADDRESS (WORD 2)
|
||
MOVEM T4,.NWNNU+1(T1)
|
||
MOVE T2,T3 ;SAVE CB ADDRESS IN T2
|
||
LOAD T3,CBRSC,(T3) ;GET COUNT OF CHARACTERS
|
||
JUMPE T3,LHRRH3 ;IF ZERO - NO HOST NAME
|
||
CAML T3,.NWABC(T1) ;MAKE SURE NO MORE THAN MAX
|
||
MOVE T3,.NWABC(T1) ;ENFORCE IT
|
||
MOVE T1,.NWNNP(T1) ;GET POINTER TO OUTPUT STRING
|
||
OPSTR <XMOVEI T2,>,CBSNM,(T2) ;GET ADR OF REMOTE NAME STRING
|
||
TXO T2,<OWGP. 7,> ;FORM BYTE POINTER TO BUFFER
|
||
EXCH T1,T2 ;PUT POINTER WHERE MMVAZS WANTS THEM
|
||
CALL MMVAZS ;COPY THE STRING
|
||
LHRRH2: SETZ T1,
|
||
IDPB T1,T2 ;DEPOSIT A NULL
|
||
MOVE T1,UAB ;GET POINTER TO USER ARG BLOCK
|
||
MOVX T2,NW%NNN ;GET "NO NODE NAME KNOWN" FLAG
|
||
SKIPN T3 ;GOT A NODE NAME ?
|
||
IORM T2,.NWTTF(T1) ;NO - SET THE "NO NODE NAME KNOWN" FLAG
|
||
OKSKED ;DONE WITH SB/CB
|
||
RETSKP
|
||
|
||
LHRRH3: MOVE T2,.NWNNP(T1) ;GET POINTER TO OUTPUT STRING
|
||
SETZ T3, ;NO NODE NAME
|
||
CALLRET LHRRH2 ;UPDATE HOSTNAME STRING, AND RETURN
|
||
>;END IFN FTOPS20
|
||
SUBTTL Slot Multiplexor - Main Loop
|
||
|
||
;LAMUX Slot Multiplexor Main Loop
|
||
;
|
||
;Call: CALL LAMUX
|
||
; Normal return
|
||
|
||
LAMUX:
|
||
IFN FTOPS10,<
|
||
CALL LATSCN ;Scan active LDBs
|
||
LOAD CB,QLFWD,+HN.QAC(HN) ;Get the first CB on the active queue
|
||
LANXCB: JUMPE CB,CHKWFB ;All CBs processed, check if we need buffers
|
||
>;end IFN FTOPS10
|
||
IFN FTOPS20,<
|
||
LOAD CB,QLFWD,+HN.QAC(HN) ;Get the first CB on the active queue
|
||
LANXCB: JUMPE CB,RTN ;All CBs processed, return
|
||
TMNN HNRUN,(HN) ;[7.1039]Is the NI still running?
|
||
IFSKP. ;[7.1039]
|
||
CALL NIHALT ;[7.1039]()No, so deallocate all resources
|
||
JRST MXNXCB ;[7.1039]
|
||
ENDIF. ;[7.1039]
|
||
>
|
||
SETZM NSLOTS ;Initialize number of slots in this msg
|
||
LOAD T1,CBSTA,(CB) ;Consider only those circuits which are
|
||
CAIE T1,CS.RUN ; in the running state
|
||
JRST MXNXCB ; ...
|
||
OPSTR <SKIPE>,CBSBQ,(CB);[7.1039]If there are no slots for this circuit
|
||
IFSKP. ;[7.1039] kill it and look at the next one
|
||
CALL IDLHLT ;[7.1039]()
|
||
JRST MXNXCB ;[7.1039]
|
||
ENDIF. ;[7.1039]
|
||
LOAD T1,HNLAS,(HN) ;Get the current access state.
|
||
CAIN T1,LS.OFF ;If the access state is now off,
|
||
JRST MXNXC2 ; kill this circuit and look at next.
|
||
SETZRO CBRRF,(CB) ;No RRF set yet
|
||
CALL TMRCHK ;Check for circuit timer related functions.
|
||
JRST MXNXCB ;Continue with next circuit.
|
||
TMNN CBMRN,(CB) ;Must we go balanced (reply to server) now?
|
||
JRST LMNMRN ;No
|
||
; We have received a message from the server and must respond message now. If
|
||
; there is a free transmit buffer and there is slot data waiting to be sent,
|
||
; then build the slots in a large MSD transmit buffer and send it. If the MSD
|
||
; buffer is not available or there is no slot data waiting, just send a RUN
|
||
; message header. If there are no free transmit buffers, retransmit the queue
|
||
; of unacknowledged messages.
|
||
|
||
MOVX T1,CBMRS!CBMRN!CBRRF;Clear all flags
|
||
ANDCAM T1,CB.FLG(CB) ; since we will reply now.
|
||
SETZRO CBCSB,(CB) ;Clear count since balanced
|
||
SKIPN XB,CB.XBQ(CB) ;Is there a transmit buffer header free?
|
||
JRST LMNOXB ;No, go transmit unACK'd Q
|
||
OPSTR <SKIPE >,CBSDC,(CB);There is a buffer, is there data waiting?
|
||
CALL BLDMSL ;Everything there so build slots in buffer
|
||
NOP ;No slots, but don't care
|
||
CALL MTTRUN ;Transmit either hdr only or full message
|
||
JRST MXNXCB ;Go to next circuit block
|
||
LMNOXB: CALL XUNAKQ ;Transmit all messages on the unack'd Q
|
||
JRST MXNXCB
|
||
|
||
; Check to see if we just received a message from the server. If so,
|
||
; flag to force a reply at the next sheduler cycle. We wait one cycle in
|
||
; case user programs are controlling echoing in the hopes that response
|
||
; will be smoother.
|
||
|
||
LMNMRN: TMNN CBMRS,(CB) ;Must reply soon?
|
||
JRST LMUNSL
|
||
SETONE CBMRN,(CB) ;Yes, set to force reply on next cycle
|
||
JRST MXNXCB
|
||
|
||
; We are in balanced mode, i.e. the response to the latest server message
|
||
; has already been sent. Check here to see if we ought to send an unsolicited
|
||
; message. We are allowed one. We wait at least MXBALC scheduler cycles since
|
||
; last going balanced. If after that period there is slot data waiting, we
|
||
; send an unsolicited message to the server.
|
||
; If we have not data to send, wait another MXBALC cycles before trying again.
|
||
;
|
||
LMUNSL: LOAD T1,CBCSB,(CB) ;Number of cycles to wait before sending
|
||
CAIL T1,MXBALC ;Have we waited long enough?
|
||
IFSKP. ;No, so
|
||
AOJ T1, ; increment the count
|
||
STOR T1,CBCSB,(CB) ; and wait
|
||
JRST MXNXCB ; some more.
|
||
ENDIF.
|
||
|
||
; We have waited long enough. If there is slot data waiting and resouces
|
||
; available, send an unsolicited message to the server
|
||
;
|
||
SKIPN XB,CB.XBQ(CB) ;Is there a transmit buffer header free?
|
||
JRST MXNXCB ;No, so don't send anything
|
||
SETZRO CBCSB,(CB) ;We might send data, reset the ticker.
|
||
OPSTR <SKIPE >,CBSDC,(CB);Is there slot data waiting?
|
||
CALL BLDMSL ;Build a message full of slots
|
||
JRST MXNXC1 ; If no slots, do keep-alive timing.
|
||
CALL MTTRUN ;There are slots in the message so send it.
|
||
MXNXCB: LOAD CB,QLFWD,(CB) ;Index of the next CB on active queue
|
||
JRST LANXCB ;Continue looping
|
||
RET
|
||
|
||
; We don't have any unsolicited data to send, check if we have heard
|
||
; from the server within the last few SERVER_KEEP_ALIVE_TIMER seconds.
|
||
; If not, we will assume the server died, and we will kill the circuit.
|
||
;
|
||
MXNXC1: MOVE T1,TODCLK ;Get the current time
|
||
LOAD T2,CBKAT,(CB) ;Get the time last msg received
|
||
OPSTR <ADD T2,>,CBKAV,(CB) ;Add the keep-alive time
|
||
CAML T1,T2 ;Have we hit limit yet?
|
||
MXNXC2: CALL LCLHLT ;Yes, we have not heard from the server
|
||
JRST MXNXCB ;in a long time, so kill the circuit.
|
||
SUBTTL BLDMSL
|
||
|
||
;BLDMSL - Build RUN Message Slots
|
||
;
|
||
;Call: CB/ Address of Circuit Block
|
||
; CALL BLDMSL
|
||
; Normal return
|
||
;
|
||
; This routine scans through all slots associated with a LAT virtual circuit
|
||
; and builds RUN message slots for those which have data waiting to be sent
|
||
; to the remote node. SBFLGS contains a bits mask which indicates which
|
||
; type of slot must be built for the slot block. More than one bit may be set.
|
||
|
||
BLDMSL: OPSTR <SKIPN SB,>,QLFWD,+CB.SBQ(CB);Get addr of first slot for this CB
|
||
RET ;There are none
|
||
SETZRO UNBSZ,+UNB.OF(XB); and message count
|
||
SETZM MD.NXT+MDB.OF(XB) ;[7.1039]No transmit buffer yet.
|
||
BLSLOP: SKIPL W1,SB.FLG(SB) ;Does this slot have data waiting?
|
||
JRST MXNXSL ;No, loop to next slot
|
||
ANDX W1,SBSMSK ;[7.1120]Clear all but the flags
|
||
BLNXSL: JFFO W1,BLSDSP ;Find first flags bit which is lit.
|
||
MXNXSL: OPSTR<SKIPE SB,>,QLFWD,(SB);Get next slot's index and
|
||
JRST BLSLOP ; continue with the next slot
|
||
BLSLCP: SKIPN NSLOTS ;Check to see if any slots entered at all
|
||
RET ;None.
|
||
|
||
;If we couldn't get through all slots, rotate this circuit's slot queue so
|
||
;that we resume next time with the slot we did not complete this time.
|
||
|
||
SKIPN SB ;Did we get through the whole queue?
|
||
IFSKP. ;NO
|
||
OPSTR <CAMN SB,>,QLFWD,+CB.SBQ(CB);Is slot already at the Q head?
|
||
IFSKP. ;NO
|
||
LOAD T3,QLFWD,+CB.SBQ(CB);Get old queue head
|
||
LOAD T4,QLBWD,+CB.SBQ(CB);Get old queue tail
|
||
STOR T3,QLFWD,(T4) ;Joint them together
|
||
STOR T4,QLBWD,(T3) ; ...
|
||
LOAD T3,QLBWD,(SB) ;Get new Q tail from new Q head
|
||
SETZRO QLFWD,(T3) ;Clear new tail's forward ptr
|
||
SETZRO QLBWD,(SB) ;Clear new head's backward ptr
|
||
STOR SB,QLFWD,+CB.SBQ(CB);New head
|
||
STOR T3,QLBWD,+CB.SBQ(CB);New tail
|
||
ENDIF.
|
||
ENDIF.
|
||
;Compute final byte count padding to minimum NI datagram size if necessary.
|
||
|
||
LOAD T1,UNBSZ,+UNB.OF(XB);Store the larger of the final real message
|
||
CAIG T1,MINXBF-MMHDSI ; count and the minimum count as the message
|
||
MOVEI T1,MINXBF-MMHDSI ; count.
|
||
MOVE T3,MD.NXT+MDB.OF(XB) ;[7.1039]Get MSD address
|
||
STOR T1,MDBYT,(T3) ;[7.1039]and store count in MSD
|
||
RETSKP
|
||
|
||
; Check first to see if adding a new slot causes the number of slots in a
|
||
; message to exceed the maximum permitted by remote.
|
||
|
||
BLSDSP: LOAD T3,CBMSL,(CB) ;Get the maximum permitted by remote
|
||
CAMG T3,NSLOTS ; and compare with number of slots so far.
|
||
JRST BLSLCP ;At maximum, stop processing this circuit.
|
||
|
||
; Check to see if there is enough room remaining in the transmit buffer to
|
||
; include this slot.
|
||
|
||
HLRZ T1,SLLNTB-1(W2) ;Minimum bytes required for this slot type.
|
||
LOAD T3,UNBSZ,+UNB.OF(XB);Current number of bytes in the buffer.
|
||
ADD T1,T3 ;Count if we include this new slot.
|
||
CAILE T1,SZ.XBF ;Compare with total transmit buffer capacity.
|
||
JRST BLSLCP ;Will not fit so stop processing this circuit.
|
||
|
||
; Call the routine to build the slot. It may or may not be entered into the
|
||
; message. At this point however it is always marked as having been processed.
|
||
|
||
MOVE T1,BITS(W2) ;Get the mask for the bit
|
||
ANDCM W1,T1 ;Indicate that this slot has been processed.
|
||
CALL @SLBDSP-1(W2) ;Build the slot.
|
||
JRST BLNXSL ;Slot not entered. Try next.
|
||
|
||
; Slot successfully entered into the transmit buffer. Update the buffer counts.
|
||
; Terminal character count has already been added.
|
||
|
||
HRRZ T1,SLLNTB-1(W2) ;Get the count for the slot header.
|
||
OPSTR <ADD T1,>,UNBSZ,+UNB.OF(XB);Get the message count so far
|
||
TRNN T1,1 ;Is the count even?
|
||
IFSKP. ;No, must pad to even number
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);Put fill byte into message
|
||
AOS T1 ;Increment total in message
|
||
ENDIF.
|
||
STOR T1,UNBSZ,+UNB.OF(XB);
|
||
AOS NSLOTS ;Increment number of slots in the message.
|
||
JRST BLNXSL ;Get next slot request.
|
||
MIN. (MINSFL,<^L<SBREJ>,^L<SBSTR>,^L<SBSTO>,^L<SBOUT>,^L<SBFOU>,^L<SBFCC>>)
|
||
MAX. (MAXSFL,<^L<SBREJ>,^L<SBSTR>,^L<SBSTO>,^L<SBOUT>,^L<SBFOU>,^L<SBFCC>>)
|
||
|
||
SLBDSP: XADDR. XSLREJ ;[7.1052]Reject
|
||
XADDR. XSLSTA ;[7.1052]Start
|
||
XADDR. XSLATT ;[7.1052]Attention
|
||
XADDR. XSLDTA ;[7.1052]Data A
|
||
XADDR. XSLDTB ;[7.1052]Data B
|
||
XADDR. XSLSTP ;[7.1052]Stop
|
||
|
||
SLLNTB: EXP <SZ.SHD+SZ.REJ,,SZ.SHD+SZ.REJ> ;[7.1052]Reject
|
||
EXP <SZ.SHD+SZ.SST,,SZ.SHD+SZ.SST> ;[7.1052]Start
|
||
EXP <SZ.SHD+SZ.ATT,,SZ.SHD+SZ.ATT> ;[7.1052]Attention
|
||
EXP <SZ.SHD,,SZ.SHD> ;[7.1052]Data A
|
||
EXP <SZ.SHD+SZ.SDB,,SZ.SHD+SZ.SDB> ;[7.1052]Data B
|
||
EXP <SZ.SHD+SZ.SSP,,SZ.SHD+SZ.SSP> ;[7.1052]Stop
|
||
|
||
SUBTTL Slot Formatting Routines
|
||
|
||
;XSLSTA - Format a START Slot in the Transmit Buffer
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLSTA
|
||
; Normal Return
|
||
|
||
XSLSTA: CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
RET ;No, and can't get any.
|
||
MOVEI T1,SS.RUN ;Put the slot in the
|
||
STOR T1,SBSTA,(SB) ; RUNNING state.
|
||
MOVEI T1,<<ST.STA_^D12>!<MAXCRE_^D8>!SZ.SST>;COUNT/TYPE/CREDITS fields
|
||
CALL BSLTHD ;Build the slot header
|
||
MOVEI T1,SCITTY ;Only available service class currently
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB)
|
||
MOVEI T1,MXSLSI ;Maximum slot size for all slot types
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);As maximum attention slot size
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);As maximum data slot size
|
||
MOVEI T1,0
|
||
CALL LAP2B0 ;Zero slot names
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);No parameters either
|
||
MOVX T1,SBSTR ;Indicate that this slot request successfully
|
||
CALL CSBDAV ; and entirely completed.
|
||
RETSKP
|
||
|
||
;XSLREJ - Format a REJECT Slot in the Transmit Buffer
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLREJ
|
||
; Normal Return
|
||
|
||
XSLREJ: CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
RET ;No, and can't get any.
|
||
LOAD T1,SBREA,(SB) ;Get the reject reason code
|
||
LSH T1,^D8
|
||
MOVEI T1,<ST.REJ_^D12!SZ.REJ>(T1) ;COUNT/TYPE/REASON fields
|
||
CALL BSLTHD ;Go build the slot header
|
||
MOVX T1,SBREJ ;Indicate that this slot request successfully
|
||
CALL CSBDAV ; and entirely completed.
|
||
CALL RELSB ;Release the slot.
|
||
RETSKP ;That's all there is to a REJECT slot.
|
||
SUBTTL Slot Formatting Routines
|
||
|
||
;XSLSTP - Format a STOP Slot in the Transmit Buffer
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLSTP
|
||
; Normal Return
|
||
|
||
XSLSTP: CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
RET ;No, and can't get any.
|
||
CALL RLSBID ;Release the local slot block ID.
|
||
LOAD T1,SBREA,(SB) ;Get the stop reason code
|
||
LSH T1,^D8
|
||
MOVEI T1,<ST.STP_^D12!SZ.SSP>(T1) ;COUNT/TYPE/REASON fields
|
||
CALL BSLTHD ;Go build the slot header
|
||
MOVX T1,SBSTO ;Indicate that this slot request successfully
|
||
CALL CSBDAV ; and entirely completed.
|
||
CALL RELSB ;Now go release the slot
|
||
RETSKP
|
||
|
||
;XSLATT - Format a ATTENTION Slot in the Transmit Buffer
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLATT
|
||
; Normal Return
|
||
|
||
XSLATT: CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
RET ;No, and can't get any.
|
||
MOVEI T1,<ST.ATT_^D12!SZ.ATT>;COUNT/TYPE fields
|
||
CALL BSLTHD ;Go build the slot header
|
||
MOVEI T1,1B30
|
||
OPSTRM <IDPB T1,>,UNBFA,+UNB.OF(XB);Deposit control flags
|
||
MOVX T1,SBFOU ;Indicate that this slot request successfully
|
||
CALL CSBDAV ; and entirely completed.
|
||
RETSKP
|
||
SUBTTL Slot Formatting Routines
|
||
|
||
;XSLDTA - Format a DATA_A Slot in the Transmit Buffer
|
||
;
|
||
;Call: W1/ Slot Block Flags
|
||
; SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLDTA
|
||
; Normal Return
|
||
|
||
; If we have transmit credit available, compute the maximum number of terminal
|
||
; output characters which may be entered into the slot. If we no longer have
|
||
; credit, set the character count to zero.
|
||
|
||
XSLDTA: SAVEAC <W1,W2>
|
||
IFN FTOPS20,<
|
||
SETZ W1, ;Assume character count is zero.
|
||
OPSTR <SKIPN>,SBXCR,(SB);Do we still have any transmit credit?
|
||
IFSKP.
|
||
LOAD T2,SBTDB,(SB) ;Get address of TDB
|
||
TMNE <TTSFG,TTRXF>,(T2);Check if at a page stop. If so, character
|
||
IFSKP. ; stays 0 (cannot call TTSND).
|
||
MOVEI W1,SZ.XBF-SZ.SHD;Get the residual buffer (minus slot header)
|
||
OPSTR <SUB W1,>,UNBSZ,+UNB.OF(XB); count.
|
||
CALL GTCHCT ;(T2/T1)Get total character count
|
||
CAMLE W1,T1 ;Smaller of residual count - 4 and TTOCT+TSALC
|
||
MOVE W1,T1 ;TTOCT+TSALC was smaller
|
||
OPSTR <CAMLE W1,>,SBMDS,(SB) ;Compare with maximum DATA_A slot size
|
||
LOAD W1,SBMDS,(SB) ;Maximum allowed by remote is less.
|
||
ENDIF.
|
||
ENDIF.
|
||
|
||
; Determine if the remote needs more credits and if we can give him any. If
|
||
; he doesn't or we can't and there is no terminal output data to be sent(count
|
||
; from above is 0) , exit without building the slot since there is no need to
|
||
; send one. Otherwise at least a DATA_A slot header will be sent. If it is
|
||
; extending credit, there may or may not be output data.
|
||
|
||
CALL CRECHK ;Check if we can grant more credit remote
|
||
SKIPE W1 ;Can't or don't need to so if there is no data
|
||
SKIPA ; either, no need to send a slot. Otherwise,
|
||
JRST XSLDA3 ; send at least empty slot granting new credit.
|
||
MOVE W2,T1 ;Save CRECHK result
|
||
CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
JRST XSLDA3 ;No, and can't get any.
|
||
MOVE T1,W2 ;Retrieve CHECHK results
|
||
LSH T1,^D8 ;Shift into proper position
|
||
IORI T1,<ST.DTA_^D12>(W1);Fill in the rest of last 2 slot header bytes.
|
||
CALL BSLTHD ;Go build the slot header
|
||
JUMPE W1,XSLDA2 ;No slot data and no credits used.
|
||
MOVNS W1 ;Set up to be used in an AOBJN
|
||
HRLZS W1 ;... [-count,,0]
|
||
XSLDA0: LOAD T2,SBTDB,(SB) ;Dynamic TT data base
|
||
CALLX (MSEC1,TTSND) ;[7.1024]Get a character from the buffer
|
||
JRST [ HRRZS W1
|
||
MOVEI T1,1(W1)
|
||
MOVNS T1
|
||
OPSTR <ADJBP T1,>,UNBFA,+UNB.OF(XB)
|
||
DPB W1,T1
|
||
JRST XSLDA1]
|
||
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB) ;[7.1039]Enter character into buffer
|
||
AOBJN W1,XSLDA0 ;Continue if more characters
|
||
XSLDA1: LOAD T1,SBXCR,(SB) ;Get our transmit credit count
|
||
SOS T1 ;Decrement since we may consume one credit now.
|
||
STOR T1,SBXCR,(SB) ; send data so store decremented credit count.
|
||
;Still in IFN FTOPS20
|
||
|
||
; Determine whether to slot request was FULLY completed. If not, don't
|
||
; clear the request bit since it will have to be completed next time around.
|
||
|
||
XSLDA2: OPSTRM <ADDM W1,>,UNBSZ,+UNB.OF(XB);Update the total message count.
|
||
OPSTRM <ADDM W2,>,SBRCR,(SB);Update his credit count.
|
||
LOAD T2,SBTDB,(SB) ;Get the TDB address back
|
||
CALL GTCHCT ;(T2/T1)Get remaining character count. If more,
|
||
JUMPN T1,RSKP ; return and do not clear request bit.
|
||
SETZRO TTOTP,(T2) ;Clear TTY output active if not more data.
|
||
OPSTR <SKIPN>,SBRCR,(SB);If remote has zero credit for transmits
|
||
RETSKP ; return successfully without clearint request.
|
||
MOVX T1,SBOUT ; Otherwise mark this request as complete.
|
||
CALL CSBDAV
|
||
RETSKP
|
||
|
||
XSLDA3: LOAD T2,SBTDB,(SB) ;Get the TDB address
|
||
CALL GTCHCT ;(T2/T1)Get remaining character count.
|
||
JUMPN T1,RTN
|
||
SETZRO TTOTP,(T2) ;There is no more terminal output, clear
|
||
RET ; the TTOTP bit and return.
|
||
|
||
>;end ifn ftops20
|
||
|
||
IFN FTOPS10,<
|
||
LOAD U,SBTDB,(SB) ;Get address of LDB.
|
||
;We will carry this in U for a while
|
||
SETZ W1, ;Assume character count is zero.
|
||
OPSTR <SKIPN>,SBXCR,(SB);Do we still have any transmit credit?
|
||
IFSKP.
|
||
MOVEI W1,SZ.XBF-SZ.SHD;Get the residual buffer (minus slot header)
|
||
OPSTR <SUB W1,>,UNBSZ,+UNB.OF(XB); count.
|
||
OPSTR <CAMLE W1,>,SBMDS,(SB) ;Compare with maximum DATA_A slot size
|
||
LOAD W1,SBMDS,(SB) ;Maximum allowed by remote is less.
|
||
ENDIF.
|
||
|
||
; Determine if the remote needs more credits and if we can give him any.
|
||
; If he doesn't or we can't and there is no terminal output data to be
|
||
; sent, exit without building the slot since there is no need to send
|
||
; one. Otherwise at least a DATA_A slot header will be sent. If it is
|
||
; extending credit, there may or may not be output data. We don't know
|
||
; at this point how many characters SCNSER has for us to send, so just
|
||
; keep trying to get chars until we fill the slot or run out of
|
||
; characters
|
||
;
|
||
; at this point:
|
||
; W1/ max characters we can send
|
||
;
|
||
MOVNS W1 ;Make into
|
||
HRLZS W1 ;AOBJN word
|
||
;
|
||
; now:
|
||
; W1/ -max,,0
|
||
;
|
||
JUMPE W1,NOCHR ;We don't have credit to send. Don't get a char
|
||
SKIPGE SB.TTO(SB) ;Is there saved character? (SBTTO is sign bit)
|
||
JRST GOTCHR ;Yes
|
||
SNCALL (XMTCHR##,MCSEC1) ;No, try to get a character from SCNSER
|
||
JRST NOCHR ;SCNSER doesn't have any for us.
|
||
SETONE SBTTO,(SB) ;SCNSER does have one, remember we got it
|
||
STOR T3,SBCHR,(SB) ;and save it away
|
||
GOTCHR: AOBJN W1,.+1 ;Got a char, count it
|
||
NOCHR: CALL CRECHK ;Check if we can grant more credit remote
|
||
TRNE W1,777777 ;Can't or don't need to. See if any data?
|
||
SKIPA ;Got data or can grant credit, send a slot
|
||
RET ;No slot to send, just return
|
||
MOVE W2,T1 ;Save CRECHK result
|
||
CALL XBFCHK ;Do we have a transmit buffer yet?
|
||
RET ;No, and can't get any.
|
||
LOAD T1,SBXCR,(SB) ;Get our transmit credit count
|
||
SOS T1 ;Decrement since we may consume one credit now
|
||
TRNE W1,777777 ;If data count is not zero, we will definitely
|
||
STOR T1,SBXCR,(SB) ;Store updated credit count
|
||
|
||
;Can't build slot header yet, since we don't know how many characters
|
||
; we will send. Save a pointer to the slot character count, and
|
||
; call BSLTHD anyway. We will stuff the char count later.
|
||
;
|
||
;At this point, the slot byte pointer points to the DST_SLOT_ID
|
||
;
|
||
MOVEI T1,3 ;the byte count is the 3rd byte of the slot
|
||
OPSTR <ADJBP T1,>,UNBFA,+UNB.OF(XB) ;so make a DPB pointer to it
|
||
PUSH P,T1 ;save first word of byte pointer
|
||
PUSH P,T2 ;and possible second word
|
||
;Still in IFN FTOPS10
|
||
|
||
;Now build the slot header
|
||
;
|
||
MOVE T1,W2 ;get CRECHK results
|
||
LSH T1,^D8 ;Shift to proper position
|
||
IORI T1,<ST.DTA_^D12> ;fill in the flag
|
||
CALL BSLTHD ;build the slot header (with bad char count)
|
||
TRNN W1,777777 ;Is there some data?
|
||
JRST XSLDA2 ;No, no characters to move
|
||
LOAD T3,SBCHR,(SB) ;Yes, get saved character.
|
||
SETZRO SBTTO,(SB) ;And remember we got it.
|
||
OPSTR <IDPB T3,>,UNBFA,+UNB.OF(XB) ;Stuff first character into buffer
|
||
JUMPGE W1,XSLDA2 ;if (heaven help us) there was only space for
|
||
;one character, stop now.
|
||
XSLDA0: SNCALL (XMTCHR##,MCSEC1) ;Get a character from SCNSER
|
||
JRST XSLDA2 ;None left
|
||
OPSTR <IDPB T3,>,UNBFA,+UNB.OF(XB) ;Stuff a character into buffer
|
||
AOBJN W1,XSLDA0 ;Count characters done
|
||
|
||
; Here we have either filled up the slot or run out of characters.
|
||
; Stuff the actual character count into the slot header.
|
||
;
|
||
XSLDA2: POP P,T2 ;retrieve pointer to slot header
|
||
POP P,T1 ; byte count
|
||
DPB W1,T1 ;and stuff actual character count
|
||
HRRZ T1,W1 ;get character count by itself
|
||
OPSTRM <ADDM T1,>,UNBSZ,+UNB.OF(XB) ;and update total message count.
|
||
OPSTRM <ADDB W2,>,SBRCR,(SB) ;Update his credit count. (remember total)
|
||
JUMPE W1,RSKP ;If we don't have any transmit credits, or
|
||
SKIPE W2 ;If the remote has zero credits for transmits
|
||
SKIPL LDBDCH##(U) ;Or if SCNSER doesn't think line is idle
|
||
.CREF LDLIDL ;(really checking this bit)
|
||
RETSKP ;Return successfully without clearing request
|
||
MOVX T1,SBOUT ;Otherwise, mark this request as complete.
|
||
CALL CSBDAV
|
||
RETSKP
|
||
>;END IFN FTOPS10
|
||
|
||
SUBTTL Slot Formatting Routines
|
||
|
||
;XSLDTB - Format a DATA_B Slot in the Transmit Buffer
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CB/ Circuit Block Address
|
||
; XB/ Transmit Buffer Address
|
||
; CALL XSLDTB
|
||
; Normal Return
|
||
;
|
||
|
||
XSLDTB: OPSTR <SKIPE>,SBXCR,(SB);Do we still have any transmit credit?
|
||
CALL XBFCHK ;Check if we have a transmit buffer yet.
|
||
RET ; Didn't and can't get one.
|
||
LOAD T1,SBXCR,(SB) ;Current number of transmit credits available
|
||
SOS T1 ;Decrement since this slot will consume one.
|
||
STOR T1,SBXCR,(SB) ;Store updated credit count
|
||
IFN FTOPS10,<
|
||
LOAD U,SBTDB,(SB) ;Point to LDB
|
||
>;end IFN FTOPS10
|
||
CALL CRECHK ;Does remote need credits?
|
||
NOP ;Dont't care if he did and we can't provide
|
||
OPSTRM <ADDM T1,>,SBRCR,(SB) ;[7275] Update remote credit count
|
||
LSH T1,^D8 ;Shift to proper position.
|
||
IORI T1,<ST.DTB_^D12>!SZ.SDB;Fill in rest of last 2 header bytes.
|
||
CALL BSLTHD ;Go build the slot header
|
||
MOVEI T1,SL.DXF ;Assume disabling XOFF recognition
|
||
IFN FTOPS20,<
|
||
LOAD T2,SBTDB,(SB) ;Get the terminal data base address
|
||
TMNE TT%PGM,TTFLGS(T2)
|
||
>;end IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
LOAD U,SBTDB,(SB) ;Get LDB address
|
||
LDB T2,@[IW MCSEC1,LDPXNF##] ;Get XON/XOF flag
|
||
SKIPE T2 ;disabling XON/XOF recognition?
|
||
>;end IFN FTOPS10
|
||
MOVEI T1,SL.EXF ;No, enabling
|
||
OPSTR <IDPB T1,>,UNBFA,+UNB.OF(XB);Enter control flags to buffer
|
||
MOVEI T1,<XONC_^D8!XOFFC> ;XON and XOFF characters
|
||
CALL LAP2B0 ;Enter them into buffer
|
||
CALL LAP2B0 ;Also input XON/XOFF characters
|
||
MOVX T1,SBFCC
|
||
CALL CSBDAV
|
||
RETSKP
|
||
|
||
BSLTHD: MOVE T3,T1 ;Save input arg
|
||
LOAD T1,SBLID,(SB) ;Remote slot ID
|
||
LSH T1,^D8 ;Shift to second byte
|
||
OPSTR <IOR T1,>,SBRID,(SB) ;Local slot ID into first byte
|
||
CALL LAP2B0 ;(Clobbers T2 only.)
|
||
MOVE T1,T3 ;Get original argument back
|
||
CALL LAP2B0 ;Enter count/slot type/credits
|
||
RET
|
||
|
||
|
||
|
||
;CRECHK - Remote Credit Check Routine
|
||
;
|
||
;Call: SB/ Slot Block Address
|
||
; CALL CRECHK
|
||
; No-Grant return
|
||
; Grant return
|
||
; T1/ <Number to grant>
|
||
|
||
; If the remote has less than the maximum number of transmit credits, try to
|
||
; compute the number of additional credits to grant him and return in T1,
|
||
; shifted by one byte (for convenience of caller). We can only grant credit
|
||
; if there is room for a non-zero integral number of full slot buffers (of
|
||
; length MXSLSI).
|
||
|
||
;[7469] If terminal has pause at end of page enabled always be sure to
|
||
;[7469] grant at least 1 credit. If zero credits are granted and the
|
||
;[7469] user hits end of page they will not be able to resume type out
|
||
;[7469] by pressing the unpause character, since the LAT box will not
|
||
;[7469] be able to send it.
|
||
|
||
CRECHK: MOVEI T1,MAXCRE ;Maximum number of credits remote may have.
|
||
OPSTR <SUB T1,>,SBRCR,(SB);His deficiency.
|
||
JUMPE T1,RTN ;Can't grant him more-- he already has limit.
|
||
MOVE T3,T1 ;Save remote's credit deficiency.
|
||
IFN FTOPS20,<
|
||
LOAD T4,SBTDB,(SB) ;Get the terminal dynamic pointer
|
||
LOAD T1,TIMAX,(T4) ;Maximum that will fit in an input buffer
|
||
SUB T1,TTICT(T4) ;Subtract current input count to get whats left
|
||
IDIVI T1,MXSLSI ;Compute number of slot buffer that would fit
|
||
IFE. T1
|
||
SETONE TTFWK,(T4) ;[7469] Hopefully start the process running
|
||
JE TT%PGM,TTFLGS(T4),RTN ;[7469] Jump if not in page mode
|
||
TMNE TTNXO,(T4) ;[7469] Pause at end of page?
|
||
MOVEI T1,1 ;[7469] Yes, always grant 1 credit
|
||
ENDIF.
|
||
JUMPE T1,[SETONE TTFWK,(T4);None, so can't grant more so force
|
||
JRST RTN] ; the process to wake.
|
||
>;end IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
MOVEI T1,TTIWRN## ;Get max characters for an input buffer
|
||
SUB T1,LDBTIC##(U) ;Minus number that have been echoed
|
||
SUB T1,LDBECC##(U) ;Also minus number that have not yet echoed
|
||
IDIVI T1,MXSLSI ;Compute number of slot buffer that would fit
|
||
JUMPE T1,RTN ;None, so can't grant more.
|
||
>;end IFN FTOPS10
|
||
|
||
CAMLE T1,T3 ;Make sure he never gets a total of more than
|
||
MOVE T1,T3 ; the maximum allowed.
|
||
RETSKP
|
||
|
||
|
||
|
||
IGNSLT: SETZM UN.BSZ+UNB.OF(RB) ;[7.1120]Force data to be ignored.
|
||
RETSKP ;This is a good return.
|
||
|
||
ILLSLT: OPSTRM <AOS>,HCISR,(HN) ;Increment host count
|
||
OPSTRM <AOS>,CCISR,(CB) ; and the per-server count
|
||
ILLSLX: RET ;Give a bad return
|
||
|
||
SUBTTL - Queue Handling Routines
|
||
|
||
;LAQUE - Add an element to the front of a queue
|
||
;
|
||
;Call: T1/ Address of Queue Header
|
||
; T2/ Address of Element to Add
|
||
; CALL LAQUE
|
||
; Normal Return
|
||
; This routine is used to queue either CBs or SBs. The queue headers
|
||
; and link words are always two words, and are described by the BEGSTR QL.
|
||
; All elements are linked in both forward and backward directions.
|
||
|
||
LAQUE: MOVE T4,T1 ;Save queue header address
|
||
OPSTR <SKIPE T3,>,QLFWD,(T1) ;Get old first queue element if any.
|
||
MOVE T1,T3 ; Old first element or Q header backward
|
||
STOR T2,QLBWD,(T1) ; pointer points to new element
|
||
STOR T2,QLFWD,(T4) ;Store new first queue element
|
||
SETZRO QLBWD,(T2) ;Zero its backward pointer
|
||
STOR T3,QLFWD,(T2) ;Set up its forward pointer
|
||
RET
|
||
|
||
;LAUNQ - Dequeue a queue element
|
||
;
|
||
;Call: T1/ Address of queue header
|
||
; T2/ Address of queue element to be unqueued
|
||
; CALL LAUNQ
|
||
; Normal return
|
||
;
|
||
;Uses: T3,T4
|
||
|
||
LAUNQ: LOAD T3,QLBWD,(T2) ;Get elements backward pointer
|
||
LOAD T4,QLFWD,(T2) ;Get its forward ptr also.
|
||
SKIPN T2,T4 ;Remove the element from the backward list
|
||
XMOVEI T2,QL.FWD(T1) ; by updating the backward
|
||
STOR T3,QLBWD,(T2) ; ptr of either next Q element or Q head
|
||
SKIPE T3 ;If backward ptr 0 update Q head forward ptr
|
||
XMOVEI T1,QL.FWD(T3) ; otherwise update that of the previous Q
|
||
STOR T4,QLFWD,(T1) ; element
|
||
RET
|
||
|
||
|
||
|
||
;QUE1WB - Routine to queue and element to the back of a 1 directional queue.
|
||
;
|
||
;Call: T1/ address of Q header block
|
||
; T2/ address of queue element to add to queue
|
||
; CALL QUE1WB
|
||
; Normal return
|
||
|
||
QUE1WB: OPSTR <SKIPN T3,>,QLBWD,(T1);Address of first element on Q
|
||
MOVE T3,T1 ;Zero, Q header fwd ptr points to new element
|
||
STOR T2,QLFWD,(T3) ;Update forward ptr of Q hdr or old Q tail
|
||
SETZRO QLFWD,(T2) ;Zero new elements forward ptr
|
||
STOR T2,QLBWD,(T1) ;New tail ptr
|
||
RET
|
||
|
||
;UNQ1WF - Routine to remove an element from the front of a 1 directional queue.
|
||
;
|
||
;Call: T1/ address of the Q header block
|
||
; CALL UNQ1WF
|
||
; Error return - queue emtpy
|
||
; Normal return
|
||
; T2/ address of element
|
||
|
||
UNQ1WF: OPSTR <SKIPN T2,>,QLFWD,(T1);Address of first element on Q
|
||
RET ;Zero, so queue is empty
|
||
OPSTR <SKIPN T3,>,QLFWD,(T2);If only 1 element on Q then update
|
||
STOR T3,QLBWD,(T1) ; the Q headers tail ptr (set to 0)
|
||
STOR T3,QLFWD,(T1) ;There is a new head of the Q (or 0)
|
||
RETSKP ;Return with the Q element in T2
|
||
|
||
SUBTTL - Buffer Handling Routines - Transmit Buffers
|
||
|
||
;GETXBH - Get the necessary number of transmit buffer headers
|
||
;
|
||
;Call: CB/ Address of the circuit block
|
||
; CALL GETXBH
|
||
; Error return - insufficient resources
|
||
; Normal return
|
||
|
||
GETXBH: MOVSI W1,-MAXXBF ;Number of buffers to get
|
||
GTXNXT: MOVEI T1,<<MINXBF+3>/4+XBF.OF>;Buffer length to get
|
||
CALL MMGTZW ;Go get the storage
|
||
JRST GTXFL ;Failed to get all that are needed
|
||
MOVX T2,<POINT 8,0>
|
||
STOR T2, MDAUX,+MDB.OF(T1);
|
||
MOVEI T2,SZ.MHD ;The message header always has
|
||
STOR T2,MDBYT,+MDB.OF(T1); 8 bytes.
|
||
MOVEI T2,VMC.XC ;Always use exec virtual paging
|
||
STOR T2,MDVMC,+MDB.OF(T1); ...
|
||
XMOVEI T2,<XBF.OF>(T1) ;
|
||
STOR T2,MDALA,+MDB.OF(T1);Address of start of header
|
||
MOVE T2,T1 ;Now queue to circuit blocks queue of free
|
||
XMOVEI T1,CB.XBQ(CB) ; transmit buffers
|
||
CALL QUE1WB ; ...
|
||
AOBJN W1,GTXNXT ;Get as many as required
|
||
RETSKP
|
||
|
||
; Failed to get the nececessary number of buffers. Must free those
|
||
; which we did get.
|
||
|
||
GTXFL: XMOVEI T1,CB.XBQ(CB) ;Unqueu each from the transmit free Q
|
||
CALL UNQ1WF ; ...
|
||
RET ;No more there so return with error
|
||
MOVE T1,T2 ;Give back the buffer to the memory
|
||
CALL MMFREE ; manager
|
||
JRST GTXFL ; and continue looping til all returned
|
||
|
||
|
||
|
||
;GETXBF - Get one long transmit buffer for real data
|
||
;
|
||
;Call: CB/ Address of the circuit block
|
||
; XB/ Address of the 1st MSD (header)
|
||
; CALL GETXBH
|
||
; Error return - insufficient resources
|
||
; Normal return
|
||
; T3/ MSD address (also saved in MD.NXT+MDB.OF(XB))
|
||
|
||
GETXBF: MOVEI T1,<MD.LEN+SZ.XBF>;Buffer length to get
|
||
IFN FTOPS20,<
|
||
CALL MMGTZW ;Go get the storage
|
||
>
|
||
IFN FTOPS10,<
|
||
CALL GETZBF ;Go get the storage
|
||
>
|
||
RET ;No luck!
|
||
MOVE T3,T1
|
||
SETZ T1,
|
||
MOVX T2,<POINT 8,0>
|
||
STOR T2,MDAUX,(T3);Byte pointer to message
|
||
MOVEI T1,SZ.XBF
|
||
STOR T1,MDBYT,(T3);Zero length
|
||
MOVEI T1,VMC.XC ;Always use exec virtual paging
|
||
STOR T1,MDVMC,(T3); ...
|
||
XMOVEI T1,<MD.LEN>(T3) ;
|
||
MOVEM T3,MD.NXT+MDB.OF(XB) ;Link header MSD to this
|
||
STOR T1,MDALA,(T3) ;Message address
|
||
RETSKP
|
||
|
||
|
||
|
||
;XBFCHK - Check for Transmit buffer
|
||
;
|
||
;Call: XB/
|
||
; CALL XBFCHK
|
||
; Error Return
|
||
; Normal Return
|
||
|
||
XBFCHK: SKIPE T3,MD.NXT+MDB.OF(XB) ;[7.1039]If we already have one,
|
||
RETSKP ;return
|
||
CALL GETXBF ;Get an MSD transmit buffer
|
||
RET ;None available, return failure
|
||
XMOVEI T1,<MD.LEN>(T3) ;[7.1039]Make a one word 8 bit
|
||
TLO T1,(<OWGP. 8,0>) ;[7.1039] global byte pointer and save as
|
||
STOR T1,UNBFA,+UNB.OF(XB); message byte pointer.
|
||
RETSKP
|
||
|
||
|
||
|
||
;RFXBFS - Release all free transmit buffers
|
||
;
|
||
;Call: CB/ circuit block address
|
||
; CALL RFXBFS
|
||
; Normal return
|
||
;
|
||
|
||
RFXBFS: XMOVEI T1,CB.XBQ(CB) ;Address of the free xmit buffer queue
|
||
CALL UNQ1WF ;Unqueue the head of the Q
|
||
RET
|
||
MOVE XB,T2 ;Put buffer address where RELXBH wants it
|
||
CALL RELXBH ;Go release it
|
||
JRST RFXBFS ;Get next
|
||
|
||
;RELXBF - Release Transmit Buffer
|
||
;
|
||
;Call: XB/ Address of buffer header
|
||
; CALL RELXBF
|
||
; Normal return
|
||
|
||
RELXBF: MOVEI T1,0 ;[7.1039]
|
||
EXCH T1,MD.NXT+MDB.OF(XB) ;[7.1039]If there is no MSD style buffer
|
||
JUMPE T1,RTN ;[7.1039] then just return
|
||
IFN FTOPS20,<
|
||
CALLRET MMFREE ;[7.1039] and free the MSD's storage.
|
||
>
|
||
IFN FTOPS10,<
|
||
CALLRET GIVBF ; and free the MSD's storage.
|
||
>
|
||
;RELXBH - Release Transmit Buffer Header and Buffer
|
||
;
|
||
;Call: XB/ Address of buffer header
|
||
; CALL RELXBH
|
||
; Normal return
|
||
|
||
RELXBH: CALL RELXBF ;Release the buffer first
|
||
MOVE T1,XB ;Now the header
|
||
CALL MMFREE
|
||
RET
|
||
|
||
SUBTTL - Buffer Handling Routines - Receive Buffers
|
||
|
||
;GETRBF - Get a Receive buffer
|
||
;
|
||
;Call: CALL GETRBF
|
||
; Error return - no receive buffers
|
||
; Normal Return
|
||
;
|
||
; This routine checks to see if enough receive buffers have been posted
|
||
; to the NI DLL to support the number of currently active circuits plus
|
||
; a new one. If buffers are needed and can be obtained, they are posted
|
||
; directly to the NI DLL. If some are needed, and cannot be obtained,
|
||
; the error return is taken.
|
||
|
||
GETRBF: STKVAR <BUFADR>
|
||
LOAD T1,HNNRB,(HN) ;Do check to see if we need more buffers.
|
||
LOAD T2,HNNAC,(HN)
|
||
CAIL T1,1(T2)
|
||
RETSKP ;No additional are needed. Return success.
|
||
MOVEI T1,<<LMRFSI+3>/4+UN.LEN+UE.LEN> ;Receive buffer size
|
||
IFN FTOPS20,<
|
||
CALL MMGTZW ;Get the number of required buffers
|
||
>
|
||
IFN FTOPS10,<
|
||
CALL GETZBF ;Get the number of required buffers
|
||
>
|
||
RET ;Can't, return error.
|
||
MOVEM T1,BUFADR ;Save address in case we can't post buffer
|
||
CALL RBPOST ;Post the receive buffer to NISRV
|
||
IFSKP.
|
||
OPSTRM <AOS>,HNNRB,(HN);Increment the number of receive buffers
|
||
RETSKP ;Return success
|
||
ENDIF.
|
||
MOVE T1,BUFADR ;Get address of buffer
|
||
IFN FTOPS20,<
|
||
CALLRET MMFREE ;Free the memory
|
||
>
|
||
IFN FTOPS10,<
|
||
CALLRET GIVBF ;Free the memory
|
||
>
|
||
|
||
ENDSV.
|
||
|
||
;RELRBF - Release a Receive buffer
|
||
;
|
||
;Call: RB/ Address of the buffer to release
|
||
; CALL RELRBF
|
||
; Normal Return
|
||
;
|
||
; This routine frees a receive buffer if there is already a sufficient number
|
||
; posted to the NI DLL otherwise the buffer is re-posted to the NI DLL.
|
||
|
||
RELRBF: LOAD T1,HNNRB,(HN) ;Do we still need this buffer?
|
||
LOAD T2,HNNAC,(HN)
|
||
CAILE T1,1(T2)
|
||
JRST RELRB0 ;No, so free it
|
||
MOVE T1,RB ;Yes, so
|
||
CALL RBPOST ; re-post it to NISRV
|
||
JRST RELRB0 ;NISRV could not accept it?! Release it.
|
||
RET ;Successfully re-posted. Return.
|
||
RELRB0: MOVE T1,RB ;Here to free the buffer.
|
||
IFN FTOPS10,<
|
||
CALL GIVBF
|
||
>
|
||
IFN FTOPS20,<
|
||
CALL MMFREE
|
||
>
|
||
OPSTRM <SOS>,HNNRB,(HN) ;Reduce the number of receive buffers
|
||
RET
|
||
|
||
IFN FTOPS10,<
|
||
SUBTTL SCNSER DEVICE DEPENDANT ROUTINES
|
||
;
|
||
; TOPS10 does not call a device dependant routine for each output
|
||
; character. Nor does it call a routine to change TTY PAGE.
|
||
; At each scheduler interval, we scan all LDBs in LATSER's queue
|
||
; to see what must be done with each one.
|
||
;
|
||
LATSCN: MOVEI T1,LATRTQ ;Get SCNSER's queue header
|
||
SNCALL (TOTAKE##,MCSEC1) ;Get next active LDB on the chain
|
||
RET ;None. Just return.
|
||
SKIPN SB,LDBLAT##(U) ;Get slot block address
|
||
RET ;None. This guy's a loser so punt.
|
||
MOVEI T1,0 ;T1 will get Slot flags
|
||
MOVEI T3,L1RCHP##
|
||
TDNE T3,LDBBYT##(U) ;Need to change parameters?
|
||
CALL LATCHP ;Yes. See what needs change and set T1
|
||
TXO T1,SBOUT ;Always set flag for output. Check later anyway
|
||
;
|
||
; Here if we MIGHT have characters to output, or need to change TTY PAGE
|
||
;
|
||
MOVE CB,SB.CBA(SB) ;And associated circuit block address
|
||
CALL SSBDAV ;And set this slot's flags
|
||
JRST LATSCN ;Look at next LDB in the queue
|
||
|
||
;
|
||
;Routine to see if we need to change recognition of XON/XOFF
|
||
;
|
||
;Call: U/ LDB address
|
||
;
|
||
;Return: Flag SBFCC set in T1 if we need to change
|
||
;
|
||
LATCHP: ANDCAM T3,LDBBYT##(U) ;Turn off CHP bit to show we checked
|
||
LDB T2,@[IW MCSEC1,LDPXNF##] ;Get XON/XOF flag
|
||
LOAD T3,SBXNF,(SB) ;Get bit that says what the LAT knows
|
||
CAMN T2,T3 ;Are they already the same?
|
||
RET ;Yes, no need to send a message, then
|
||
TXO T1,SBFCC ;Different. Need to send a message
|
||
STOR T2,SBXNF,(SB) ;AND remember what we are now.
|
||
RET
|
||
>;end IFN FTOPS10
|
||
ENDAV.
|
||
|
||
IFN FTOPS20,<
|
||
SUBTTL TTYSRV DEVICE DEPENDENT ROUTINES
|
||
|
||
XRENT (LTSTRO,G) ;[7.1024]LTSTRO::, XLTSTR::
|
||
|
||
MOVX T1,SBOUT
|
||
SETONE TTOTP,(T2) ;Set output active
|
||
JRST LTSSDC
|
||
|
||
XRENT (LTCOBF,G) ;[7.1024]LTCOBF::, XLTCOB::
|
||
|
||
MOVX T1,SBFOU
|
||
JRST LTSSDC
|
||
|
||
XRENT (LTEXF,G) ;[7.1024]LTEXF::, XLTEXF::
|
||
|
||
MOVX T1,SBFCC
|
||
LTSSDC: ACVAR <HN,XB,RB,CB,SB,W1,W2>
|
||
NOSKD1
|
||
CHNOFF DLSCHN
|
||
SKIPN SB,TTDEV(T2) ;Get the slot data base from TDB if not 0
|
||
JRST LTSSD0
|
||
MOVE CB,SB.CBA(SB) ;Get the circuit data base from slot block.
|
||
SAVEAC <T2> ;TTYSRV needs T2 returned intact
|
||
CALL SSBDAV
|
||
LTSSD0: CHNON DLSCHN
|
||
OKSKD1
|
||
RET
|
||
|
||
; TTYSRV Device Dependent Routine to see if SENDAL should be done on this
|
||
; line.
|
||
; Call: T2/ Line Number
|
||
; Non-skip Return/ Skip SENDALL to this Line
|
||
; Skip Return / Do SENDALL to this Line
|
||
|
||
XRENT (LTSALL,G) ;[7.1024]LTSALL::, XLTSAL::
|
||
|
||
SKIPG TTACTL(T2) ;Is line fully active?
|
||
RET ;No, don't do SENDALL
|
||
RETSKP ;Yes, do the SENDALL
|
||
|
||
; TTYSRV device dependent routine to perform hang-up action
|
||
;
|
||
;Call: T2/ Line Number
|
||
|
||
XRENT (LTHNGU,G) ;[7.1024]LTHNGU::, XLTHNG:
|
||
SAVEAC <T2> ;Caller wants this back intact
|
||
CALLX (MSEC1,STADYN) ;[7.1024]Get the dynamic data base
|
||
RET ;There is none
|
||
MOVX T1,SBSTO ;Mark to send STOP slot if necessary
|
||
CALL LTSSDC ;(CALLRET won't work here)
|
||
RET
|
||
|
||
; TTYSRV device dependent routine to see if output is possible on a line
|
||
;
|
||
; Call: T2/ TDB Address
|
||
; Non-skip Return/ Output not possible
|
||
; Skip Return / Output possible
|
||
|
||
XRENT (LTTCOU,G) ;[7.1024]LTTCOU::, XLTTCO::
|
||
|
||
RETSKP
|
||
|
||
; TTYSRV device dependent routine to set LAT Host terminal lines as
|
||
; high speed lines.
|
||
;
|
||
;RETSKP always with:
|
||
; T3/ ^D9600 to simulate high speed output
|
||
; T4/ IBFRC1 the high speed terminal characteristics word
|
||
|
||
XRENT (LTSOF,G) ;[7.1024]LTSOF::, XLTSOF::
|
||
|
||
MOVEI T3,^D9600 ;Fake 9600 baud
|
||
MOVE T4,IBFRC1 ;High speed buffer word
|
||
RETSKP ;Always
|
||
>;end IFN FTOPS20
|
||
|
||
IFN FTOPS10,<
|
||
SUBTTL More SCNSER device dependant routines
|
||
|
||
;Routine LTHNGU - LAT "disconnect" function
|
||
;Called by SCNSER thru ISRREM entry point in dispatch vector with
|
||
; a function code if IRRDSC in T3
|
||
;
|
||
; U/ LDB address
|
||
; T3/IRRDSC
|
||
; CALL LTHNGU
|
||
; Returns +2 always (note: there is no "error" return)
|
||
;
|
||
LTHNGU: MOVX T1,SBSTO ;Yes, we want to stop this slot
|
||
CALL LTSSDC ;SO do it
|
||
RETSKP ;And indicate success to SCNSER
|
||
;
|
||
;Routine LATREM
|
||
;Called from SCNSER through dispatch vector element ISRREM (7)
|
||
;
|
||
; U/ LDB address
|
||
; T3/ Function code
|
||
; Possible values are:
|
||
; (1) Input buffer low (ignored)
|
||
; (2) Input character not stored (ignored)
|
||
; (IRRSCG) Eat all output characters
|
||
; (IRRDSC) Disconnect LAT terminal
|
||
; (IRRTMO) Disconnect idle terminal
|
||
;
|
||
LATREM: CAIN T3,IRRDSC ;Is the the "disconnect" function?
|
||
CALLRET LTHNGU ;Yes, do it.
|
||
CAIN T3,IRRTMO ;Is it the "timeout" function?
|
||
CALLRET LTHNGU ;Yes, do it.
|
||
CAIE T3,IRRSCG ;Is it "send character gobbler"?
|
||
RET ;No, those are all we know about
|
||
LTCOBF: MOVX T1,SBFOU ;User hit ^O, tell remote to gobble output
|
||
LTSSDC: ACVAR <HN,XB,RB,CB,SB,W1,W2>
|
||
ETHLOK ;Interlock against races
|
||
SKIPN SB,LDBLAT##(U) ;Get slot data base from LDB
|
||
JRST LTSSD0 ;Not there any more, ignore
|
||
MOVE CB,SB.CBA(SB) ;Get circuit data base from slot block.
|
||
CALL SSBDAV
|
||
LTSSD0: ETHULK ;Release interlock
|
||
RET
|
||
>;end IFN FTOPS10
|
||
|
||
|
||
SUBTTL General Untility Routines
|
||
|
||
;
|
||
;RANDOM - get a "random" number
|
||
;
|
||
;Call: T1/ Maximum number allowed
|
||
; CALL RANDOM
|
||
; Normal Return
|
||
; T1/ Random Number
|
||
|
||
RANDOM: MOVE T4,T1 ;Save for modulo
|
||
IFN FTOPS20,<
|
||
CALLX (MSEC1,LGTAD) ;[7.1024]Get internal time and date
|
||
>;end IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVE T1,DATE## ;get TOPS-10 time and date
|
||
>;end IFN FTOPS10
|
||
ANDI T1,777777 ;Time only
|
||
IDIV T1,T4 ;MODULO max, (which is the remainder in T2)
|
||
SKIPN T1,T2 ;GET remainder
|
||
MOVEI T1,1 ;But if it's zero, make it 1
|
||
RET
|
||
|
||
;GTCHCT - Get character count for terminal output.
|
||
;Call: T2/ TDB address
|
||
;Return:
|
||
; T1/ Total character count
|
||
|
||
IFN FTOPS20,<
|
||
|
||
GTCHCT: SETZ T1,0
|
||
TMNN TTSAL,(T2) ;Is there a send all in progress?
|
||
IFSKP. ;Yes, must include count of the
|
||
LOAD T1,TSALC,(T2) ; send all buffer.
|
||
ENDIF.
|
||
ADD T1,TTOCT(T2) ;Add the terminal buffer count.
|
||
RET
|
||
|
||
>;END IFN FTOPS20
|
||
|
||
ENDAV.
|
||
|
||
SUBTTL LAGTCR - LAT memory management routines
|
||
|
||
;
|
||
; Subroutine to tell COMMON how much core LAT needs at ONCE time
|
||
;
|
||
;Call: CALL LAGTCR
|
||
;
|
||
;Return: +1 always with T1/ size of memory LAT needs, which is:
|
||
;
|
||
; Space for 1 outstanding receive buffer +
|
||
; for each possible open circuit: MAXXBF transmit buffers
|
||
; + 1 receive buffer
|
||
|
||
IFN FTOPS10,<
|
||
|
||
; MAX.(BUFSIZ,<RBFSIZ,XBFSIZ>) ;BUFSIZ is size of largest buffer
|
||
; BUFSIZ==BUFSIZ+QL.LEN ;we need + 2 words for linking list
|
||
BUFSIZ==PAGSIZ ;Oh, the hell with it! receive buffers have
|
||
;to be contiguous, so don't bother to
|
||
;split a buffer across a page boundary.
|
||
;Luckily, the actual size of a buffer
|
||
;is slightly smaller than a page.
|
||
NBUFS==<1+<MAXXBF+1>> ;
|
||
;
|
||
|
||
|
||
$CSUB
|
||
LAGTCR::
|
||
MOVEI T1,<BUFSIZ*NBUFS>
|
||
RET
|
||
XRESCD
|
||
|
||
;
|
||
; Routine to ask for more memory from user free core
|
||
; We should get it a tick or two later.
|
||
;
|
||
CHKWFB: SKIPE T1,LATWFB ;Do we want any more buffers?
|
||
SKIPE LATRFB ;And have we not yet aksed for them?
|
||
RET ;No to either, don't get memory now.
|
||
;
|
||
; Here we have finally decided it's our turn to ask for some memory
|
||
;
|
||
IMULI T1,BUFSIZ ;Calculate how many words
|
||
TRZE T1,PG.BDY ;Round up to page bound
|
||
ADDI T1,PAGSIZ
|
||
MOVEM T1,LATRFB ;Remember how many words we asked for.
|
||
LSH T1,W2PLSH ;Convert to pages
|
||
HRLI T1,(MS.DCN) ;Section to allocate from
|
||
XMOVEI T2,CHKRFB ;Callback routine address
|
||
XJRST [MCSEC1+GETCLP##] ;Ask for the space
|
||
;
|
||
; CHKRFB - Routine called when VMSER gave us memory
|
||
; If so, link it into free buffer list
|
||
;
|
||
CHKRFB: MOVE T4,T1 ;Get address of start
|
||
SETZ T1, ;Get a zero
|
||
EXCH T1,LATRFB ;Get number of pages we wanted (and clear it)
|
||
IDIVI T1,BUFSIZ ;Convert to number of buffers
|
||
ADDM T1,LATNFB ;Indicate that we've got more
|
||
MOVE T2,T4 ;Get address of first buffer
|
||
MOVE T4,T1 ;save buffer count
|
||
ALCBUF: MOVEI T1,LATFRE ;QUEUE header for LAT free core
|
||
CALL QUE1WB ;Link this buffer to the list.
|
||
ADDI T2,BUFSIZ ;Point to next one.
|
||
SOJG T4,ALCBUF ;Until all buffers have been allocated.
|
||
RET
|
||
;
|
||
; GETZBF - Routine to get a receive or transmit buffer and zero it.
|
||
;
|
||
;Call: T1/ required size
|
||
;Return: +1 failure
|
||
; +2 success T1/ address of buffer
|
||
;
|
||
GETZBF: PUSH P,T1 ;Save size wanted
|
||
MOVEI T1,LATFRE ;Address of queue header for free pool
|
||
CALL UNQ1WF ;Get a buffer
|
||
JRST TPOPJ ;Couldn't, restore T1 and return.
|
||
SOS LATNFB ;One less free buffer
|
||
PUSH P,T2 ;SAVE ADDRESS OF BUFFER
|
||
XMOVEI T3,1(T2) ;POINT TO SECOND WORD
|
||
SETZM (T2) ;ZERO FIRST WORD
|
||
MOVEI T1,BUFSIZ-1 ;SET UP TO ZERO THE WHOLE BLOCK
|
||
XBLT. T1 ;DO IT
|
||
POP P,T2 ;RESTORE ADDRESS
|
||
POP P,T1 ;Restore size
|
||
HRLI T1,'LAT' ;check word
|
||
MOVEM T1,(T2) ;save <'LAT',,size> as first word
|
||
HRRZ T3,T1 ;Isolate size
|
||
ADD T3,T2 ;Point to end of buffer
|
||
HRLI T1,'END'
|
||
MOVEM T1,1(T3)
|
||
XMOVEI T1,1(T2) ;POINT to address of data portion
|
||
RETSKP
|
||
|
||
;
|
||
; GIVBF - Routine to give back a buffer to free pool
|
||
;
|
||
;Call: T1/ address of data portion of buffer
|
||
;Return: +1 always
|
||
;
|
||
GIVBF: SUBI T1,1 ;Point to size word
|
||
HLRZ T2,(T1) ;Get check code
|
||
HRRZ T3,(T1) ;Get size
|
||
ADD T3,T1 ;Point to near end of buffer
|
||
HLRZ T3,1(T3) ;Get ending check code
|
||
CAIN T3,'END' ;See if either end has been wiped out
|
||
CAIE T2,'LAT' ;Is it still there?
|
||
BUG. (CHK,LATMEM,LATSER,SOFT,<LAT buffer overwritten>,<<T1,ADDRESS>>,<
|
||
While trying to return a buffer, LATSER discovered it had been overwritten.>)
|
||
MOVE T2,T1 ;Now return the buffer
|
||
MOVEI T1,LATFRE ;To the queue of free buffers
|
||
AOS LATNFB ;Count one more buffer available
|
||
CALLRET QUE1WB ;For re-use
|
||
> ;END IFN FTOPS10
|
||
|
||
MMGTZW:
|
||
IFN FTOPS20,<
|
||
CALLRET DNGWDZ ;[7.1024]
|
||
>;END IFN FTOPS20
|
||
IFN FTOPS10,<
|
||
MOVEI T2,1(T1) ;Going to ask for 1 more word for check
|
||
PUSH P,T2 ;save requested size
|
||
SNCALL (GETEWZ##,MCSEC1) ;Get zeroed core from ethernet free pool
|
||
JRST TPOPJ ;No luck
|
||
POP P,T2 ;Get back requested size
|
||
ADDI T1,1 ;Point to data portion of block
|
||
MOVEM T2,-1(T1) ;save length as first word of block
|
||
RETSKP ;And return it to caller
|
||
>;END IFN FTOPS10
|
||
|
||
MMFREE:
|
||
IFN FTOPS20,<
|
||
CALLRET DNFWDS ;[7.1024]
|
||
>
|
||
IFN FTOPS10,<
|
||
XMOVEI T2,-1(T1) ;Point to block-1
|
||
HRRZ T1,(T2) ;Which contains length of block
|
||
XJRST [MCSEC1+GIVEWS##] ;and give it back to ethernet free pool.
|
||
;
|
||
; Subroutine to convert SIXBIT nodename to ASCII
|
||
;
|
||
;Call: T1/ SIXBIT node name
|
||
;
|
||
;Return: +1 always with ASCII in OURNAM, OURNAM+1
|
||
; and character in OURCNT
|
||
;
|
||
CVTNOD: SETZM OURCNT ;No characters yet
|
||
SETZM OURNAM ;Or name
|
||
SETZM OURNAM+1 ; ...
|
||
JUMPE T1,RTN ;Done if no characters left
|
||
MOVE T3,[POINT 7,OURNAM] ;Where to put node name
|
||
CVTNO1: SETZ T2, ;Zap the temp AC
|
||
ROTC T1,6 ;Get next character into T2
|
||
ADDI T2,40 ;Convert to ASCII
|
||
AOS OURCNT ;Count characters done
|
||
IDPB T2,T3 ;Put the character into the name
|
||
JUMPN T1,CVTNO1 ;Continue
|
||
RET ;Done
|
||
>;END IFN FTOPS10
|
||
XLIST
|
||
LIT
|
||
|
||
IFN FTOPS10,<
|
||
define .xcrf1(syms),<
|
||
irp syms,<purge syms>>
|
||
.xcmsy ;Purge some stupid MACSYM symbols
|
||
PRGALL ;Purge all ..nnnn symbols
|
||
>;end IFN FTOPS10
|
||
|
||
END
|