Trailing-Edge
-
PDP-10 Archives
-
bb-x130a-sb
-
swinet.mac
There are 4 other files named swinet.mac in the archive. Click here to see a list.
TITLE .NET SWIL network operations
SUBTTL Robert Houk/RDH
SEARCH SWIDEF, SWIL ;SWIL PACKAGE DEFINITIONS
SEARCH JOBDAT, MACTEN, UUOSYM ;STANDARD DEFINITIONS
SALL ;PRETTY LISTINGS
.DIREC FLBLST ;PRETTIER LISTINGS
TWOSEG 400000
Copyright (C) Digital Equipment Corporation 1984.
COMMENT \
Copyright (C) 1984
Digital Equipment Corporation, Maynard, Massachusetts, U.S.A.
This software is furnished under a license and may be used and copied only
in accordance with the terms of such license and with the inclusion of the
above copyright notice. This software or any other copies thereof may not
be provided or otherwise made available to any other person. No title to
and ownership of the software is hereby transferred.
The information in this software is subject to change without notice and
should not be construed as a commitment by Digital Equipment Corporation.
Digital assumes no responsibility for the use or reliability of its
software on equipment which is not supplied by Digital.
\
;SWINET VERSION IDENTIFICATION
MAJVER==1 ;MAJOR VERSION LEVEL
MINVER==0 ;MINOR (MAINTENANCE RELEASE) LEVEL
CSTVER==0 ;CUSTOMER VERSION (WHO LAST . . .)
EDTVER==0 ;EDIT LEVEL
%%SNET==:<BYTE (3)CSTVER(9)MAJVER(6)MINVER(18)EDTVER>
IF2,< PURGE CSTVER,MAJVER,MINVER,EDTVER>
SUBTTL Revision History
;INITIAL CREATION 21-MAR-80
SUBTTL DAP Message Service Routines
;RDSTS -- READ AND TRY TO MAKE SENSE OF RECEIVED DAP STATUS
;CALL IS:
;
; PUSHJ P,RDSTS
; error return
; normal return
;
;RDSTS will read in the status message from the network stream via
;RDDAP, so call RDSTS upon receipt of the $DHSTS code.
;
;The error return is taken if the network dies or the status message
;makes no sense (uses a reserved code, etc.)
;
;On normal return M0 will contain the translated 18-bit status code.
;
;Uses T1 - T4.
ENTRY .RDSTS
INTERN RDSTS0, RDSTS1
.RDSTS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RDSTS0: PUSHJ P,.SAVE4## ;SAVE THE P'S
RDSTS1: SKIPLE T2,.IODIM(IO) ;GET INPUT MESSAGE TYPE FROM RDMSG
CAIE T2,$DHSTS ;IT HAD BETTER BE STATUS!
STOPCD <RDSTS called without a status message>
SETZB T3,T4 ;INITIALIZE SOME 0 VALUES
MOVDM T3,STC ;CLEAR OUT STATUS CODE FIELD
MOVDM T3,SRA ;CLEAR OUT RECORD ADDRESS FIELD
MOVDM T3,SRN ;CLEAR OUT RECORD NUMBER FIELD
MOVDM T3,STV ;CLEAR OUT SECONDARY STATUS FIELD
;READ IN THE STATUS MESSAGE
PUSHJ P,RDDAP1 ;SLURP UP THE STATUS MESSAGE
POPJ P, ;SIGH
PJRST RDSTC1 ;AND CONVERT IT TO ERROR/EXCEPTION CODE
;RDSTC -- TRANSLATE DAP STATUS CODE INTO INTERNAL ERROR/EXCEPTION CODE
;CALL IS:
;
; PUSHJ P,RDSTC
; error return
; normal return
;
;RDSTC takes the DAP error status from the I/O CDB (as read in by RDSTS)
;and translates it into NIP/NFT internal error/exception code. The new
;code is always returned in register M0.
;
;The error return is taken if the DAP status code is illegal or otherwise
;unintelligible.
;
;Uses T1 - T4.
ENTRY .RDSTC
INTERN RDSTC0, RDSTC1
.RDSTC: PUSHJ P,.SACIO## ;CONVERT TO I/O CONTEXT
RDSTC0: ;WE DON'T STOMP ON THE P'S HERE
RDSTC1: LDB T1,PDPEMA ;DAP "MACCODE" FIELD
LDB T2,PDPEMI ;DAP "MICCODE" FIELD
LDB T3,PDPEMT ;MESSAGE TYPE WITHIN MICCODE
LDB T4,PDPEMF ;MESSAGE FIELD WITHIN MESSAGE TYPE
PJRST @RDSTCX(T1) ;DISPATCH ON STATUS CLASS
;STATUS CODE FIELD POINTERS
PDPEMA::POINT 04,.IDSTC(IO),23;DAP "MACCODE" FIELD
PDPEMI::POINT 12,.IDSTC(IO),35;DAP "MICCODE" FIELD
PDPEMT::POINT 06,.IDSTC(IO),29;MESSAGE TYPE WITHIN MICCODE
PDPEMF::POINT 06,.IDSTC(IO),35;MESSAGE FIELD WITHIN MESSAGE TYPE
;STATUS MACRO-CODE DISPATCH
RDSTCX: IFIW RD00S ;OPERATION IN PROGRESS
IFIW RD01S ;OPERATION SUCCESSFUL
IFIW RD02S ;UNSUPPORTED FUNCTION
IFIW RD03S ;RESERVED
IFIW RD04S ;FILE ACCESS
IFIW RD05S ;I/O TRANSMISSION ERROR
IFIW RD06S ;I/O OPERATION WARNING
IFIW RD07S ;ERROR CLOSING FILE
IFIW RD10S ;DAP MESSAGE SYNTAX ERROR
IFIW RD11S ;DAP MESSAGE FIELD ERROR
IFIW RD12S ;DAP MESSAGE OUT OF SYNC
IFIW RD13S ;RESERVED
IFIW RD14S ;RESERVED
IFIW RD15S ;RESERVED
IFIW RD16S ;CUSTOMER-DEFINED
IFIW RD17S ;CUSTOMER-DEFINED
;00 - OPERATION PENDING
RD00S: MOVEI M0,$EGOIP ;"OPERATION IN PROGRESS" (AS A WILD GUESS)
JRST .POPJ1## ;RETURN STATUS
;01 - OPERATION SUCCESSFUL
RD01S: MOVEI M0,$EGAOK ;"A-OK" (AS A WILD GUESS)
JRST .POPJ1## ;RETURN STATUS
;02 - UNSUPPORTED DAP FUNCTION
RD02S: MOVEI M0,$EERDE ;REMOTE DAP ERROR
JRST .POPJ1## ;RETURN STATUS
;03 - XXX - RESERVED
RD03S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
POPJ P, ;RETURN ERROR
;04 - FILE ACCESS ERROR
RD04S: MOVEI T4,DS2EF ;CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO FILE ACCESS ERROR
MOVEI T1,$EFDAP ;BIZARRE DAP STATUS ERROR
MOVE M0,T1 ;RETURN STATUS IN M0
JRST .POPJ1## ;RETURN STATUS
;05 - I/O DATA TRANSMISSION ERROR
RD05S: MOVEI T4,DS2EI ;CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO I/O ERROR
JRST RD05S2 ;NOT I/O CODE - MAYBE FILE CODE?
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
RD05S2: MOVEI T4,DS2EF ;FILE-LEVEL CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO FILE ERROR
MOVEI T1,$EIDAP ;BIZARRE DAP I/O STATUS ERROR
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
;06 - I/O DATA TRANSMISSION WARNING
RD06S: MOVEI T4,DS2EI ;CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO I/O ERROR
JRST RD06S2 ;TRY FOR FILE ERROR
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
RD06S2: MOVEI T4,DS2EF ;FILE-LEVEL CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO FILE ERROR
MOVEI T1,$EIDAP ;BIZARRE DAP I/O STATUS ERROR
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
;07 - FILE/I/O CLOSE ERROR
RD07S: MOVEI T4,DS2EI ;CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO I/O ERROR
JRST RD07S2 ;TRY FOR FILE ERROR
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
RD07S2: MOVEI T4,DS2EF ;FILE-LEVEL CONVERSION TABLE
PUSHJ P,.CFIND## ;TRY TO CONVERT TO FILE ERROR
MOVEI T1,$EFDAP ;BIZARRE DAP FILE STATUS ERROR
MOVE M0,T1 ;POSITION IN M0
JRST .POPJ1## ;AND RETURN STATUS
;10 - DAP SYNTAX ERROR
RD10S: MOVEI M0,$EERDE ;REMOTE DAP ERROR
JRST .POPJ1## ;RETURN STATUS
;11 - DAP FIELD ERROR
RD11S: MOVEI M0,$EERDE ;REMOTE DAP ERROR
JRST .POPJ1## ;RETURN STATUS
;12 - DAP MESSAGE OUT OF SYNC
RD12S: MOVEI M0,$EERDE ;REMOTE DAP ERROR
JRST .POPJ1## ;RETURN STATUS
;13 - XXX - RESERVED
RD13S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
JRST .POPJ1## ;RETURN STATUS
;14 - XXX - RESERVED
RD14S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
JRST .POPJ1## ;RETURN STATUS
;15 - XXX - RESERVED
RD15S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
JRST .POPJ1## ;RETURN STATUS
;16 - XXX - CUSTOMER DEFINED
RD16S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
JRST .POPJ1## ;RETURN STATUS
;17 - XXX - CUSTOMER DEFINED
RD17S: MOVEI M0,$EEUDS ;UNKNOWN DAP STATUS
JRST .POPJ1## ;RETURN STATUS
;CONVERSION TABLE: DAP STATUS TO FILE ACCESS ERROR
DS2EF:: $EFRAE,,$DSACC ;"GENERIC" REMOTE FILE ACCESS ERROR
$EFNSD,,$DSDEV ;BAD DEVICE; NO SUCH DEVICE
$EFTBL,,$DSDME ;SYSTEM DYNAMIC MEMORY EXHAUSTED
$EFDNF,,$DSDNF ;DIRECTORY NOT FOUND
$EFAEF,,$DSFEX ;(DUPL) ALREADY EXISTING FILE
$EFFLK,,$DSFLK ;FILE LOCKED BY ANOTHER USER
$EFFNF,,$DSFNF ;FILE NOT FOUND
$EFNRM,,$DSFUL ;NO ROOM - DEVICE/FILE IS FULL
$EFFUL,,$DSFUL ;DEVICE/FILE IS FULL
$EFPRT,,$DSPRV ;PRIVILEGE VIOLATION
$EFILU,,$DSSYS ;SYSTEM DIRECTIVE ERROR
$EFWLK,,$DSWLK ;DEVICE IS WRITE-LOCKED
$EFRIB,,$DSIFA ;ILL FILE ATTR; CORRUPT FILE HEADER
$EFQTA,,$DSQTA ;QUOTA EXCEEDED
$EFFBM,,$DSFBM ;FILE BEING MODIFIED (ANOTHER WRITER)
$EFDNA,,$DSDNA ;DEVICE NOT AVAILABLE
$EFNSD,,$DSDNF ;DEVICE NOT FOUND (NO SUCH DEVICE)
$EFPOA,,$DSPOA ;PARTIAL ALLOCATION ONLY
$EFBNF,,$DSBNF ;SPECIFIED BLOCK NOT FREE
$EFCSD,,$DSCSD ;CAN'T SUPERSEDE DIRECTORY FILE
$EFDNE,,$DSDNE ;CAN'T DELETE NON-EMPTY DIRECTORY FILE
$EFSNF,,$DSSNF ;SUB-FILE-DIRECTORY NOT FOUND
$EFSLE,,$DSSLE ;SEARCH LIST EMPTY
$EFLVL,,$DSLVL ;SUB-FILE-DIRECTORIES NESTED TOO DEEPLY
$EFNCE,,$DSNCE ;NO-CREATE FOR ENTIRE SEARCH LIST
$EFFCU,,$DSFCU ;CAN'T UPDATE FILE
$EFENC,,$DSENC ;EXCEEDED NETWORK CAPACITY
$EFTNA,,$DSTNA ;TSK DEVICE NOT AVAILABLE
$EFNSN,,$DSNSN ;NO SUCH NODE
$EFSIU,,$DSSIU ;SUB-FILE-DIRECTORY IN USE ON RENAME
$EFNDR,,$DSNDR ;CAN'T DELETE FILE - NDR LOCK SET
$EFJCH,,$DSJCH ;TOO MANY SIMULTANEOUS FILE ACCESSES
$EFSSL,,$DSSSL ;CAN'T RENAME SUB-FILE-DIRECTORY TO LOWER LVL
$EFDDU,,$DSDDU ;DEVICE "DOWN" AND UNUSEABLE
$EFDRS,,$DSDRS ;DEVICE IS RESTRICTED
$EFDCM,,$DSDCM ;DEVICE CONTROLLED BY MDA, NOT ASSIGNABLE
$EFDAJ,,$DSDAJ ;DEVICE ASSIGNED TO ANOTHER JOB
$EFIDM,,$DSIDM ;ILLEGAL I/O DATA MODE
;"DUPLICATES", SEPARATED TO PRIORITIZE ERRORS FOR FAL
$EFAEF,,$DSCFS ;CREATED FILE SUPERSEDED EXTANT FILE
$EFAEF,,$DSRFE ;RENAME TO EXTANT FILE
0
;CONVERSION TABLE: DAP STATUS TO I/O TRANSMISSION ERROR
DS2EI:: $EIEOF,,$DSEOF ;END OF FILE
$EIFUL,,$DSFUL ;DEVICE FULL
$EIBKT,,$DSRTB ;RECORD/BLOCK TOO LARGE
$EIHWL,,$DSWLK ;DEVICE IS (HARDWARE) WRITE-LOCKED
$EIDEV,,$DSHDE ;HARD DEVICE ERROR
$EIDAT,,$DSPAR ;DEVICE PARITY ERROR
$EIEOV,,$DSEOV ;END OF VOLUME
$EICKE,,$DSCKE ;NETWORK FILE DATA CRC (CHECKSUM) ERROR
$EIQTA,,$DSQTA ;USER QUOTA EXCEEDED
$EILLE,,$DSLLE ;LINEPRINTER PAGE LIMIT EXCEEDED
$EIVFE,,$DSVFE ;LINEPRINTER VFU FORMAT ERROR
$EILUC,,$DSLUC ;LINEPRINTER "UNDEFINED CHARACTER" ERROR
$EIVRP,,$DSVRP ;LINEPRINTER VFU RAM PARITY ERROR
$EIRIE,,$DSRER ;GENERIC/UNSPECIFIED READ ERROR
$EIRIE,,$DSWER ;GENERIC/UNSPECIFIED WRITE ERROR
;"DUPLICATES", SEPARATED TO PRIORITIZE ERRORS FOR FAL
$EISWL,,$DSWLK ;DEVICE IS (SOFTWARE) WRITE-LOCKED
0
;RDDAT -- START READING A DAP DATA MESSAGE
;CALL IS:
;
; MOVX T2,<CDB>
; PUSHJ P,RDDAT
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return M0 contains an error code (network died, etc.).
;
;On normal return the DAP input routines (i.e., RDBYT) are ready to
;read and return data bytes. The DAP DATA RCN (record number) field
;returned in T2/T3.
;
;Uses T1 - T4.
ENTRY .RDDAT
INTERN RDDAT0, RDDAT1
.RDDAT: PUSHJ P,.SACIO## ;SETUP I/O CDB ADDRESS
RDDAT0: PUSHJ P,.SAVE4## ;SAVE THE P'S
RDDAT1: SKIPLE T2,.IODIM(IO) ;GET CURRENT INPUT MESSAGE TYPE
CAIE T2,$DHDAT ;IS IT DATA?
STOPCD <Not a DAP DATA message in RDDAT>
PUSHJ P,RDDAP2 ;HANDLE TEMPLATED PORTION OF DATA MESSAGE
POPJ P, ;SOMETHING BAD HAPPENED
MOVD T2,RCN ;GET RECORD NUMBER (IF ANY)
JRST .POPJ1## ;READY TO EXTRACT THE DATA BYTES
;RDDAP -- READ AND STORE A GENERIC DAP MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<code>
; PUSHJ P,RDDAP
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB, and <code> is the
;DAP message code of the incoming DAP message. Data messages
;(<code> = $DHDAT) are illegal.
;
;On error return, M0 contains an error code (network died or some sort
;of DAP error such as message too short). If the error was DAPpish in
;origin, a status message will have been sent to the other side telling
;of the error.
;
;On normal return the DAP message has been read into the .IODAP area in
;the I/O CDB, ready to be translated into the usual CDB stuff.
;
;Uses acs T1, T2, T3, T4
ENTRY .RDDAP
INTERN RDDAP0, RDDAP1
.RDDAP: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RDDAP0: PUSHJ P,.SAVE4## ;SAVE LOTS OF ACS
RDDAP1: CAIN T2,$DHDAT ;BETTER NOT BE A DATA MESSAGE
STOPCD <RDDAP called for DATA message>
RDDAP2: MOVEI T4,DAPIDX ;DAP INDEX TABLE
PUSHJ P,.CFIND## ;FIND THE INDEX ENTRY FOR THIS MESSAGE TYPE
PJRST RDEUM ;ERROR - UNKNOWN MESSAGE TYPE
HRRZM T1,.IODRX(IO) ;SET CURRENT RDDAP EXECUTION INDEX
HRRZM T2,.IODIM(IO) ;SET CURRENT INPUT MESSAGE TYPE
;LOOP READING FIELDS FROM THE DAP INPUT MESSAGE
RDDAP3: PUSHJ P,RDBYT0 ;GET NEXT DAP BYTE
JRST RDDAP7 ;END OF MESSAGE ACCEPTABLE HERE
PUSHJ P,RDBYR0 ;SAVE BYTE TO BE RE-READ
STOPCD ;CAN'T HAPPEN
AOS P1,.IODRX(IO) ;ADVANCE TO NEXT FIELD
MOVE T1,DAPXCT(P1) ;EXECUTION TABLE ENTRY FOR THIS FIELD
LDB T2,[POINTR T1,DX$COD] ;FIELD "NUMBER"
LDB T3,[POINTR T1,DX$TYP] ;FIELD "TYPE"
CAILE T3,$DXTMX ;RANGE CHECK AGAINST KNOWN FIELDS
STOPCD <RDDAP DX$TYP field entry too big>
JUMPE T3,RDDAP5 ;END OF MESSAGE TEMPLATE?
.XCREF $DXTMS ;CREF REFERENCE TO SYMBOLIC NAME
MOVEM T2,.IODRF(IO) ;SAVE IN CASE OF ERROR
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;CALL FIELD PROCESSOR WITH P1/DAPXCT INDEX AND T1/DAPXCT TABLE ENTRY
PUSHJ P,@RDDAPX(T3) ;DISPATCH ON FIELD TYPE
POPJ P, ;ERROR SOMEWHERE
JRST RDDAP3 ;LOOP BACK FOR REST OF THE MESSAGE
;HERE WHEN THE INPUT DAP MESSAGE SHOULD BE EXHAUSTED (SINCE OUR TEMPLATE
;USED UP ALL ITS FIELD DEFINITIONS).
RDDAP5: MOVE T2,.IODIM(IO) ;GET INPUT MESSAGE TYPE
CAIN T2,$DHDAT ;DATA MESSAGE?
JRST .POPJ1## ;YES, SOMEONE ELSE READS THE REST
PUSHJ P,RDBYT1 ;SEE IF ANY MORE DATA
JRST RDDAP7 ;PROBABLY NOT
HRRZ T1,.IODIM(IO) ;TOO MUCH DATA PRESENT
CAIE T1,$DHCFG ;IN CONFIGURATION MESSAGE?
PJRST RDEUF ;NO, ERROR - UNKNOWN FIELD IN MESSAGE
PJRST RDEAT1 ;YES, OK, JUST EAT EXCESS CONFIGURATION
RDDAP7: JUMPE M0,.POPJ1## ;IF OUT OF DAP DATA THEN WE'RE HAPPY
POPJ P, ;OTHERWISE NETWORK DIED, ERROR
;DAP MESSAGE FIELD PROCESSOR DISPATCH TABLE
;EACH FIELD PROCESSING ROUTINE IS ENTERED WITH:
; T1/DAPXCT TABLE ENTRY FOR THE FIELD
; P1/DAPXCT TABLE INDEX FOR THE FIELD
;ACS T1 - T4, AND P1 - P4 ARE AVAILABLE FOR USAGE WITHIN THE VARIOUS
;FIELD PROCESSING ROUTINES
RDDAPX: RD00T ;00 - START OF DAP MESSAGE TEMPLATE
RD01T ;01 - ASCII TEXT
RD02T ;02 - BINARY DATA
RD03T ;03 - COMPRESSED (1 WORD/5 BYTES) BINARY
RD04T ;04 - FLAGS (OR BIT MAP)
RD05T ;05 - IMAGE 8-BIT BYTES
RD06T ;06 - MENU FIELD FOR REST OF MESSAGE
RD07T ;07 - DATE/TIME IN ASCII
;RD00T - START OF MESSAGE TEMPLATE IN EXECUTION TABLE
RD00T: STOPCD <RD00T dispatch in RDDAP>
;RD01T - ASCII TEXT FIELD
RD01T: PUSHJ P,TSAV11## ;NEED A SCRATCH LOCATION
LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH (DAP BYTES)
LDB T4,[POINTR T1,DX$IOX] ;FIELD OFFSET INTO .IODAP
ADD T4,[POINT 7,.IODAP(IO)] ;MAKE INTO BYTE POINTER
SETZM -T1(P) ;NO TRAILING SPACE YET
TXNE T1,DX$XTN ;EXTENSIBLE ASCII?
JRST RD01T5 ;YES
TXNN T1,DX$VAR ;VARIABLE LENGTH ASCII STRING?
JRST RD01T3 ;NO, FIXED LENGTH
PUSHJ P,RDBYT1 ;YES, READ STRING LENGTH
PJRST RDEIE ;ERROR IN FIELD
CAMLE T2,T3 ;FIELD LENGTH WITHIN SPECS?
PJRST RDEIE ;NO, TOO BIG, ERROR IN FIELD
EXCH T3,T2 ;YES, OK, SET REAL FIELD LENGTH
SUB T2,T3 ;T2:=SPACE LEFT OVER
MOVEM T2,-T1(P) ;SET TRAILING SPACE NEEDING CLEARING
JRST RD01T3 ;ENTER LOOP
;LOOP READING FIXED/VARIABLE ASCII INPUT
RD01T2: PUSHJ P,RDBYT1 ;READ NEXT ASCII BYTE
PJRST RDEIE ;SOMETHING'S WRONG
IDPB T2,T4 ;STASH AWAY THIS CHARACTER
RD01T3: SOJGE T3,RD01T2 ;LOOP FOR REST OF FIELD
MOVE T3,-T1(P) ;AMOUNT OF SPACE STILL NEEDING CLEARING
SETZ T2, ;INPUT DONE, A TERMINATING NULL
IDPB T2,T4 ;TERMINATE THE STRING
SOJGE T3,.-1 ;CLEAR THE REST OF THE STRING
JRST .POPJ1## ;SUCCESSFUL RETURN
;LOOP READING EXTENSIBLE ASCII INPUT
RD01T5: PUSHJ P,RDBYT1 ;READ NEXT INPUT BYTE
PJRST RDEIE ;ERROR SOMEWHERE
IDPB T2,T4 ;STASH AWAY THIS CHARACTER
TRNE T2,200 ;EXTENDED BYTE?
SOJG T3,RD01T5 ;YES, READ MORE
TRNE T2,200 ;TRULY END OF INPUT?
PJRST RDEIF ;NO, TOO MUCH, ERROR IN FIELD
SETZ T2, ;YES, A TERMINATING NULL
IDPB T2,T4 ;TO TERMINATE THE STRING
SOJGE T3,.-1 ;CLEAR REST OF STRING
JRST .POPJ1## ;SUCCESSFUL RETURN
;RD02T - BINARY INPUT FIELD
;RD03T - COMPRESSED BINARY INPUT FIELD
RD02T: ;THEY'RE THE SAME, ALMOST
RD03T: LDB P3,[POINTR T1,DX$LNB] ;FIELD LENGTH (MAX IN DAP BYTES)
CAILE P3,^D9 ;WILL IT FIT THE ALGORITHM BELOW?
STOPCD <Binary DAP field larger than 9 bytes in RD03T>
SETZB T2,T3 ;INITIALIZE BINARY VALUE
TXNE T1,DX$XTN ;EXTENSIBLE BINARY FORMAT?
JRST RD03T5 ;YES
MOVEI P4,^D9 ;MAXIMUM POSSIBLE LENGTH
SUB P4,P3 ;P4:=BYTES NOT USED IN 72-BIT DOUBLE-WORD
TXNN T1,DX$VAR ;VARIABLE LENGTH BINARY FORMAT?
JRST RD03T3 ;NO, FIXED LENGTH
PUSHJ P,RDBYT1 ;READ FIELD LENGTH
PJRST RDEIE ;ERROR IN FIELD
MOVE P3,T2 ;SET ACTUAL FIELD LENGTH
MOVEI P4,^D9 ;MAX FIELD LENGTH (FOR TWO WORDS)
SUB P4,P3 ;BYTES NOT USED
SETZB T3,T4 ;INITIALIZE BINARY VALUE
JRST RD03T3 ;ENTER LOOP
;LOOP READING FIXED/VARIABLE BINARY INPUT BYTES
RD03T2: PUSHJ P,RDBYT1 ;READ NEXT BYTE
PJRST RDEIE ;ERROR IN FIELD
LSHC T3,-^D8 ;MAKE ROOM FOR NEXT HIGHER-ORDER BYTE
LSH T3,^D8 ;SLIP BACK AND
LSHC T2,-^D8 ;PICK UP THE BYTE
RD03T3: SOJGE P3,RD03T2 ;LOOP FOR REST OF FIELD
IMULI P4,^D8 ;COUNT OF BITS NOT USED IN DOUBLE-WORD VALUE
MOVNS P4 ;NEGATIVE BIT COUNT
LSHC T3,0(P4) ;RIGHT-JUSTIFY FIELD
TLNE T3,(1B0!1B1) ;MORE THAN 70 BITS?
STOPCD <Binary DAP value greater than 70 bits in RD03T>
LSHC T3,1 ;PUT 35-BITS PER WORD
LSH T4,-1 ;-10 FORMAT DOUBLE PRECISION INTEGER
LDB T1,[POINTR DAPXCT(P1),DX$LNB] ;SIZE OF FIELD IN 8-BIT BYTES
CAIG T1,4 ;MORE THAN ONE -10 WORDS' WORTH?
MOVEI T1,1 ;NO, ONE WORD IS SUFFICIENT
CAILE T1,4 ;LESS THAN TWO -10 WORDS' WORTH?
MOVEI T1,2 ;NO, TWO WORDS NEEDED
LDB T2,[POINTR DAPXCT(P1),DX$TYP] ;FIELD TYPE
CAIN T2,$DXTCN ;COMPRESSED 1 WORD VALUE?
MOVEI T1,1 ;YES, SIZE IS ONE WORD THEN
LDB T2,[POINTR DAPXCT(P1),DX$IOX] ;OFFSET INTO .IODAP AREA
ADDI T2,.IODAP(IO) ;RELOCATE INTO I/O CDB
CAIN T1,1 ;ONE-WORD VALUE?
MOVEM T4,(T2) ;YES
CAIN T1,2 ;TWO-WORD VALUE?
DMOVEM T3,(T2) ;YES
LDB T1,[POINTR DAPXCT(P1),DX$TYP] ;FIELD TYPE AGAIN
CAIN T1,$DXTCN ;COMPRESSED BINARY?
CAIN T3,0 ;YES, DID DAP INPUT FIT?
JRST .POPJ1## ;SUCCESSFUL RETURN
STOPCD <Compressed DAP binary field exceeded 36 bits in RD03T>
;LOOP READING EXTENSIBLE BINARY FIELD
RD03T5: STOPCD <Extensible DAP binary field encountered in RD03T>
;RD04T - FLAGS FIELD (ALSO MENU, SEE RD06T)
RD04T: LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH (DAP BYTES)
LDB T4,[POINTR T1,DX$IOX] ;FIELD STORAGE IN .IODAP
ADD T4,[POINT 7,.IODAP(IO)] ;MAKE INTO BYTE POINTER
TXNE T1,DX$XTN ;EXTENSIBLE FIELD?
JRST RD04T5 ;YES
STOPCD <Fixed/variable length DAP flags field encountered in RD04T>
;LOOP READING EXTENSIBLE FLAG BYTES
RD04T5: PUSHJ P,RDBYT1 ;READ NEXT FLAG BYTE
PJRST RDEIE ;ERROR IN FIELD
IDPB T2,T4 ;STORE FLAGS
TRNE T2,200 ;EXTENDED BYTE?
SOJG T3,RD04T5 ;YES, LOOP BACK AND FINISH THE FIELD
TRNE T2,200 ;REALLY THE END?
PJRST RDEIF ;ERROR IN FIELD - TOO BIG
TDZA T2,T2 ;NULL BYTE
IDPB T2,T4 ;CLEAR SOME FLAGS
SOJG T3,.-1 ;CLEAR REST OF FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
;RD05T - IMAGE BYTE FIELD
RD05T: LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH (BYTES)
LDB T4,[POINTR T1,DX$IOX] ;FIELD STORAGE IN .IODAP
ADD T4,[POINT 8,.IODAP(IO)] ;MAKE INTO BYTE POINTER
TXNE T1,DX$XTN ;EXTENSIBLE IMAGE FIELD?
JRST RD05T5 ;YES
TXNN T1,DX$VAR ;NO, VARIABLE LENGTH FIELD?
JRST RD05T3 ;NO, FIXED LENGTH
PUSHJ P,RDBYT1 ;YES, READ ACTUAL FIELD SIZE
PJRST RDEIE ;ERROR IN FIELD
CAMLE T2,T3 ;WITHIN SPECS?
PJRST RDEIE ;NO, TOO BIG, ERROR IN FIELD
MOVE T3,T2 ;SET ACTUAL FIELD SIZE
JRST RD05T3 ;AND ENTER LOOP
;LOOP READING IMAGE BYTES
RD05T2: PUSHJ P,RDBYT1 ;NEXT IMAGE BYTE
PJRST RDEIE ;ERROR IN FIELD
IDPB T2,T4 ;STORE THIS BYTE
RD05T3: SOJGE T3,RD05T2 ;LOOP FOR REST OF FIELD
TDZA T2,T2 ;TRAILING NULL
IDPB T2,T4 ;WIPE OUT TRAILING FIELD
SOJGE T3,.-1 ;CLEAR OUT REST OF FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
;LOOP READING EXTENSIBLE IMAGE BYTES
RD05T5: STOPCD <Extensible DAP image field encountered in RD05T>
;RD06T - MENU FIELD
RD06T: TXNE T1,DX$SKP ;IS THIS AN "INVISIBLE" MENU?
JRST .POPJ1## ;*** YES, JUST IGNORE IT HERE
LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH
LDB T4,[POINTR T1,DX$IOX] ;FIELD STORAGE IN .IODAP
ADD T4,[POINT 7,.IODAP(IO)] ;MAKE INTO BYTE POINTER
DMOVEM T3,.IODRM(IO) ;SAVE FOR PROCESSING THE MENU FIELD
TXNE T1,DX$XTN ;EXTENSIBLE FIELD?
JRST RD06T5 ;YES
STOPCD <Fixed/variable length DAP menu field encountered in RD06T>
;LOOP READING EXTENSIBLE MENU FIELD
RD06T5: PUSHJ P,RDBYT1 ;NEXT DAP BYTE
PJRST RDEIE ;ERROR IN FIELD
IDPB T2,T4 ;STORE AWAY MENU BYTE
TRNE T2,200 ;END OF EXTENSIBLE FIELD?
SOJG T3,RD06T5 ;NO, LOOP BACK AND FINISH IT OFF
TRNE T2,200 ;REALLY THE END?
PJRST RDEIF ;NO, ERROR IN FIELD
TDZA T2,T2 ;YES, A NULL
IDPB T2,T4 ;TO TERMINATE THE FIELD
SOJG T3,.-1 ;CLEAR REST OF FIELD
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;NOW LOOP PROCESSING REST OF MESSAGE AS DESCRIBED BY THE MENU
RD06M1: ILDB P2,.IODRM+1(IO) ;GET A MENU BYTE
TROA P2,200 ;FORCE 7-BITS-WORTH OF LOOP
;LOOP WITHIN 7-BIT MENU SUBFIELD
RD06M2: LSH P2,-1 ;ADVANCE TO NEXT MENU BIT
AOS P1,.IODRX(IO) ;CORRESPONDING EXECUTION TABLE INDEX
TRZN P2,1 ;THIS FIELD PRESENT?
JUMPN P2,RD06M5 ;NO, TRY CHECK FOR REST OF MENU'ED MESSAGE
JUMPE P2,RD06M7 ;YES, UNLESS FAKE BIT ("TROA" ABOVE)
;READ IN MENU-SPECIFIED FIELD
MOVE T1,DAPXCT(P1) ;PICK UP EXECUTION TABLE ENTRY
LDB T2,[POINTR T1,DX$COD] ;FIELD "NUMBER"
LDB T3,[POINTR T1,DX$TYP] ;FIELD "TYPE"
CAILE T3,$DXTMX ;WITHIN MAXIMUM LIMITS?
STOPCD <DX$TYP menued DAP field type too big in RD06M>
MOVEM T2,.IODRF(IO) ;SET CURRENT INPUT FIELD "NUMBER"
CAIE T3,$DXTMS ;IF START OF MESSAGE,
CAIN T3,$DXTMN ; OR MENU
JRST RDEIF ;THEN ERROR IN FIELD
PUSH P,P2 ;SAVE P2
PUSHJ P,@RDDAPX(T3) ;DISPATCH ON FIELD TYPE
JRST [POP P,P2 ;ERROR, ADJUST STACK
POPJ P,] ;AND PROPAGATE THE ERROR
POP P,P2 ;RESTORE P2
RD06M5: LDB T3,[POINTR DAPXCT+1(P1),DX$TYP] ;PEEK AT NEXT FIELD TYPE
CAIE T3,$DXTMS ;END OF CURRENT MESSAGE?
JRST RD06M2 ;NO, STILL MORE FIELDS POSSIBLE
MOVE T1,P2 ;CURRENT MENU BYTE
JFFO T1,.+1 ;FIND THE FIRST BIT
LSH T1,1(T2) ;GET RID OF JUNK ("TROA") BIT
JUMPN T1,RDEIF ;IF STILL BITS (ALLEGING FIELDS) THEN ERROR
ILDB T1,.IODRM+1(IO) ;NEXT MENU BYTE
SOSLE .IODRM+0(IO) ;COUNT DOWN MENU BYTES LEFT
JRST .-3 ;CHECK THEM ALL OUT
JRST .POPJ1## ;SUCCESSFUL RETURN
RD06M7: SOS .IODRX(IO) ;THE "TROA" BIT DOESN'T COUNT AGAINST INDEX
SOSLE .IODRM+0(IO) ;COUNT DOWN MENU BYTES
JRST RD06M1 ;AND KEEP PROCESSING THEM
PJRST RDEIF ;ERROR IN FIELD
;RD0T7 - TIME FIELD
RD07T: LDB P3,[POINTR T1,DX$LNB] ;DAP FIELD LENGTH (BYTES)
MOVE P4,[POINT 7,.IODTM(IO)];TEMP HOLDING AREA POINTER
;FIRST STRIP OFF ANY LEADING SPACES (E.G., " 1-MAY-...") SO IT/THEY DON'T
;GET CONVERTED INTO COLONS . . .
RD07T1: PUSHJ P,RDBYT1 ;GET A DATE/TIME CHARACTER
JRST RDEIE ;ERROR IN FIELD
CAIE T2," " ;IS THIS A LEADING SPACE?
JRST RD07T4 ;NO, VALID CHARACTER
SOJG P3,RD07T1 ;YES, LOOP EATING SPACES
SETZ T2, ;NO?????????????????
JRST RD07T7 ;SO RETURN A ZERO DATE/TIME
;READ IN ASCII DATE/TIME STRING INTO SCRATCH HOLDING AREA
RD07T3: PUSHJ P,RDBYT1 ;NEXT ASCII DATE/TIME CHARACTER
JRST RDEIE ;ERROR IN FIELD
CAIN T2," " ;IS THIS DAP'S SPACE 'TWEEN DATE AND TIME?
MOVEI T2,":" ;YES, SCAN WANTS A COLON THERE
RD07T4: IDPB T2,P4 ;STASH THIS CHARACTER
SOJG P3,RD07T3 ;LOOP FOR REST OF FIELD
IDPB P3,P4 ;ASCIZIZE THE STRING
;TRANSLATE ASCII STRING INTO 36-BIT INTERNAL DATE/TIME FORMAT
PUSHJ P,RD07X0 ;GET INTERNAL FORMAT DATE/TIME
JRST RDEIE ;ERROR IN FIELD
RD07T7: LDB T4,[POINTR DAPXCT(P1),DX$IOX] ;GET CDB OFFSET FOR THIS FIELD
ADDI T4,.IODAP(IO) ;RELOCATE INTO MEMORY
MOVEM T2,0(T4) ;SET DATE/TIME FIELD IN DAP BLOCK
JRST .POPJ1## ;SUCCESSFUL RETURN
;HELPER TO TRANSLATE ASCIZ STRING INTO BINARY ("INTERNAL") DATE/TIME
RD07X0: PUSHJ P,.SAVE4## ;SCAN'S CH AND NM ARE OUR P3 AND P4 !!!
SETZM .IOXTO(IO) ;USE IOXTO AS COUNTER/FLAG HERE
XMOVEI T1,RD07XI ;OUR VERY OWN INPUT TYPER
PUSHJ P,.XTYPI## ;INTERCEPT "COMMAND" INPUT
XMOVEI T1,RD07XO ;OUR VERY OWN OUTPUT TYPER
PUSHJ P,.XTYPO## ;INTERCEPT "COMMAND" OUTPUT
MOVE T1,[POINT 7,[0]];A DUMMY STRING
MOVEM T1,.IOXTI(IO) ;SET IN CASE .CLRTI NEEDS SOMETHING
PUSHJ P,.CLRTI## ;SETUP LOWLEVEL COMMAND INPUT ROUTINES
MOVE T1,[POINT 7,.IODTM(IO)] ;BYTE POINTER TO ASCIZ STRING
MOVEM T1,.IOXTI(IO) ;SET FOR RD07XI
;NOW PARSE THE ASCIZ DATE/TIME STRING
RD07X3: PUSHJ P,.DYTIM## ;LET SCAN DO ITS THING
JRST RD07X7 ;ERROR - DIE
MOVE T2,NM ;POSITION DATE/TIME FOR CALLER
SKIPN .IOXTO(IO) ;IT BETTER NOT HAVE COMPLAINED
JRST .POPJ1## ;RETURN WITH DATE/TIME IN T2
RD07X7: STOPCD <Error in parsing received DATE/TIME message in RD07X>
;THE "COMMAND" INPUT ROUTINE
RD07XI: ILDB CH,.IOXTI(IO) ;GET NEXT CHARACTER FROM NAME STRING
JUMPN CH,.POPJ## ;RETURN IT
MOVEI CH,.CHLFD ;END OF STRING, RETURN EOL TO SCAN
POPJ P, ; . . .
;THE "COMMAND" OUTPUT ROUTINE
RD07XO: OUTCHR T1 ;OH WELL
AOS .IOXTO(IO) ;COUNT OCCURENCES
POPJ P, ;RETURN TO SCAN
;ERRORS READING DAP PROTOCOL
;UNKNOWN DAP MESSAGE TYPE
RDEUM: STOPCD <Unknown DAP message type>
;UNKNOWN DAP MESSAGE FIELD
RDEUF: STOPCD <Unknown DAP message field>
;ERROR (UNSPECIFIED) IN FIELD
RDEIE: STOPCD <Error in DAP field>
RDEIF: STOPCD <Error in DAP field>
;RDEAT -- EAT [REST OF] DAP MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDEAT
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died whilst reading whatever is left of the
;DAP input message.
;
;On normal return the DAP input message has been completely read, and
;is now ready for the next DAP input message (i.e., RDBYT will return
;with no data available, RDMSG must be called to start the next input
;message processing). If called to eat a data message the file data
;CRC will be updated to reflect the data bytes "eaten" (note that the
;caller is responsible to ensure that the RCN field of the data message
;has already been read).
;
;Uses ac T2.
ENTRY .RDEAT
INTERN RDEAT0, RDEAT1
.RDEAT: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RDEAT0:
RDEAT1: MOVE T2,.IODIM(IO) ;GET CURRENT DAP MESSAGE TYPE
CAIN T2,$DHDAT ;EATING INPUT FILE DATA?
JRST RDEAT4 ;YES, MUST KEEP CRC UPDATED
;HERE TO EAT NON-DATA DAP MESSAGES
RDEAT2: PUSHJ P,RDBYT1 ;READ ANOTHER DAP BYTE
CAIA ;NONE AVAILABLE
JRST RDEAT2 ;TRY FOR MORE
JUMPE M0,.POPJ1## ;IF NO DATA THEN SUCCESSFUL RETURN
POPJ P, ;OTHERWISE THE NETWORK DIED
;HERE TO EAT DAP DATA MESSAGES
RDEAT4: PUSHJ P,RDBYC1 ;READ ANOTHER DAP BYTE, UPDATING THE CRC
CAIA ;NONE AVAILABLE
JRST RDEAT4 ;TRY FOR MORE
JUMPE M0,.POPJ1## ;IF NO DATA THEN SUCCESSFUL RETURN
POPJ P, ;OTHERWISE THE NETWORK DIED
;RDBYC -- READ ONE DAP FILE DATA BYTE, CALCULATING CRC
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDBYC
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return either the network died or the current input DAP
;data message is exhausted (M0 has 0).
;
;On normal return the next available file data byte is in T2,
;and the running file data CRC has been updated.
;
;This routine is functionally identical to RDBYT, except that the
;file data CRC is updated.
;
;Uses T2.
ENTRY .RDBYC
INTERN RDBYC0, RDBYC1
INTERN RDCRC1
.RDBYC: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
RDBYC0:
RDBYC1: PUSHJ P,RDBYT1 ;GET NEXT DAP BYTE
POPJ P, ;PROPAGATE EXCEPTION RETURN
RDCRC1: PUSH P,T2 ;SAVE RETURN DATA BYTE
ANDI T2,377 ;REDUCE TO JUST INTERESTING DATA
MOVE M0,.IODIK(IO) ;GET LAST FILE DATA CRC
XORB M0,T2 ;INCLUDE BYTE IN CRC
ANDI T2,377 ;COMPUTE OFFSET INTO CRC TABLE
LSH M0,-^D08 ;XOR REMAINING CRC FROM TABLE
XOR M0,DAPCRC(T2) ;COMPUTE NEW CRC
MOVEM M0,.IODIK(IO) ;AND STASH IT AWAY
POP P,T2 ;RESTORE DAP FILE DATA BYTE
JRST .POPJ1## ;AND SUCCESSFUL RETURN
;RDBYT -- READ ONE DAP BYTE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDBYT
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return either the network died or the current input DAP
;message is exhausted (M0 has 0).
;
;On normal return the next available DAP byte is in T2.
;
;This routine handles continuation messages (DF$MOR) internally - the
;caller is not required to be aware of them (and in fact is not even told
;if a continuation message is encountered).
;
;Uses ac T2.
ENTRY .RDBYT
INTERN RDBYT0, RDBYT1
.RDBYT: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RDBYT0:
RDBYT1: SKIPE T2,.IODIR(IO) ;GOT A BYTE TO BE RE-READ?
JFFO P,[SETZM .IODIR(IO) ;CLEAR OUT STALE BYTE
TLNE T2,(1B1) ;SAVED ERROR CODE (400000,,ERROR)?
TLZA T2,-1 ;NO, CLEAR OUT FLAG, LEAVING DATA BYTE
TROA M0,(T2) ;YES, POSITION ERROR CODE
AOS 0(P) ;SUCCESS RETURN
POPJ P,] ;FAILURE RETURN
SOSGE .IODIC(IO) ;ANY DAP BYTES LEFT?
JRST RDBYT4 ;PROBABLY NOT, BUT MIGHT BE CONTINUATION
PUSHJ P,RNBYT1 ;YES, READ NEXT BYTE FROM NETWORK
JRST RDBYT2 ;HMMM. PROBABLY BAD NEWS
AOS (P) ;SKIP
POPJ P, ; RETURN
;NETWORK REFUSED TO GIVE US A BYTE
RDBYT2: PJUMPN M0,.POPJ## ;IF NETWORK DIED, LET HIGHER UPS HANDLE IT
HLRZ T2,.IODIC(IO) ;GET DAP BYTE COUNT
CAIE T2,223344 ;WAS IT A DUMMY COUNT?
STOPCD <Network EOM before DAP EOM - DAP data lost>
SETZM .IODIC(IO) ;FLAG OK END OF DAP MESSAGE
;HERE WHEN THE CURRENT DAP MESSAGE IS EXHAUSTED. CHECK FOR A CONTINUATION
;MESSAGE (I.E., A DAP MESSAGE WHICH WAS BROKEN UP INTO SEGMENTS AND ACTUALLY
;TRANSMITTED AS SEVERAL DISTINCT (PRESUMABLY PHYSICAL NETWORK) MESSAGES.)
RDBYT4: SKIPE .IODIX(IO) ;IS THIS A RETRY?
JRST RDBYT6 ;YES
MOVE T2,.IODIF(IO) ;GET DAP INPUT HEADER FLAGS
TFNN T2,MOR ;ARE THERE MORE SEGMENTS COMING?
JRST RDBYT8 ;NO, RETURN EMPTY
SKIPE .IODIB(IO) ;IF CONTINUED, BETTER NOT BE RANDOM BITS LEFT
PJRST RDEID4 ;THERE WERE, ERROR IN FIELD
SKIPG T2,.IODIM(IO) ;GET CURRENT INPUT MESSAGE TYPE
STOPCD <XDBYT but no DAP message in progress>
MOVEM T2,.IODIX(IO) ;SAVE AND SET STATE FLAG
RDBYT6: PUSHJ P,RDBYU0 ;READ IN AND STARTUP A NEW MESSAGE
POPJ P, ;NETWORK DIED
MOVE M0,.IODIX(IO) ;GET PREVIOUS MESSAGE TYPE
SETZM .IODIX(IO) ;CLEAR CONTINUATION STATE
CAME T2,M0 ;IS CONTINUED MESSAGE SAME AS BEFORE?
PJRST RDEOS ;NO, DAP MESSAGE OUT OF SEQUENCE
JRST RDBYT1 ;YES, GO BACK AND FINISH READING IT
;HERE WHEN DAP MESSAGE IS EMPTY
RDBYT8: HRROS .IODIM(IO) ;NEGATIVE LH TO INDICATE OUT OF DAP MESSAGE
; (LEAVE CODE IN RH FOR ERROR ROUTINES)
SETZ M0, ;RETURN NULL
POPJ P, ;EMPTY RETURN
;HELPER TO READ CONTINUATION MESSAGE
RDBYU0: PUSHJ P,TSAV14## ;NEED TO PROTECT THE T'S
PUSHJ P,RDMSG0 ;START UP A NEW DAP MESSAGE
POPJ P, ;NET DIED?
MOVEM T2,-T2(P) ;PASS BACK THE NEW MESSAGE TYPE
JRST .POPJ1## ;AND RETURN WITH NEW MESSAGE READY TO CONTINUE
;RDBYR -- RE-READ DAP MESSAGE/DATA BYTE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDBYR
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;RDBYR assumes that a call to RDBYT has been successfully executed,
;leaving a valid 8-bit DAP byte in T2. This byte will be set, and
;returned on the next call to RDBYT.
;
;The error return is not exercised.
;
;On normal return the next call to RDBYT will re-read the just-read
;(i.e., in T2) DAP 8-bit byte.
;
;Uses no acs.
ENTRY .RDBYR
INTERN RDBYR0, RDBYR1
.RDBYR: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
RDBYR0:
RDBYR1: HRROM T2,.IODIR(IO) ;SAVE CURRENT DAP BYTE
JRST .POPJ1## ;SUCCESSFUL RETURN
;RDCLR -- CLEAR OUT DAP MESSAGE BASE
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<MSG>
; PUSHJ P,RDCLR
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB; and <MSG> is
;the DAP message type ($DHxxx) whose base area within the .IODAP
;block is to be cleared.
;
;RDCLR zeroes all parameters, fields, values, etc. associated with
;the specified DAP message type contained within the .IODAP block
;within the I/O CDB (for example the attributes fields of the main
;attributes DAP message).
;
;On error return the specified <MSG> is illegal (error code in M0).
;
;On normal return the .IODAP area associated with the message type
;has been zeroed.
;
;Uses T1, T2, T3, T4.
ENTRY .RDCLR
INTERN RDCLR0, RDCLR1
.RDCLR: PUSHJ P,.SACIO## ;SET UP I/O CONTEXT
RDCLR0: ;WE DON'T USE THE P'S
RDCLR1: PUSHJ P,TSAV14## ;PRESERVE THE TEAS (ESPECIALLY T2!)
MOVEI T4,DAPIDX ;THE MESSAGE INDEX INTO THE EXECUTION TABLE
PUSHJ P,.CFIND## ;LOCATE THE MESSAGE WITHIN THE TEMPLATE
STOPCD <Unknown DAP message in RDCLR>
LDB T1,[POINTR DAPXCT(T1),DX$IOX] ;GET FIRST .IODAP ENTRY
HLRZ T2,1(T4) ;GET POINTER TO NEXT MESSAGE TYPE FIRST ENTRY
SKIPN T2 ;AT END OF TABLE?
SKIPA T2,[$DLDAP] ;YES, POINT TO END OF .IODAP AREA
LDB T2,[POINTR DAPXCT(T2),DX$IOX] ;NO, FETCH NEXT FIRST ENTRY
ADDI T1,.IODAP(IO) ;RELOCATE TO REAL MEMORY
SETZM (T1) ;CLEAR FIRST WORD
HRL T1,T1 ;CONCOCT A
ADDI T1,1 ; BLT POINTER
ADDI T2,.IODAP(IO) ;RELOCATE LAST WORD TO REAL MEMORY
BLT T1,-1(T2) ;CLEAR OUT DAP MESSAGE BASE
JRST .POPJ1## ;SUCCESSFUL RETURN
;RDMSG -- READ IN AND STARTUP ONE DAP MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDMSG
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died
;
;On normal return the DAP message code is in T2. Subsequent calls to
;RDBYT will read the rest of the DAP message.
;
;Uses ac T2.
ENTRY .RDMSG
INTERN RDMSG0, RDMSG1
.RDMSG: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RDMSG0: PUSHJ P,.SAVE4## ;WE NEED A FEW ACS HERE
RDMSG1: SKIPLE .IODIC(IO) ;ANY DAP BYTES STILL OUTSTANDING?
STOPCD <RDMSG called before end of current DAP message>
SKIPE .IODRS(IO) ;GOT A SAVED (RDREA) MESSAGE?
JRST [MOVSI T3,.IODRS(IO) ;YES,
HRRI T3,.IODIM(IO) ;CONCOCT A BLT POINTER
BLT T3,.IODIM+.IODRL-1(IO) ;TO BRING BACK INPUT MESSAGE
SETZM .IODRS(IO) ;CLEAR SAVED INPUT STATE
JRST RDMSZ] ;AND RETURN "NEW" INPUT MESSAGE
SETZM .IODIF(IO) ;RESET HEADER FLAGS
SETZM .IODIS(IO) ;RESET STREAM ID FIELD
SETZM .IODIB(IO) ;RESET TRAILING UNUSED BITS
;READ IN MESSAGE TYPE
PUSHJ P,RNBYT1 ;ANY NETWORK BYTES LEFT?
CAIA ;APPARENTLY NOT
JRST RDMSG2 ;YES, T2 HAS MESSAGE TYPE
JUMPN M0,.POPJ## ;ERROR RETURN IF NETWORK DIED
PUSHJ P,RNMSG0 ;READ IN A NEW NETWORK MESSAGE
POPJ P, ;NETWORK DIED
RDMSG2: HRRZM T2,.IODIM(IO) ;SET NEW MESSAGE TYPE
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;READ IN DAP MESSAGE HEADER FLAGS
MOVEI P3,$DBMHF ;LENGTH OF MESSAGE HEADER FLAGS
MOVE P4,[POINT 7,.IODIF(IO)] ;AND WHERE TO STORE THEM
SETZ P1, ;NO BYTE SEEN YET
RDMSG3: PUSHJ P,RNBYT0 ;READ A NETWORK BYTE
JRST [JUMPN M0,.POPJ## ;IF ERROR, PASS THE WORD
MOVE T2,.IODIF(IO) ;GET HEADER FLAGS SO FAR
TFZ T2,MOR ;CLEAR OK FLAG BIT
TRNN P1,200 ;SHOULD THERE BE ANOTHER BYTE?
JUMPE T2,RDMSZ ;MESSAGE OK IF NO FIELDS EXPECTED
PJRST RDEID0] ;ELSE ERROR IN FLAGS FIELD
IDPB T2,P4 ;STASH THIS FLAG BYTE
MOVE P1,T2 ;SAVE EXTENSIBILITY FLAG
TRNE T2,200 ;END OF FLAGS?
SOJG P3,RDMSG3 ;NO, READ REST OF FIELD
TRNE T2,200 ;REALLY END OF FLAGS?
PJRST RDEID0 ;NO, FIELD TOO BIG, ERROR
MOVE P1,.IODIF(IO) ;PICK UP HEADER FLAGS
;READ STREAM ID FIELD, IF PRESENT
TFZN P1,SID ;STREAM ID FIELD PRESENT?
JRST RDMSG4 ;NO
PUSHJ P,RNBYT0 ;YES, READ IT IN
JRST [JUMPE M0,RDEID1 ;ERROR IN SID FIELD
POPJ P,] ;ERROR IN NETWORK
MOVEM T2,.IODIS(IO) ;SET STREAM ID FIELD
JUMPN T2,RDEID1 ;WE DON'T SUPPORT MULTIPLE SID'S
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;READ IN LENGTH FIELD
RDMSG4: TFNN P1,HLN ;HEADER LENGTH FIELD PRESENT?
JRST RDMSG5 ;NO
PUSHJ P,RNBYT0 ;YES, READ IT
JRST [JUMPE M0,RDEID2 ;ERROR IN LENGTH FIELD
POPJ P,] ;NETWORK DIED
MOVEM T2,.IODIC(IO) ;SET LENGTH OF DAP DATA
;READ IN SECOND HALF OF LENGTH FIELD
RDMSG5: TFNN P1,HL2 ;HIGH-ORDER HEADER LENGTH PRESENT?
JRST RDMSG6 ;NO
PUSHJ P,RNBYT0 ;YES, READ IT
JRST [JUMPE M0,RDEID3 ;ERROR IN EXTENDED LENGTH FIELD
POPJ P,] ;NETWORK DIED
DPB T2,[POINT 8,.IODIC(IO),27] ;SET HIGH-ORDER BYTE COUNT
RDMSG6: HRLOI T2,223344 ;DUMMY DAP BYTE COUNT
; (THIS WILL LEAVE A "223344" IN THE LH, OUR
; "INDICATION" THAT THE DAP COUNT IS NOT
; REALLY VALID, BUT KEPT POSITIVE JUST TO
; KEEP EVERYONE ELSE HAPPY - SEE RDBYT)
TFZN P1,<HLN,HL2> ;DAP MESSAGE HEADER CONTAIN ITS LENGTH?
MOVEM T2,.IODIC(IO) ;NO, USE DEFAULT
;READ IN TRAILING UNUSED BIT COUNT
TFZN P1,BCT ;ANY UNUSED BITS?
JRST RDMSG7 ;NO
PUSHJ P,RNBYT0 ;YES, READ THE COUNT
JRST [JUMPE M0,RDEID4 ;ERROR IN UNUSED BIT COUNT
POPJ P,] ;NETWORK DIED
MOVEM T2,.IODIB(IO) ;SET TRAILING UNUSED BIT COUNT
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;CHECK FOR SYSPEC (SYSTEM-SPECIFIC) FIELD
RDMSG7: TFZN P1,SHX ;SYSTEM-SPECIFIC HEADER FIELD?
JRST RDMSG8 ;NO
PUSHJ P,RNBYT0 ;YES, GET LENGTH OF FOLLOWING IMAGE FIELD
JRST [JUMPE M0,RDEID5 ;ERROR IN SYSPEC FIELD
POPJ P,] ;NETWORK DIED
SKIPG T4,T2 ;COUNT OF IMAGE BYTES FOLLOWING
JRST RDMSG8 ;NONE, ALL DONE HERE
PUSHJ P,RNBYT0 ;GET NEXT SYSPEC IMAGE BYTE
JRST [JUMPE M0,RDEID5 ;ERROR IS SYSPEC FIELD
POPJ P,] ;NETWORK DIED
SOJG T4,.-2 ;EAT THE WHOLE SILLY THING
;NOW SEE IF THERE IS ANYTHING LEFT OVER
RDMSG8: TFZ P1,MOR ;CLEAR OK BIT
JUMPN P1,RDEID0 ;ANYTHING LEFT OVER IS AN ERROR
;NOW VERIFY THAT ALL THE FIELDS FIT TOGETHER
RDMSZ: MOVE T3,.IODIC(IO) ;GET INPUT BYTE COUNT
MOVEM T3,.IODRC(IO) ;AND SET IN CASE .RDREA IS CALLED
HRRZ T2,.IODIM(IO) ;RETURN NEW CURRENT INPUT MESSAGE TYPE
JRST .POPJ1## ;SUCCESSFUL RETURN
;RDMSR -- RE-READ THE CURRENT DAP MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RDMSR
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;RDMSR assumes that a DAP message has just been started (i.e., RDMSG
;has been called, T2 has the current DAP message code, and no DAP
;data bytes have been read, which is to say neither RDDAP nor RDBYT
;have been called). RDMSR will "undo" the current message such that
;the next call to RDMSG will re-read it.
;
;On error return either a message was not in progress, or had been
;already partially read.
;
;On normal return the current DAP message will be readable via the
;next call to RDMSG.
;
;Uses T1, T2, T3, T4.
ENTRY .RDMSR
INTERN RDMSR0, RDMSR1
.RDMSR: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
RDMSR0:
RDMSR1: MOVE T3,.IODRC(IO) ;GET SAVED INITIAL DAP BYTE COUNT
CAME T3,.IODIC(IO) ;WON'T HAVE CHANGED UNLESS RDBYT CALLED
STOPCD <RDMSR not called immediately after RDMSG>
MOVSI T3,.IODIM(IO) ;START OF DAP INPUT MESSAGE STUFF
HRRI T3,.IODRS(IO) ;WHERE TO SAVE IT
BLT T3,.IODRS+.IODRL-1(IO) ;SAVE INPUT MESSAGE CONTEXT
SETZM .IODIM(IO) ;CLEAR START OF INPUT MESSAGE CONTEXT
MOVSI T3,.IODIM(IO) ;CONCOCT
HRRI T3,.IODIM+1(IO) ; A BLT POINTER TO
BLT T3,.IODIM+.IODRL-1(IO) ;CLEAR CURRENT INPUT MESSAGE CONTEXT
JRST .POPJ1## ;READY TO CALL .RDMSG AGAIN
;ERRORS READING DAP FIELDS
;ERROR IN DAP MESSAGE HEADER FLAGS
RDEID0: STOPCD <Error in received DAP message header flags>
;ERROR IN DAP MESSAGE HEADER STREAM ID FIELD
RDEID1: STOPCD <Error in received DAP message header stream ID field>
;ERROR IN DAP MESSAGE HEADER LENGTH FIELD
RDEID2: STOPCD <Error in received DAP message header length field>
;ERROR IN DAP MESSAGE HEADER LEN256 (EXTENDED LENGTH) FIELD
RDEID3: STOPCD <Error in received DAP message header length-256 field>
;ERROR IN DAP MESSAGE HEADER BITCNT FIELD
RDEID4: STOPCD <Error in received DAP message header trailing bit count field>
;ERROR ID DAP MESSAGE HEADER SYSPEC FIELD
RDEID5: STOPCD <Error in received DAP message header SYSPEC field>
;DAP MESSAGE OUT OF SEQUENCE
.RDEOS::
RDEOS: STOPCD <DAP message received out of sequence>
;XDACK -- SEND ACKNOWLEDGE MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,XDACK
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network aborted.
;
;On successful return an ACKNOWLEDGE message has been built and is
;ready to be shipped to the remote.
;
; THE CALLER MUST CALL XDFLS TO FORCE TRANSMISSION OF THE ACK
;
;Historically, before DAP %6.0, any ACK implied a line turnaround.
;With version 6 the DELETE/EXECUTE/RENAME functions can block multiple
;NAME/ATTRIBUTES/ACK sequences together, so XDACK doesn't flush the
;output automatically.
;
;Uses T1 - T4.
ENTRY .XDACK
INTERN XDACK0, XDACK1
.XDACK: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDACK0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDACK1: MOVEI T2,$DHACK ;ACKNOWLEDGE MESSAGE CODE
PUSHJ P,XDMSG1 ;START UP A NEW DAP MESSAGE
JRST XDACK9 ;CAN'T, GO CHECK IT OUT
PUSHJ P,XDEOM1 ;CAP OFF THE DAP ACKNOWLEDGE MESSAGE
POPJ P, ;OOPS
JRST .POPJ1## ;SUCCESSFUL RETURN
XDACK9: CAIE M0,$ECTRA ;SHOULD WE TRY AGAIN?
POPJ P, ;NO, FATAL ERROR
JRST XDACK1 ;YES
;XDACL -- SEND SHORT-FORM ACCESS COMPLETE (CLOSE) MESSAGE
;XDAKL -- SEND SHORT-FORM ACCESS COMPLETE (KILL) MESSAGE
;XDARS -- SEND SHORT-FORM ACCESS COMPLETE (RESPONSE) MESSAGE
;XDASK -- SEND SHORT-FORM ACCESS COMPLETE (SKIP) MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,XDACL/AKL/ARS/ASK
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network aborted.
;
;On successful return an ACCOMP(xxx) message has been shipped to the
;remote file service. This access complete message will have only the
;A2F field set - neither the access options nor the file data checksum
;fields will be sent.
;
;Uses T1 - T4.
;ACCOMP(CLOSE)
ENTRY .XDACL
INTERN XDACL0, XDACL1
.XDACL: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDACL0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDACL1: MOVEI T2,$DVACL ;"CLOSE" FUNCTION (NORMAL COMPLETION)
PJRST XDA2F1 ;CAP OFF SHORT-FORM ACCOMP(CLOSE)
;ACCOMP(KILL)
ENTRY .XDAKL
INTERN XDAKL0, XDAKL1
.XDAKL: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDAKL0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDAKL1: MOVEI T2,$DVAKL ;"KILL/RESET" FUNCTION
PJRST XDA2F1 ;CAP OFF SHORT-FORM ACCOMP(KILL)
;ACCOMP(RESPONSE)
ENTRY .XDARS
INTERN XDARS0, XDARS1
.XDARS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDARS0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDARS1: MOVEI T2,$DVARS ;"RESPONSE" FUNCTION
PJRST XDA2F1 ;SHIP THE ACCOMP(RESPONSE)
;ACCOMP(SKIP)
ENTRY .XDASK
INTERN XDASK0, XDASK1
.XDASK: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDASK0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDASK1: MOVEI T2,$DVASK ;"SKIP" FUNCTION
PJRST XDA2F1 ;CAP OFF SHORT-FORM ACCOMP(SKIP)
;MAIN BODY OF SHORT-FORM ACCOMP(XXX)
XDA2F1: MOVD1M T2,A2F ;SET ACCOMP FUNCTION CODE
MOVDII T2,M07,A2F ;FLAG ONLY THE FUNCTION FIELD
MOVDM T2,M07 ;IN THE ACCOMP "HIDDEN" MENU
MOVEI T2,$DHACM ;ACCESS COMPLETE MESSAGE CODE
PUSHJ P,XDDAP1 ;PACKAGE THE ACCOMP MESSAGE
POPJ P, ;ERROR
PJRST XDFLS1 ;AND FORCE IT OUT INTO THE COLD CRUEL WORLD
;XDCAB -- SEND CONTINUE (ABORT) MESSAGE
;XDCRS -- SEND CONTINUE (RESUME) MESSAGE
;XDCTA -- SEND CONTINUE (TRY AGAIN) MESSAGE
;XDCSK -- SEND CONTINUE (SKIP AND CONTINUE) MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,XDCTA/CRS/CTA/CSK
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network aborted.
;
;On successful return a CONTINUE(xxx) message has been shipped to the
;remote file service.
;
;Uses T1 - T4.
;CONTINUE(ABORT)
ENTRY .XDCAB
INTERN XDCAB0, XDCAB1
.XDCAB: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDCAB0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDCAB1: MOVEI T2,$DVCAB ;"ABORT" FUNCTION
PJRST XDC2F1 ;SKIP A CONTINUE(ABORT) MESSAGE
;CONTINUE(RESUME)
ENTRY .XDCRS
INTERN XDCRS0, XDCRS1
.XDCRS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDCRS0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDCRS1: MOVEI T2,$DVCRS ;"RESUME" FUNCTION
PJRST XDC2F1 ;SHIP OFF THE CONTINUE(RESUME) MESSAGE
;CONTINUE(TRY AGAIN)
ENTRY .XDCTA
INTERN XDCTA0, XDCTA1
.XDCTA: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDCTA0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDCTA1: MOVEI T2,$DVCTA ;"TRY AGAIN" FUNCTION
PJRST XDC2F1 ;PACKAGE AND SHIP A CONTINUE(TRY AGAIN)
;CONTINUE(SKIP)
ENTRY .XDCSK
INTERN XDCSK0, XDCSK1
.XDCSK: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDCSK0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDCSK1: MOVEI T2,$DVCSK ;"SKIP AND CONTINUE" FUNCTION
PJRST XDC2F1 ;SHIP A CONTINUE(SKIP) MESSAGE
;COMMON CONTINUE(XXX)
XDC2F1: MOVD1M T2,C2F ;SAVE THE "CONTINUE" FUNCTION
MOVDII T2,M05,C2F ;MENU FIELD: FUNCTION ONLY
MOVDM T2,M05 ;SET CONTINUE "HIDDEN" MENU
MOVEI T2,$DHCNT ;DAP CONTINUE MESSAGE CODE
PUSHJ P,XDDAP1 ;PACKAGE THE CONTINUE MESSAGE
POPJ P, ;SOMETHING BROKE
PJRST XDFLS1 ;AND FORCE IT OUT NOW
;XDEOF -- SEND "END OF FILE" STATUS MESSAGE
;CALL IS:
;
; PUSHJ P,XDEOF
; error return
; normal return
;
;On error return the network aborted
;
;On normal return a DAP STATUS "EOF" has been packaged and transmitted to
;the remote. This status message contains only the status code, no other
;fields are transmitted.
;
;Uses T1 - T4.
ENTRY .XDEOF
INTERN XDEOF0, XDEOF1
.XDEOF: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
XDEOF0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDEOF1: MOVEI T2,50000+$DSEOF ;DAP "EOF" STATUS CODE
MOVD1M T2,STC ;SET STATUS CODE
MOVDII T2,M09,STC ;FLAG ONLY THE STATUS CODE IN THE MENU
MOVDM T2,M09 ;AND SET THE "HIDDEN" MENU FIELD
MOVEI T2,$DHSTS ;DAP STATUS MESSAGE TYPE
PJRST XDDAP1 ;OFF TO THE GENERAL DAP MESSAGE SENDER
;XDDAT -- START UP A DATA MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2/T3,<RECN>
; PUSHJ P,XDDAT
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <RECN> is the
;64-bit double-precision integer record number to use in the DATA message.
;
;On error return the network died.
;
;On normal return a data message (code = $DHDAT) has been started
;and may be filled via calls to XDBYT.
;
;Uses T1 - T4
ENTRY .XDDAT
INTERN XDDAT0, XDDAT1
.XDDAT: PUSHJ P,.SACIO## ;SET UP I/O CDB INDEX
XDDAT0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDDAT1: MOVDM T2,RCN ;SET OUTPUT RECORD NUMBER TEMPLATE
MOVEI T2,$DHDAT ;DATA MESSAGE CODE
PUSHJ P,XDDAP2 ;START UP A DATA MESSAGE
POPJ P, ;ERROR
JRST .POPJ1## ;READY FOR DATA BYTES
;XDDAP -- BUILD AND SEND A GENERIC DAP MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<code>
; PUSHJ P,XDDAP
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; <code> is the DAP message
;code for the message to be sent. Data messages (<code> = $DHDAT)
;are illegal.
;
;On error return either the network died (M0 has the error code) or
;an input message has been received and needs to be processed (in which
;case no data has been sent - the XDDAP call must be re-executed in
;order to send the desired DAP message).
;
;On normal return the DAP message has been built and is in the network
;output buffer (a call to XDFLS must be executed if the message must
;be guaranteed transmitted - otherwise the message may be kept in the
;network buffer in order to "piggyback" multiple DAP messages into one
;physical network transmission message).
;
;Uses T1, T2, T3, T4
ENTRY .XDDAP
INTERN XDDAP0, XDDAP1
.XDDAP: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDDAP0: PUSHJ P,.SAVE4## ;SAVE THE P'S
XDDAP1: PUSHJ P,TSAV12## ;SAVE T1 AND T2
CAIN T2,$DHDAT ;DATA MESSAGE?
STOPCD <XDDAP called for DATA message>
XDDAP2: MOVEI T4,DAPIDX ;INDEX TABLE
PUSHJ P,.CFIND## ;FIND STARTING INDEX INTO EXECUTION TABLE
STOPCD <XDDAP called with unknown DAP message>
HRRZM T1,.IODXX(IO) ;SET XDDAP EXECUTION TABLE INDEX
PUSHJ P,XDMSG1 ;START A NEW DAP MESSAGE
JRST XDDAP9 ;CAN'T, CHECK IT OUT
;LOOP BUILDING FIELDS IN THE DAP OUTPUT MESSAGE
XDDAP4: AOS P1,.IODXX(IO) ;NEXT MESSAGE FIELD
MOVE T1,DAPXCT(P1) ;FETCH COPY OF EXECUTION TABLE ENTRY
LDB T3,[POINTR T1,DX$TYP] ;FIELD "TYPE"
CAILE T3,$DXTMX ;WITHIN OUR LIMITS?
STOPCD <DX$TYP field type too big in XDDAP>
JUMPE T3,XDDAP7 ;EXIT IF END OF MESSAGE TEMPLATE
.XCREF $DXTMS ;CREF REFERENCE TO SYMBOLIC NAME
;DISPATCH TO FIELD HANDLER WITH P1/INDEX AND T1/DAPXCT TABLE ENTRY
TXNE T1,DX$ILM!DX$SKP;A FIELD THAT WE SHOULD IGNORE?
JRST [CAIN T3,$DXTMN ;YES - EXCEPT THAT
JRST .+1 ;MENUS REQUIRE SPECIAL ATTENTION
JRST XDDAP4] ;JUST SKIP THIS DAP FIELD
PUSHJ P,@XDDAPX(T3) ;DISPATCH ON FIELD TYPE
JRST XDDAP9 ;POSSIBLE ERROR SOMEWHERE
JRST XDDAP4 ;ADVANCE TO NEXT FIELD
;HERE WHEN DAP OUTPUT MESSAGE COMPLETED
XDDAP7: MOVE T2,.IODOM(IO) ;GET MESSAGE CODE
CAIN T2,$DHDAT ;IS IT A DATA MESSAGE?
JRST .POPJ1## ;YES, THEN MORE STILL TO COME
PJRST XDEOM1 ;NO, CAP OFF THE OUTPUT MESSAGE.
;HERE WHEN WE COULDN'T COMPLETE THE OUTPUT MESSAGE
XDDAP9: CAIE M0,$ECTRA ;SHOULD WE TRY AGAIN?
POPJ P, ;NO, HIGHER-UP'S INTERVENTION REQUIRED
MOVE T2,-T2(P) ;YES, FETCH MESSAGE CODE BACK
; EVEN THOUGH IT MIGHT SEEM LIKE AN ERROR
; TO DO THIS IF ENTERED AT XDMSG2 FROM XDDAT,
; $ECTRA SHOULD NEVER HAPPEN FOR DATA SINCE
; DATA MESSAGES ONLY NEED A FEW BYTES TO
; GET STARTED, WHICH THEY ARE GUARANTEED
; IF XDMSG RETURNS SUCCESSFULLY . . .
JRST XDDAP2 ;TRY AGAIN
;DAP MESSAGE FIELD PROCESSOR DISPATCH TABLE
;EACH FIELD PROCESSING ROUTINE IS ENTERED WITH:
; T1/DAPXCT TABLE ENTRY FOR THE FIELD
; P1/DAPXCT TABLE INDEX FOR THE FIELD
;ACS T1 - T4, AND P1 - P4 ARE AVAILABLE FOR USAGE WITHIN THE VARIOUS
;FIELD PROCESSING ROUTINES
XDDAPX: XD00T ;00 - START OF DAP MESSAGE TEMPLATE
XD01T ;01 - ASCII TEXT
XD02T ;02 - BINARY [INTEGER] DATA
XD03T ;03 - COMPRESSED (1 WORD/5 BYTES) BINARY
XD04T ;04 - FLAGS (BIT MAP)
XD05T ;05 - IMAGE 8-BIT BYTES
XD06T ;06 - MENU FIELD
XD07T ;07 - DATE/TIME FIELD
;XD00T - START OF NEW DAP MESSAGE TEMPLATE
XD00T: STOPCD <XD00T dispatch in XDDAP>
;XD01T - ASCII TEXT FIELD
XD01T: MOVE P2,T1 ;PROTECT COPY OF EXECUTION TABLE ENTRY
LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH (DAP BYTES)
LDB T4,[POINTR T1,DX$IOX] ;DAP AREA OFFSET
ADD T4,[POINT 7,.IODAP(IO)];MAKE INTO BYTE POINTER
TXNE T1,DX$XTN ;EXTENSIBLE ASCII?
JRST XD01T5 ;YES
TXNN T1,DX$VAR ;VARIABLE LENGTH ASCII?
JRST XD01T3 ;NO, FIXED LENGTH
PUSHJ P,XDBYT0 ;YES, ALLOCATE COUNT BYTE
POPJ P, ;OOPS
MOVE T1,.IONOP(IO) ;REMEMBER POINTER TO THE COUNT BYTE
JRST XD01T3 ;ENTER BYTE LOOP
;LOOP SENDING FIXED/VARIABLE ASCII OUTPUT FIELD
XD01T2: SOJL T3,XD01T9 ;FIELD SIZE OK?
PUSHJ P,XDBYT0 ;YES, STUFF THIS ASCII CHARACTER
POPJ P, ;OOPS
XD01T3: ILDB T2,T4 ;GET ANOTHER POSSIBLE ASCII CHARACTER
JUMPN T2,XD01T2 ;STORE IF NOT YET END OF STRING
LDB T2,[POINTR P2,DX$LNB] ;LENGTH (MAXIMUM) OF FIELD
SUB T2,T3 ;T2:=ACTUAL FIELD LENGTH
TXNE P2,DX$VAR ;VARIABLE LENGTH FIELD?
DPB T2,T1 ;YES, SET COUNT BYTE
TXNE P2,DX$VAR ;FIXED LENGTH FIELD?
JRST .POPJ1## ;NO, ALL DONE HERE
JUMPE T3,.POPJ1## ;YES, FIELD STILL LEFT?
SETZ T2, ;YES, NULL-FILL REMAINDER OF FIELD
PUSHJ P,XDBYT1 ;FILL WITH ANOTHER NULL
POPJ P, ;OOPS
SOJG T3,.-2 ;LOOP FOR REST OF FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
;LOOP SENDING EXTENSIBLE ASCII OUTPUT
XD01T5: ILDB T2,T4 ;FIRST CHARACTER
JUMPN T2,XD01T7 ;OK IF NON-NULL STRING
PUSHJ P,XDBYT1 ;NULL STRING, FILL OUT THE FIELD
POPJ P, ;OOPS
JRST .POPJ1## ;THAT'S ALL HERE
XD01T7: SOJL T3,XD01T9 ;MAKE SURE STILL ROOM
TRO T2,200 ;MAKE EXTENSIBLE BYTE
PUSHJ P,XDBYT1 ;AND PUT IN OUTPUT MESSAGE
POPJ P, ;OOPS
ILDB T2,T4 ;NEXT BYTE
JUMPN T2,XD01T7 ;LOOP WHILE STRING LASTS
LDB T2,.IONOP(IO) ;RE-FETCH LAST CHARACTER
TRZ T2,200 ;MARK END OF EXTENSIBLE STRING
DPB T2,.IONOP(IO) ;RE-STORE LAST CHARACTER OF FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
;STRING FIELD SIZE EXCEEDED
XD01T9: STOPCD <ASCII string too long for DAP field in XD01T>
;XD02T - BINARY DATA FIELD
;XD03T - COMPRESSED BINARY DATA
XD02T: ;THEY'RE THE SAME (ALMOST)
XD03T: MOVE P2,T1 ;SAVE A COPY OF THE EXECUTION TABLE ENTRY
LDB P3,[POINTR P2,DX$LNB] ;FIELD LENGTH (DAP BYTES)
CAILE P3,^D9 ;WILL IT FIT OUR ALGORITHM?
STOPCD <Binary DAP field larger than 9 bytes in XD03T>
LDB T1,[POINTR P2,DX$LNB] ;SIZE OF FIELD IN 8-BIT BYTES
CAIG T1,4 ;MORE THAN ONE -10 WORDS' WORTH?
MOVEI T1,1 ;NO, ONE WORD IS SUFFICIENT
CAILE T1,4 ;LESS THAN TWO -10 WORDS' WORTH?
MOVEI T1,2 ;NO, TWO WORDS NEEDED
LDB T4,[POINTR P2,DX$TYP] ;FIELD TYPE
CAIN T4,$DXTCN ;COMPRESSED 1 WORD VALUE?
MOVEI T1,1 ;YES, SIZE IS ONE WORD THEN
LDB T2,[POINTR P2,DX$IOX] ;DAP AREA OFFSET
ADDI T2,.IODAP(IO) ;RELOCATE ADDRESS
SETZ T3, ;ASSUME ONLY ONE-WORD VALUE
CAIN T1,1 ;ONE-WORD FIELD?
MOVE T4,(T2) ;YES
CAIN T1,2 ;TWO-WORD FIELD?
DMOVE T3,(T2) ;YES
LSH T4,1 ;POSITION AND
LSHC T3,-1 ;CONCATENATE TWO HALVES
TXNE P2,DX$XTN ;EXTENSIBLE BINARY?
JRST XD03T5 ;YES
TXNN P2,DX$VAR ;NO, VARIABLE-LENGTH BINARY?
JRST XD03T3 ;NO, FIXED-LENGTH FIELD
PUSHJ P,XDBYT0 ;YES, ALLOCATE COUNT BYTE
POPJ P, ;OOPS
MOVE P4,.IONOP(IO) ;REMEMBER WHERE COUNT BYTE IS
JRST XD03T3 ;ENTER LOOP
;LOOP SENDING FIXED/VARIABLE BINARY FIELD
XD03T2: ROTC T3,-^D8 ;POSITION NEXT LEAST SIGNIFICANT BYTE
LSHC T2,^D8 ;AND PUT THE BYTE IN T2
LSH T3,-^D8 ;CORRECT T3
SOJL P3,XD03T9 ;MAKE SURE STILL FITS
PUSHJ P,XDBYT0 ;STUFF AWAY THIS BYTE
POPJ P, ;OOPS
XD03T3: JUMPN T3,XD03T2 ;LOOP FOR ALL OF FIELD
JUMPN T4,XD03T2 ; (ALL TWO WORDS' WORTH)
LDB T2,[POINTR P2,DX$LNB] ;FIELD LENGTH (DAP BYTES)
SUB T2,P3 ;ACTUAL FIELD LENGTH
TXNE P2,DX$VAR ;VARIABLE-LENGTH FIELD?
DPB T2,P4 ;YES, SET BYTE COUNT
TXNE P2,DX$VAR ;FIXED-LENGTH FIELD?
JRST .POPJ1## ;NO, ALL DONE
JUMPLE P3,.POPJ1## ;YES, FIELD FULL?
SETZ T2, ;NO, NEED NULL-FILL
PUSHJ P,XDBYT0 ;FILL REST OF FIELD
POPJ P, ;OOPS
SOJG P3,.-2 ;LOOP FOR REST OF FIELD
JRST .POPJ1## ;ALL DONE
;LOOP FOR EXTENSIBLE BINARY FIELD
XD03T5: STOPCD <Extensible DAP binary field encountered in XD03T>
;BINARY FIELD TOO LARGE
XD03T9: STOPCD <Binary value exceeded DAP binary field size in XD03T>
;XD04T - SEND FLAGS (BIT MAP) FIELD
XD04T: LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH (DAP BYTES)
LDB T4,[POINTR T1,DX$IOX] ;DAP AREA OFFSET
ADD T4,[POINT 7,.IODAP(IO)];MAKE INTO BYTE POINTER
TXNE T1,DX$XTN ;EXTENSIBLE FIELD?
JRST XD04T5 ;YES
STOPCD <Fixed/variable length DAP flags field encountered in XD04T>
;LOOP SENDING EXTENSIBLE FLAGS FIELD
XD04T5: ILDB T2,T4 ;FIRST FLAG BYTE
TROA T2,200 ;GUARANTEE AT LEAST ONE BYTE
XD04T6: ILDB T2,T4 ;NEXT FLAG BYTE
JUMPE T2,XD04T9 ;SEE IF TRAILING NULL
XD04T7: TRO T2,200 ;SET EXTENSIBLE BIT
PUSHJ P,XDBYT1 ;PUT INTO OUTPUT MESSAGE
POPJ P, ;OOPS
SOJG T3,XD04T6 ;LOOP FOR REST OF FIELD
XD04T8: LDB T2,.IONOP(IO) ;RE-FETCH LAST BYTE
TRZ T2,200 ;CLEAR EXTENSIBLE BIT
DPB T2,.IONOP(IO) ;RE-STORE LAST BYTE OF EXTENSIBLE FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
XD04T9: MOVE T1,T3 ;SAVE BYTE COUNT
SOJLE T3,XD04T8 ;COUNT DOWN TRAILING NULLS
ILDB T2,T4 ;FETCH NEXT BYTE'S WORTH OF FLAGS
JUMPE T2,.-2 ;COMPRESS OUT NULLS
SUB T1,T3 ;NON-NULL FLAG,
MOVEI T2,200 ;EXTENSIBLE NULL BYTE
PUSHJ P,XDBYT1 ;FILL OUT NULL BYTES
POPJ P, ;OOPS
SOJG T1,.-2 ;LOOP FOR EMBEDDED NULLS
LDB T2,T4 ;RE-FETCH NON-NULL FLAG BYTE
JRST XD04T7 ;AND SEND IT OUT
;XD05T - IMAGE 8-BIT BYTES
XD05T: LDB T3,[POINTR T1,DX$LNB] ;FIELD LENGTH
LDB T4,[POINTR T1,DX$IOX] ;DAP AREA OFFSET
ADD T4,[POINT 8,.IODAP(IO)];MAKE INTO BYTE POINTER
TXNE T1,DX$XTN ;EXTENSIBLE IMAGE?
JRST XD05T5 ;YES
TXNN T1,DX$VAR ;NO, VARIABLE-LENGTH IMAGE FIELD?
JRST XD05T2 ;NO, FIXED-LENGTH
MOVE T2,T3 ;VARIABLE-LENGTH, GET SIZE OF FIELD
PUSHJ P,XDBYT1 ;ALLOCATE BYTE COUNT BYTE
POPJ P, ;OOPS
;LOOP SENDING ENTIRE IMAGE FIELD (FOR NOW AT LEAST)
XD05T2: ILDB T2,T4 ;NEXT IMAGE BYTE
PUSHJ P,XDBYT1 ;STUFF INTO MESSAGE
POPJ P, ;OOPS
SOJG T3,XD05T2 ;LOOP FOR REST OF MESSAGE FIELD
JRST .POPJ1## ;SUCCESSFUL RETURN
;LOOP SENDING EXTENSIBLE IMAGE FIELD
XD05T5: STOPCD <Extensible DAP image field encountered in XD05T>
;XD06T - MENU FIELD
XD06T: TXNE T1,DX$SKP ;"INVISIBLE" MENU?
JRST XD06T1 ;YES, DON'T TRANSMIT IT, BUT STILL PROCESS IT
PUSHJ P,XD04T ;SEND MENU AS FLAGS
POPJ P, ;OOPS
XD06T1: MOVE P1,.IODXX(IO) ;RESTORE DAPXCT INDEX (JUST TO BE SURE)
LDB T3,[POINTR DAPXCT(P1),DX$LNB] ;FIELD LENGTH (DAP BYTES)
LDB T4,[POINTR DAPXCT(P1),DX$IOX] ;FIELD OFFSET WITHIN DAP AREA
ADD T4,[POINT 7,.IODAP(IO)] ;MAKE INTO BYTE POINTER
DMOVEM T3,.IODXM(IO) ;SET DAP MENU COUNTER/POINTER
;LOOP BUILDING REST OF MESSAGE AS DESCRIBED BY THE MENU
XD06M1: ILDB P2,.IODXM+1(IO) ;GET A MENU BYTE
TROA P2,200 ;FORCE 7-BITS-WORTH OF LOOP
;LOOP WITHIN 7-BIT MENU BYTE
XD06M2: LSH P2,-1 ;NEXT MENU BIT
AOS P1,.IODXX(IO) ;CORRESPONDING EXECUTION TABLE INDEX
TRZN P2,1 ;THIS FIELD WANT TO BE SENT?
JUMPN P2,XD06M5 ;NO, SEE IF ANYTHING MORE
JUMPE P2,XD06M7 ;YES - UNLESS FAKE BIT ("TROA" ABOVE)
;BUILD MENU-SPECIFIED FIELD AND PUT IT IN THE OUTPUT MESSAGE
MOVE T1,DAPXCT(P1) ;EXECUTION TABLE ENTRY FOR THIS FIELD
LDB T3,[POINTR T1,DX$TYP] ;FIELD "TYPE"
CAILE T3,$DXTMX ;ONE WE KNOW ABOUT?
STOPCD <DX$TYP field too large in XD06M>
CAIE T3,$DXTMS ;YES, START OF MESSAGE?
CAIN T3,$DXTMN ;OR MENU?
STOPCD <SOM or MENU field encountered within menu in XD06M>
PUSH P,P2 ;SAVE P2
PUSHJ P,@XDDAPX(T3) ;OK MESSAGE TYPE, BUILD THE FIELD
JRST [POP P,P2 ;ERROR, ADJUST STACK
POPJ P,] ;PROPAGATE THE ERROR
POP P,P2 ;RESTORE MENU BYTE
XD06M5: LDB T3,[POINTR DAPXCT+1(P1),DX$TYP] ;PEEK AT NEXT FIELD TYPE
CAIE T3,$DXTMS ;END OF CURRENT MESSAGE TEMPLATE?
JRST XD06M2 ;NO, MORE FIELDS TO TRY
MOVE T1,P2 ;YES, WHAT'S LEFT OF CURRENT MENU BYTE
JFFO T1,.+1 ;FIND THE FIRST BIT SET
LSH T1,1(T2) ;AND TOSS IT OUT ("TROA" ABOVE)
JUMPN T1,XD06M9 ;IF ANY BITS SET THEN ERROR
ILDB T1,.IODXM+1(IO) ;NEXT MENU BYTE
SOSLE .IODXM+0(IO) ;MAKE SURE IT'S OK (BLANK) TOO
JRST .-3 ; . . .
JRST .POPJ1## ;SUCCESSFUL RETURN
XD06M7: SOS .IODXX(IO) ;THE "TROA" BIT DOESN'T COUNT AGAINST INDEX
SOSLE .IODXM+0(IO) ;COUNT DOWN MENU BYTES
JRST XD06M1 ;AND PROCESS THE NEXT ONE
XD06M9: STOPCD <Too many menu bits/bytes in XD06M>
;XD07T - SEND DATE/TIME FIELD
XD07T: LDB P3,[POINTR T1,DX$LNB] ;DAP FIELD LENGTH
LDB P4,[POINTR T1,DX$IOX] ;DAP AREA OFFSET
ADDI P4,.IODAP(IO) ;P4:=ADDRESS OF DATE/TIME WORD
XMOVEI T1,XD07TO ;HELPER TYPEOUT
PUSHJ P,.XTYPO## ;SET OUTPUT ROUTINE
SKIPE T1,(P4) ;GET THE DATE/TIME WORD
TLNN T1,700000 ;DOES IT LOOK REASONABLE?
STOPCD <Null/Archaic universal date/time value in XD07T>
MOVE P4,[POINT 7,.IODTM(IO)] ;POINTER TO HOLDING AREA
MOVEM P4,.IOXTO(IO) ;SET OUTPUT STUFFER
PUSHJ P,.TDTTM## ;TYPE OUT DATE/TIME
SETZ T1, ;NULL
IDPB T1,.IOXTO(IO) ;ASCIZIZE THE STRING
;NOW CAN SAFELY SEND THE ASCIZ STRING (AND GET BLOCKED IF NEEDED)
SKIPA P2,[":"] ;MARK DATE/TIME TRANSITION
XD07T4: CAIE T2,0 ;IF STRING TERMINATED LEAVE TRAILING NULLS
ILDB T2,P4 ;GET NEXT ASCII CHARACTER
CAME T2,P2 ;DATE/TIME TRANSITION?
JRST XD07T5 ;NO, TAKE CHARACTER VERBATIM
MOVEI T2," " ;YES, DAP WANTS A SPACE HERE
SETO P2, ;ONLY ONE TRANSITION
XD07T5: PUSHJ P,XDBYT0 ;SEND THIS DATE/TIME CHARACTER
POPJ P, ;OOPS
SOJG P3,XD07T4 ;LOOP FOR ENTIRE FIELD'S WORTH
JRST .POPJ1## ;SUCCESS RETURN
;SLAVE HELPER CALLED BY SCAN WITH T1/ASCII CHARACTER
XD07TO: CAIL T1,"a" ;LOWER-CASE LETTER?
CAILE T1,"z" ; (I.E., FROM MONTH)
CAIA ;NO
XORI T1,"a"-"A" ;YES, SHIFT TO UPPER CASE
IDPB T1,.IOXTO(IO) ;STASH THIS CHARACTER
POPJ P, ;RETURN TO WHENCE-EVER
;XDBYC -- OUTPUT ONE DAP FILE-DATA-LEVEL BYTE, HANDLING CRC
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<byte>
; PUSHJ P,XDBYC
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; <byte> is the 8-bit DAP
;file data byte to be sent (eventually) to the remote DAP receiver.
;
;On error return T1 and T2 are preserved. The error or exception code is in
;M0. If the error is recoverable (e.g., output aborted due to arrival
;of input message) then the call to XDBYC may simply be re-executed.
;
;On successful return the DAP file data byte is safely enscounced away
;in the output data message being built.
;
;XDBYC is functionally identical to XDBYT but the file data CRC is
;updated to reflect the file data flow.
;
;Preserves all acs.
ENTRY .XDBYC
INTERN XDBYC0, XDBYC1
INTERN XDCRC1
.XDBYC: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDBYC0:
XDBYC1: PUSHJ P,XDBYT0 ;FIRST STUFF THE FILE DATA BYTE
POPJ P, ;PROPAGATE EXCEPTION RETURN
XDCRC1: PUSH P,T2 ;SAVE FILE DATA BYTE
ANDI T2,377 ;REDUCE TO JUST INTERESTING DATA
MOVE M0,.IODOK(IO) ;RETRIEVE OLD FILE DATA CRC
XORB M0,T2 ;INCLUDE BYTE IN CRC
ANDI T2,377 ;COMPUTE OFFSET INTO CRC TABLE
LSH M0,-^D08 ;XOR REMAINING CRC FROM TABLE
XOR M0,DAPCRC(T2) ;COMPUTE NEW CRC
MOVEM M0,.IODOK(IO) ;SAVE UPDATED CRC
POP P,T2 ;RESTORE CALLER'S BYTE
JRST .POPJ1## ;AND SUCCESSFULLY RETURN
;XDBYT -- OUTPUT ONE DAP MESSAGE-LEVEL BYTE
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<byte>
; PUSHJ P,XDBYT
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; <byte> is the 8-bit DAP
;message byte to be sent (eventually) to the remote DAP receiver.
;
;On error return T1 and T2 are preserved. The error or exception code is in
;M0. If the error is recoverable (e.g., non-blocking return) then the call
;to XDBYT may simply be re-executed.
;
;On successful return the DAP message byte is safely enscounced away
;in the output message being built.
;
;XDBYT will take care of shipping either continuation messages (i.e.,
;DAP "MOR" flag set, segmenting a single logical DAP message into multiple
;physical messages) or large messages sans the length field as needed -
;the caller does not need to worry about message blocking.
;
;Preserves all acs.
ENTRY .XDBYT
INTERN XDBYT0, XDBYT1
.XDBYT: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDBYT0:
XDBYT1: SOSGE .IODOC(IO) ;ROOM FOR ANOTHER MESSAGE BYTE?
JRST XDBYT2 ;NO, NEED TO MAKE ROOM
PUSHJ P,XNBYT0 ;YES, OUTPUT ANOTHER NETWORK BYTE
AOSA .IODOC(IO) ;OOPS - FAILED, ADJUST DAP BYTE COUNT BACK
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;HERE WHEN OUT OF ROOM TO SHIP THE DAP MESSAGE
XDBYT2: PUSHJ P,TSAV14## ;WE NEED SOME ACS HERE
SKIPLE T2,.IODOX(IO) ;BEEN HERE ALREADY?
JRST XDBYT6 ;YES, SKIP THIS PART THEN
JUMPL T2,XDBYU0 ;IF FUNNY BUSINESS, TRY TO RESUME
SKIPG T2,.IODOM(IO) ;NO, GET CURRENT OUTPUT MESSAGE TYPE
STOPCD <XDBYT called but no DAP message in progress>
MOVD T3,CNF ;GET CONFIGURATION FLAGS
CAIN T2,$DHDAT ;IS OVERFLOW DATA OR NON-DATA MESSAGE?
TFNN T3,DSG ;DATA - CAN REMOTE HANDLE DAP SEGMENTATION?
JRST XDBYV0 ;NO, DRASTIC MEASURES ARE NEEDED
;HERE TO SEGMENT THE OUTPUT DATA MESSAGE INTO MULTIPLE CONTINUED MESSAGES
XDBYT4: MOVEM T2,.IODOX(IO) ;SET FLAG IN CASE "INTERRUPTED"
PUSHJ P,XDMOR0 ;SHIP CURRENT MESSAGE AS A CONTINUED MESSAGE
POPJ P, ;BLETCH
MOVE T2,.IODOX(IO) ;RETRIEVE MESSAGE TYPE TO BE CONTINUED
;HERE TO START A NEW MESSAGE SEGMENT
XDBYT6: PUSHJ P,XDMSG0 ;STARTUP A NEW DAP MESSAGE
POPJ P, ;BLETCH
XDBYT8: SKIPG .IODOC(IO) ;MAKE SURE WE HAVE A BUFFER
STOPCD <XDMSG returned successfully with 0-length buffer in XDBYT>
SETZM .IODOX(IO) ;CLEAR INTERLOCK
MOVE T2,-T2(P) ;RESTORE ORIGINAL MESSAGE BYTE
JRST XDBYT1 ;AND STUFF IT IN THE OUTPUT BUFFER
;HERE ON "CONTINUATION" FROM SOME SORT OF BUFFER COMPRESSION
XDBYU0: PUSHJ P,XNFLS0 ;FLUSH OUT THE NETWORK BUFFER
POPJ P, ;STILL NO GO
XDBYU2: MOVE T1,.IODOX(IO) ;GET "STATE" VARIABLE
AOJE T1,XDBYV2 ;TIME TO "TRY AGAIN"
AOJE T1,XDBYV6 ;"BLT" THE INCOMPLETE MESSAGE UP
STOPCD <Confusion reigns in XDBYT at XDBYU2>
;HERE WHEN EITHER THE DAP MESSAGE LENGTH FIELD OVERFLOWS OR THE
;NETWORK BUFFER OVERFLOWS (AND THE REMOTE CAN'T HANDLE DATA MESSAGE
;SEGMENTATION). TRY TO SHIP WHAT WE HAVE AND FINISH THE REST OF THE
;CURRENT DAP MESSAGE LATER.
XDBYV0: SETOM .IODOX(IO) ;FLAG STATE AT FLUSHING AND TRY AGAIN
DMOVE T3,.IODXA(IO) ;FETCH IONOC/IONOP AT LAST DAP BOM TIME
CAME T3,.IONLM(IO) ;IS THIS THE ONLY MESSAGE IN THE BUFFER?
SKIPLE .IONOC(IO) ;OR IS THERE STILL ROOM IN THE BUFFER?
JRST XDBYW0 ;YES, SEND SANS LENGTH/LEN256/BITCNT FIELDS
;DAP MESSAGES ALREADY STASHED IN THE BUFFER, FLUSH THEM OUT
CAIN T2,$DHDAT ;WORKING ON A DATA OR OTHERWISE MESSAGE?
JRST XDBYV4 ;DATA, CAN'T THROW IT AWAY, LOTS OF WORK
;HERE ON NON-DATA MESSAGE OVERFLOWING, THROW THE CURRENT ATTEMPT AWAY,
;SHIP WHAT'S IN THE BUFFER, THEN TRY THE NON-DATA MESSAGE AGAIN
PUSHJ P,XDABM0 ;ABORT THE CURRENT NON-DATA MESSAGE
; NOTE - NEVER "SUCCEEDS"
PUSHJ P,XDFLS0 ;FLUSH OUT PRECEDING DAP MESSAGES
POPJ P, ;NET DIED?
XDBYV2: SETZM .IODOX(IO) ;CLEAR ABORTING STATE
MOVEI M0,$ECTRA ;THE "TRY AGAIN" EXCEPTION RETURN
POPJ P, ;TELL XDDAP/ET AL TO TRY AGAIN
;HERE ON A DATA MESSAGE THAT OVERFLOWED THE NETWORK BUFFER, FLUSH OUT
;PRECEDING DAP MESSAGES THEN "BLT" THE CURRENT DATA MESSAGE UP TO THE
;TOP OF THE BUFFER AND CONTINUE ON OUR MERRY WAY.
XDBYV4: SOS .IODOX(IO) ;SET STATE TO DATA MESSAGE FLUSHING
MOVEM T3,.IONOC(IO) ;RESTORE COUNTER AND
MOVEM T4,.IONOP(IO) ; POINTER TO PRECEDE CURRENT [INCOMPLETE]
PUSHJ P,XNEOM0 ; MESSAGE AND FLUSH PRECEDING DATA OUT
POPJ P, ;NET DIED?
;MOVE INCOMPLETE DATA MESSAGE TO TOP OF BUFFER AND CONTINUE
XDBYV6: DMOVE T2,.IODXA(IO) ;T2:=COUNT OF SAVED MESSAGE BYTES
;T3:=START OF SAVED MESSAGE BYTES
MOVE T4,.IONOP(IO) ;T4:=START OF FRESH MESSAGE BUFFER
PUSHJ P,.BYBLT## ;SHUFFLE OLD MESSAGE TO TOP OF BUFFER
STOPCD ;CAN'T HAPPEN
MOVE T3,.IONOC(IO) ;FRESH COUNTER
EXCH T4,.IONOP(IO) ;FRESH POINTER (UPDATING CURRENT)
MOVN T1,.IODXA(IO) ;REFETCH SAVED COUNT
ADDM T1,.IONOC(IO) ;UPDATE BYTES LEFT IN "FRESH" BUFFER
DMOVEM T3,.IODXA(IO) ;AND SET NEW ABORTION POINTERS
;NOW TO RELOCATE ALL THE "SAVED" DAP MESSAGE BYTE POINTERS
MOVE T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADDM T1,.IODO0(IO) ;RELOCATE SAVED BOD COUNTER
MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADJBP T1,.IODO1(IO) ;RELOCATE "HEADER" FLAGS BYTE POINTER
MOVEM T1,.IODO1(IO) ; AND SAVE IT FOR OTHERS
; MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
; ADJBP T1,.IODO2(IO) ;RELOCATE "STREAMID" BYTE POINTER
; MOVEM T1,.IODO2(IO) ; AND SAVE IT FOR OTHERS
MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADJBP T1,.IODO3(IO) ;RELOCATE "LENGTH" BYTE POINTER
MOVEM T1,.IODO3(IO) ; AND SAVE IT FOR OTHERS
MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADJBP T1,.IODO4(IO) ;RELOCATE "LEN256" BYTE POINTER
MOVEM T1,.IODO4(IO) ; AND SAVE IT FOR OTHERS
MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADJBP T1,.IODO5(IO) ;RELOCATE "BITCNT" BYTE POINTER
MOVEM T1,.IODO5(IO) ; AND SAVE IT FOR OTHERS
MOVN T1,.IONOC(IO) ;DISTANCE THE MESSAGE SHIFTED
ADJBP T1,.IODO9(IO) ;RELOCATE "BOD" BYTE POINTER
MOVEM T1,.IODO9(IO) ; AND SAVE IT FOR OTHERS
;NOW CALCULATE THE NEW DAP BYTE COUNT
MOVE T4,.IODOF(IO) ;DAP MESSAGE HEADER FLAGS
TFNN T4,HLN ;GOT A LENGTH FIELD?
JRST XDBYW5 ;NO, NO LIMIT
MOVEI T2,377 ;YES, ASSUME 2**8 BYTE LIMIT
TFNE T4,HL2 ;GOT A LEN256 FIELD?
MOVEI T2,177777 ;YES, THEN 2**16 BYTE LIMIT
SUB T2,.IODO0(IO) ;CALCULATE MAX POSSIBLE ROOM LEFT
ADD T2,.IONOC(IO) ; BASED ON ALREADY-PRESENT DATA
CAMLE T2,.IONOC(IO) ;LIMITED BY BUFFER SIZE STILL?
MOVE T2,.IONOC(IO) ;YES, CHOOSE SMALLER LIMIT
PJRST XDBYW8 ;FINISH OFF AND OUTPUT THE DAP BYTE
;SINGLE DAP MESSAGE OVERFLOWS THE NETWORK BUFFER, STRIP OFF THE LENGTH
;AND UNUSED BITCOUNT FIELDS, AND START SHIPPING NETWORK BUFFERS AS THEY
;ARE FILLED (ASSUME THE MESSAGE SIZE IS UNLIMITED).
XDBYW0: SKIPN .IODO3(IO) ;GOT A LENGTH FIELD?
JRST XDBYW5 ;NO, NOTHING TO COMPRESS, JUST OUTPUT
; (ACTUALLY WE MIGHT STILL BE ABLE TO COMPRESS
; OUT A BITCOUNT FIELD, BYT WHY BOTHER?)
MOVEI T1,1 ;ONE BYTE FOR THE "LENGTH" FIELD
SKIPE .IODO4(IO) ;GOT A "LEN256" FIELD?
ADDI T1,1 ;ONE MORE BYTE
SKIPE .IODO5(IO) ;GOT A BITCOUNT FIELD?
ADDI T1,1 ;YEAH, COMPRESS IT OUT TOO ON G.P.S
MOVE T2,T1 ;COUNT OF BYTES TO SHIFT
ADDB T1,.IONOC(IO) ;ADJUST NETWORK BYTE COUNTER
ADDB T2,.IODO0(IO) ;ADJUST SAVED DAP BOD BYTE COUNTER
SUB T2,T1 ;T2:=AMOUNT OF BYTES TO COMPRESS UP
MOVNI T3,1 ;ALLOW FOR THE "I" OF .BYBLT'S ILDB LOOP
ADJBP T3,.IODO9(IO) ;T3:= ILDB POINTER TO PRE-COMPRESSION DATA
MOVNI T4,1 ;ALLOW FOR THE "I" OF .BYBLT'S IDPB LOOP
ADJBP T4,.IODO3(IO) ;T4:= IDPB POINTER TO POST-COMPRESSION DATA
PUSHJ P,.BYBLT## ;COMPRESS OUT THE LENGTH/ETC. FIELDS
STOPCD ;CAN'T HAPPEN
MOVEM T4,.IONOP(IO) ;SET COMPRESSED NETWORK BUFFER STUFFER
;NOW ADJUST OUR COPIES OF WHAT FIELDS ARE LEFT
MOVE T4,.IODOF(IO) ;DAP HEADER FLAGS
TFZ T4,<HLN,HL2,BCT>;CLEAR NEWLY-NON-EX FIELDS
MOVEM T4,.IODOF(IO) ;SAVE UPDATED FLAGS
SETZ T3, ;CLEAR EXTRANEOUS BITS
LSHC T4,^D07 ;POSITION FIRST BYTE OF FLAGS
DPB T3,.IODO1(IO) ;SAVE UPDATED FLAGS IN DAP MESSAGE TOO
;SETUP FOR "EXTENDED" MESSAGE SIZE
XDBYW5: SETZM .IODO3(IO) ;NO "LENGTH" FIELD LEFT
SETZM .IODO4(IO) ;NO "LEN256" FIELD LEFT
SETZM .IODO5(IO) ;NO "BITCNT" FIELD LEFT (EVEN IF SHIPPED)
MOVX T2,ID.SNM ;THE OK-TO-SEGMENT-NETWORK-MESSAGES FLAG
IORM T2,.IODPF(IO) ;TELL XNBYT WE KNOW WHAT WE'RE DOING
HRLOI T2,223344 ;AN ARBITRARILY LARGE BYTE COUNT
XDBYW8: MOVEM T2,.IODOC(IO) ;SET NEW DAP BYTE COUNT
JRST XDBYT8 ;TRY TO OUTPUT THE BYTE AGAIN
;XDMSG -- START UP A NEW DAP OUTPUT MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<code>
; PUSHJ P,XDMSG
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and<code> is the DAP
;message type to be started.
;
;On error return the network died.
;
;On successful return a new DAP message has been started and calls
;may be made to XDBYT.
;
;Uses acs T1, T2, T3, T4.
ENTRY .XDMSG
INTERN XDMSG0, XDMSG1
.XDMSG: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDMSG0: PUSHJ P,.SAVE4## ;NEED A FEW MORE ACS
XDMSG1: PUSHJ P,TSAV14## ;SAVE THE T'S TOO
XDMSG2: SKIPLE .IODOM(IO) ;IN MIDDLE OF A DAP MESSAGE ALREADY?
STOPCD <XDMSG called before current DAP message finished>
;START UP A NEW MESSAGE
XDMSG4: MOVE T3,.IONOC(IO) ;CURRENT OUTPUT COUNTER
MOVE T4,.IONOP(IO) ;AND POINTER AT START OF DAP MESSAGE
DMOVEM T3,.IODXA(IO) ;SAVE FOR XDABM
HRRZM T2,.IODOM(IO) ;SET NEW CURRENT OUTPUT MESSAGE TYPE
PUSHJ P,XNBYT1 ;AND PUT IN THE OUTPUT BUFFER
STOPCD <XNBYT failed at XDMSG4>
MOVD T3,CNF ;GENERIC [REMOTE] CONFIGURATION
MOVDII P1,MHF,<HLN,HL2>;INITIAL DAP MESSAGE HEADER FLAGS
CAIE T2,$DHCFG ;IF A CONFIGURATION MESSAGE,
TFNN T3,<BLR,BLU> ;OR IF NOT ALLOWED TO BLOCK MESSAGES,
TFZ P1,<HLN,HL2> ;THEN DON'T SEND LENGTH FIELDS
TFNN T3,C25 ;IS "LEN256" FIELD SUPPORTED?
TFZ P1,HL2 ;NO, THEN DON'T SEND ONE
CAIE T2,$DHDAT ;DATA MESSAGE?
JRST XDMSH ;NO, ALL SET
MOVD T2,DTY ;GET DATA TYPE
TFNN T2,ASC ;IF ASCII DATA
TFNN T3,BTC ;OR IF BITCOUNT NOT SUPPORTED BY REMOTE
JRST XDMSH ;THEN DON'T REQUEST BITCOUNT FIELD
MOVD1 T2,BSZ ;DAP DATA BYTE SIZE
TRNE T2,7 ;DATA A MULTIPLE OF 8?
TFO P1,BCT ;NO, SUPPLY UNUSED BITCOUNT FIELD
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;BUILD REST OF DAP MESSAGE HEADER BASED ON "MENU" IN P1
;NOTE THAT THE SAVE DAP MESSAGE HEADER BYTE POINTERS ARE SUBJECT TO
;DYNAMIC RELOCATION. THEY SHOULD THEREFORE NEVER BE SAVED ON THE STACK
;OR ANYWHERE ELSE. IF ANY NEW ONES ARE ADDED, BY SURE TO ALSO UPDATE
;XDBYT TO RELOCATE THEM AS WELL.
XDMSH: MOVE T3,P1 ;POSITION WORKING COPY
MOVEM P1,.IODOF(IO) ;ALSO SAVE FOR OTHERS
SETZ T2, ;CLEAR EXTRANEOUS BITS
LSHC T2,^D7 ;POSITION FIRST BYTE OF FLAGS
CAIE T3,0 ;MORE FOLLOWING?
STOPCD <Too many DAP message header flags in XDMSH>
PUSHJ P,XDMSB1 ;OUTPUT FLAGS BYTE
JRST XDMSK9 ;PROBLEM, CHECK IT OUT
MOVE T4,.IONOP(IO) ;OUTPUT BYTE POINTER
MOVEM T4,.IODO1(IO) ;SAVE FOR XDMOR
;SEND STREAM ID FIELD
TFNN P1,SID ;STREAM ID WANTED?
JRST XDMSH4 ;NO
STOPCD <DAP stream ID requested in XDMSH>
;SEND LENGTH FIELD
XDMSH4: TFNN P1,HLN ;NEED TO SEND A HEADER LENGTH?
JRST XDMSH5 ;NO
PUSHJ P,XDMSB0 ;YES, ALLOCATE A BYTE
JRST XDMSK9 ;PROBLEM, CHECK IT OUT
SKIPA T2,.IONOP(IO) ;GET BYTE POINTER
XDMSH5: SETZ T2, ;NO LENGTH FIELD
MOVEM T2,.IODO3(IO) ;SAVE FOR XDEOM
;SEND LEN256 FIELD
TFNN P1,HL2 ;NEED TO SEND EXTENDED HEADER LENGTH FIELD?
JRST XDMSH6 ;NO
PUSHJ P,XDMSB0 ;YES, ALLOCATE A BYTE
JRST XDMSK9 ;PROBLEM, CHECK IT OUT
SKIPA T2,.IONOP(IO) ;GET BYTE POINTER
XDMSH6: SETZ T2, ;NO LEN256 FIELD
MOVEM T2,.IODO4(IO) ;SAVE FOR XDEOM
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;SEND TRAILING UNUSED BIT COUNT
TFNN P1,BCT ;WANT TRAILING UNUSED BITS?
JRST XDMSH7 ;NO
PUSHJ P,XDMSB0 ;YES, ALLOCATE A BYTE
JRST XDMSK9 ;PROBLEM, CHECK IT OUT
SKIPA T2,.IONOP(IO) ;GET BYTE POINTER
XDMSH7: SETZ T2, ;NO BITCNT FIELD
MOVEM T2,.IODO5(IO) ;SAVE FOR XDEOM
;NOW SET DAP BYTE COUNTER
MOVE T2,.IONOC(IO) ;INITIALLY, LIMIT AT BUFFER END
; (XDBYT WILL TAKE CARE OF MESSAGE OVERFLOW
; FROM A "SHORT" COUNT HERE)
TFNN P1,HLN ;SENDING HEADER LENGTH FIELD?
JRST XDMSH9 ;NO
TFNN P1,HL2 ;YES, LIMITED TO ONE BYTE?
CAIG T2,377 ;YES, WILL WE FIT?
CAIA ;ALL SET
MOVEI T2,377 ;USE SMALLER ONE-BYTE LIMIT
XDMSH9: MOVEM T2,.IODOC(IO) ;SET DAP OUTPUT BYTE COUNTER
MOVE T2,.IONOC(IO) ;CURRENT OUTPUT BUFFER BYTE COUNTER
MOVEM T2,.IODO0(IO) ;SAVE FOR XDEOM
MOVE T2,.IONOP(IO) ;CURRENT OUTPUT BUFFER BYTE POINTER
IBP T2 ;POINT TO FIRST DAP MESSAGE BYTE
MOVEM T2,.IODO9(IO) ;SAVE FOR XDBYT
JRST .POPJ1## ;SUCCESSFUL RETURN
;HERE WHEN CAN'T SHIP A MESSAGE HEADER BYTE
XDMSK9: CAIE M0,$ECTRA ;XDMSB WANT US TO TRY AGAIN?
POPJ P, ;NOPE, BAD ERROR
MOVE T2,-T2(P) ;YES, FETCH ORIGINAL MESSAGE TYPE
JRST XDMSG4 ;AND TRY AGAIN
;HERE TO SHIP ONE MESSAGE HEADER BYTE
XDMSB0: SETZ T2, ;A NICE NULL FILLER BYTE
XDMSB1: SKIPLE .IONOC(IO) ;ROOM LEFT IN THE NETWORK BUFFER?
PJRST XNBYT0 ;YES, ALL SET
PUSHJ P,XDABM2 ;NO, ABORT CURRENT EMBYRIONIC MESSAGE
; NOTE -NEVER SUCCEEDS
PUSHJ P,XDFLS1 ;FLUSH OUT PRECEDING DAP DATA
POPJ P, ;OOPS
MOVEI M0,$ECTRA ;TRY TRY AGAIN
POPJ P, ;EXCEPTION RETURN
;XDABM -- ABORT THE CURRENT OUTPUT DAP MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XDABM
; error return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;Note that this routine always take the error return, preserving caller's M0!
;
;Uses acs T1, T2.
ENTRY .XDABM
INTERN XDABM0, XDABM1
.XDABM: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDABM0:
XDABM1: SKIPG T1,.IODOM(IO) ;GET MESSAGE TYPE
POPJ P, ;NOTHING TO ABORT, PROPAGATE THE ERROR
CAIN T1,$DHDAT ;DATA MESSAGE?
STOPCD <Can't abort data message in XDABM>
MOVE T1,.IODPF(IO) ;GET DAP LOGIC CONTROL FLAGS
TXNE T1,ID.SNM ;HAVE WE ALREADY COMMITTED TO THIS MESSAGE?
STOPCD <Can't abort already-partially-transmitted DAP message in XDABM>
XDABM2: DMOVE T1,.IODXA(IO) ;SAVED MESSAGE ABORTION POINTER
JUMPE T1,XDABM5 ;SKIP IF NO SAVED POINTER
MOVEM T1,.IONOC(IO) ;RESET NETWORK BYTE COUNTER AND
MOVEM T2,.IONOP(IO) ;POINTER TO EAT CURRENT MESSAGE
XDABM5: SETZM .IODOM(IO) ;NO MESSAGE BEING BUILT NOW
SETOM .IODOC(IO) ;JUST TO MAKE SURE
SETZM .IODOB(IO) ;CLEAR TRAILING UNUSED BIT COUNT
POPJ P, ;PROPAGATE ERROR RETURN
;XDMOR -- SEND A MESSAGE SEGMENT (MESSAGE WITH "MOR" FLAG)
;XDEOM -- SEND DAP MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XDEOM/XDMOR
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died.
;
;On normal return the current DAP output message has been closed off.
;If needed (can't piggyback messages or data message) the output message
;will be shipped to the remote.
;
;Uses T1, T2, T3, T4
ENTRY .XDMOR
INTERN XDMOR0, XDMOR1
.XDMOR: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDMOR0:
XDMOR1: SKIPG .IODOM(IO) ;IN MIDDLE OF MESSAGE PROCESSING?
STOPCD <XDMOR but no DAP message in progress>
MOVD T3,CNF ;GET REMOTE'S CONFIGURATION
TFNN T3,DSG ;DAP SEGMENTATION SUPPORTED?
STOPCD <XDMOR called but remote doesn't support segmentation>
MOVE T2,.IODOF(IO) ;GET DAP HEADER FLAGS
TFO T2,MOR ;FLAG MORE TO COME AFTER THIS SEGMENT
SETZ T1, ;CLEAR EXTRANEOUS BITS
LSHC T1,^D07 ;POSITION FIRST BYTE OF FLAGS
DPB T1,.IODO1(IO) ;SET IN MESSAGE HEADER FLAGS
JRST XDEOM0 ;GO SEND THE MESSAGE [SEGMENT]
ENTRY .XDEOM
INTERN XDEOM0, XDEOM1
.XDEOM: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDEOM0:
XDEOM1: SKIPG .IODOM(IO) ;IN MIDDLE OF MESSAGE PROCESSING?
STOPCD <XDEOM but no DAP message in progress>
SKIPN T2,.IODO3(IO) ;SENDING LENGTH FIELD?
JRST XDEOM3 ;NO
MOVE T1,.IODO0(IO) ;YES, GET SAVED BYTE COUNT
SUB T1,.IONOC(IO) ;T1:=SIZE OF DAP "OPERAND"
DPB T1,T2 ;SET LOW ORDER LENGTH
LSH T1,-^D8 ;POSITION HIGH ORDER LENGTH
SKIPE T2,.IODO4(IO) ;HIGH ORDER FIELD PRESENT?
JRST XDEOM2 ;YES
JUMPE T1,XDEOM3 ;NO, OK UNLESS SIZE .GT. ^O377
STOPCD <DAP length greater than ^D255 but no LEN256 field in XDEOM>
XDEOM2: DPB T1,T2 ;SET HIGH ORDER LENGTH FIELD
XDEOM3: SETZ T1, ;RESET COUNT TO 0
EXCH T1,.IODOB(IO) ;UNUSED BIT COUNT FIELD
SKIPE T2,.IODO5(IO) ;WANT UNUSED BITS?
JRST XDEOM4 ;YES
JUMPE T1,XDEOM7 ;NO, OK UNLESS THERE ARE UNUSED BITS
MOVE T2,.IODOM(IO) ;NO UNUSED BITCNT POINTER
CAIE T2,$DHDAT ;ENDING A DATA MESSAGE?
JRST XDEOM7 ;NO, THEN IT DOESN'T REALLY MATTER
STOPCD <DAP data bits unused but no BITCNT field in XDEOM>
XDEOM4: DPB T1,T2 ;YES
XDEOM7: SETOM .IODOC(IO) ;NO MORE DAP BYTES UNTIL XDMSG
SETZM .IODOM(IO) ;NOT IN MESSAGE ANYMORE
SETZM .IODXA(IO) ;JUST TO MAKE SURE
SKIPE .IODO3(IO) ;IS LENGTH FIELD MISSING?
SKIPG .IONOC(IO) ;OR NETWORK BUFFER EMPTY?
PJRST XNEOM1 ;YES, THEN FORCE THIS BUFFER OUT NOW
;*** MOVD1 T1,FST ;*** GET REMOTE FILE SYSTEM TYPE
;*** CAIN T1,$DVFF1 ;*** IS THIS FCS-11 (RSX-11)?
;*** PJRST XNEOM1 ;*** YES, NEVER BLOCK MESSAGES TOGETHER
;*** ;*** FCS-11 FAL HAS SOME OBSCURE BUG THAT
;*** ;*** DOESN'T ALWAYS LIKE BLOCKED MESSAGES
;*** ;*** EVEN THOUGH IT SOMETIMES WORKS . . .
JRST .POPJ1## ;TRY TO PIGGYBACK FOLLOWING DAP MESSAGES
;XDFLS -- FLUSH OUT ANY PENDING DAP OUTPUT
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XDFLS
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return either the network died or an input message has been
;received and awaits processing.
;
;On normal return all pending DAP output messages have been given to
;the monitor to be sent to the remote receiver.
;
;Uses T1.
ENTRY .XDFLS
INTERN XDFLS0, XDFLS1
.XDFLS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XDFLS0:
XDFLS1: SKIPLE .IODOM(IO) ;IN MESSAGE PROCESSING?
STOPCD <XDFLS called with DAP output message is progress>
SETOM .IODOC(IO) ;MAKE SURE XDBYT NOT CONFUSED
XDFLS3: SKIPLE T1,.IONOC(IO) ;GET OUTPUT BUFFER SPACE LEFT
CAME T1,.IONLM(IO) ;[MAXIMUM-MESSAGE-SIZE] BUFFER EMPTY?
PJRST XNEOM0 ;NO, SEND IT OUT
JRST .POPJ1## ;YES, ALL DONE
SUBTTL DAP Protocol Tables
;*** SOME RANDOM DEFINITIONS FOR EASE OF DEBUGGING
.CREF .IDRCN ;DATA MESSAGE RECORD NUMBER
.CREF .IDSTC ;STATUS MESSAGE STATUS CODE
.CREF .IDSRA ;STATUS MESSAGE RECORD ADDRESS
.CREF .IDSRN ;STATUS MESSAGE RECORD NUMBER
.CREF .IDSTV ;STATUS MESSAGE SECODARY STATUS
SUBTTL DAP Protocol Tables - Execution table index table
;THE DAP EXECUTION TABLE INDEX
DAPIDX::DODAP(IDX)
SUBTTL DAP Protocol Tables - Execution table
;AND THE DAP EXECUTION TABLE
DAPXCT::DODAP(XCT)
SUBTTL DAP Protocol Tables - Field-text table
;THE DAP MESSAGE/FIELD TEXT DESCRIPTION TABLE
DAPXTX::DODAP(XTX)
SUBTTL DAP Protocol Tables - Status-code text table
;THE DAP STATUS CODE TEXT DESCRIPTION TABLE
DAPSTS::DODAP(STS)
SUBTTL DAP Protocol Tables - CRC polynomial table
;THE DAP CRC POLYNOMIAL TABLE
DAPCRC::BLDCRC (164405) ;X^16 + X^15 + X^13 + X^7 + X^4 + X^2 + X^1 + 1
SUBTTL Network Link Control - Link initialization
;NTNIA -- INITIALIZE ACTIVE NETWORK CHANNEL
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<NOD>
; PUSHJ P,NTNIA
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <NOD> is the SIXBIT
;node name with whom communications are desired.
;
;The caller is responsible for setting up all other network parameters
;such as object type and name, optional user data, etc.
;
;On error return, a connection could not be established, an error code
;is in M0.
;
;On normal return, a network channel has been assigned (and is returned
;in .IONCH) and the "Connect Initiate" message has been posted to the
;specified node.
;
;Note that NTNIA only requests a network logical link, it does not in any
;way ensure that the specified node will accept the request - a call to
;NTNCW must be executed to "block" waiting for completion of the request.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNIA
INTERN NTNIA0, NTNIA1
.NTNIA: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNIA0: PUSHJ P,.SAVE4## ;PRESERVE A FEW ACS
NTNIA1: SKIPE .IONCH(IO) ;MAKE SURE CDB NOT ALREADY ACTIVE
STOPCD <NTNIA called with outstanding network channel>
;SELECT THE DESTINATION NETWORK NODE
MOVE T3,T2 ;POSITION NODE SPECIFIER
PUSHJ P,.NDNAM## ;TRY TO MAKE SENSE OF IT
MOVEM T1,.ION6M(IO) ;SET NODE NAME (SIXBIT) FOR INTEREST
JUMPL T2,NDNIA1 ;IF NOT KNOWN ANF, THEN ASSUME DECNET
; JRST NANIA1 ;USE ANF NETWORK
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;HERE FOR ANF ENTER ACTIVE
NANIA1: MOVEM T2,.I1NSC+0(IO) ;SET TSK. NODE NUMBER IN DESTINATION NPD
SKIPN .IONDF(IO) ;WE REQUIRE A DESTINATION NPD FROM CALLER
STOPCD <No destination NPD in NANIA1>
;SETUP AND BUILD THE TSK.-STYLE CONNECT INFO
PUSHJ P,NAS1I1 ;INITIALIZE FOR STRING BUILDING
STOPCD <NAS1I1 failed in NANIA1>
PUSHJ P,.XTYPO## ;SELECT BYTE TYPER
MOVEI P2,"0" ;DEFAULT IS RANDOM TASK
PUSHJ P,NAS2I1 ;ENCODE THE SOURCE AND DESTINATION NPD
STOPCD <NAS2I1 failed in NANIA1>
MOVEI P2,0 ;NO DEFAULT FOR USER ID STUFF
PUSHJ P,NAS3I1 ;ENCODE USER ID/PASSWORD/AD NAUSEUM
STOPCD <NAS3I1 failed in NANAI1>
SKIPL T1,.IONP3(IO) ;DID IT ALL FIT?
STOPCD <Strings too big in NANIA1>
HRRZM T1,.I1NSC+1(IO) ;SET TSK. NPD BYTE COUNT
;NOW ASSIGN A TASK CHANNEL AND REQUEST A NETWORK CONNECT INIT
NANIA5: MOVX M0,IO.NET!IO.ANF;FLAG ANF-STYLE NETWORK CHANNEL
IORM M0,.IOCCF(IO) ;UPDATE CHANNEL CONTROL
PUSHJ P,NAS4I1 ;ASSIGN A TSK: CHANNEL, ETC
POPJ P, ;ERROR
MOVX P1,.TKFEA ;FUNCTION: ENTER ACTIVE
MOVE T1,[4,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;SEND A CONNECT INIT
JRST NACIE1 ;PROCESS TSK. CONNECT ERROR
JRST .POPJ1## ;CONNECT INIT POSTED
;HERE FOR DECNET-STYLE ENTER ACTIVE
NDNIA1: MOVE T2,T1 ;POSITION SIXBIT NAME IN T2
MOVE P3,[6,,.IONNM] ;8-BIT NAME POINTER
PUSHJ P,N6TO8 ;CONVERT 6-BIT TO 8-BIT NAME
STOPCD <Node name N6TO8 failed in NTNIA>
HRLI P3,$NTNBL ;SET MAXIMUM "NAME BLOCK LENGTH"
MOVSM P3,.IONNM(IO) ;SET BYTE,,WORD COUNTS FOR NODE NAME BLOCK
;COMMON CODE TO INITIALIZE FOR NSP.
PUSHJ P,NDS1I1 ;SETUP NSP. ARGUMENTS
STOPCD <NDS1I1 failed in NDNAI1>
;"QUEUE" THE REQUEST WITH NETWORK SERVICES VIA THE MONITOR
MOVX M0,IO.NET!IO.DCN;FLAG ACTIVE DECNET CHANNEL
IORM M0,.IOCCF(IO) ;SET IN THE CDB
XMOVEI P3,.I1NSC(IO) ;NSP. CONNECT BLOCK ADDRESS
SETZ P2, ;NO CHANNEL YET
MOVE P1,[.NSFEA,,.NSAA1+1] ;"ENTER ACTIVE" FUNCTION
TXO P1,NS.WAI ;*** IT STILL DOESN'T WORK!!!!!!!!!!
XMOVEI M0,P1 ;NSP. ARG BLOCK TO
NSP. M0, ;ASK FOR AN ACTIVE NETWORK CHANNEL
JRST NDCIE1 ;PROCESS NSP. CONNECT ERROR
HRRZM P2,.IONCH(IO) ;SUCCESS, SAVE NETWORK CHANNEL
JRST .POPJ1## ;SUCCESSFUL RETURN
;NTNIP -- INITIALIZE PASSIVE NETWORK CHANNEL
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<NOD>
; PUSHJ P,NTNIP
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <NOD> is the SIXBIT
;node name with whom communications are desired (or 0 (or "*") if any
;node is acceptable).
;
;The caller is responsible for setting such information as the source
;and/or destination process descriptors, and so forth.
;
;On error return, a network channel could not be established (e.g., not
;enough monitor resources, etc.), an error code in in M0.
;
;On normal return, a network channel has been assigned (and is returned
;in .IONCH) and is awaiting a "Connect Initiate" message.
;
;Note that NTNIP only requests a network logical link, it does not in any
;way ensure that anyone has connected to the logical link - a call to
;.NTNCW will "block" waiting for a connection.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNIP
INTERN NTNIP0, NTNIP1
.NTNIP: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNIP0: PUSHJ P,.SAVE4## ;PRESERVE A FEW ACS
NTNIP1: SKIPE .IONCH(IO) ;MAKE SURE CDB NOT ALREADY ACTIVE
STOPCD <NTNIP called with outstanding network channel>
MOVEM T2,.ION6M(IO) ;SET NODE NAME (SIXBIT) FOR INTEREST
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNE T1,IO.ANF ;ANF-STYLE NETWORK?
JRST NANIP1 ;YES
TXNE T1,IO.DCN ;DECNET-STYLE NETWORK?
JRST NDNIP1 ;YES
STOPCD <Neither ANF nor DECnet selected in NTNIP>
;HERE FOR ANF ENTER PASSIVE
NANIP1: CAME T2,['* '] ;EXPLICITLY WILD NODE?
CAIN T2,0 ;IMPLICITLY WILD NODE?
SETO T2, ;TSK.-STYLE WILD NODE!
MOVEM T2,.I1NSC+0(IO) ;SET NODE SPECIFIER IN TSK. ARG BLOCK
SKIPN .IONDF(IO) ;"DESTINATION" NPD IS REQUIRED
STOPCD <No destination NPD in NDNIP1>
;NOW SETUP TSK.-STYLE ARGUMENTS
PUSHJ P,NAS1I1 ;INITIALIZE FOR STRING WIZARDRY
STOPCD <NAS1I1 failed in NANIP1>
PUSHJ P,.XTYPO## ;SELECT BYTE TYPER
MOVEI P2,"*" ;DEFAULT HERE IS FULLY WILD
PUSHJ P,NAS2I1 ;SETUP SOURCE/DESTINATION NPDS
STOPCD <NAS2I1 failed in NANIP1>
MOVEI P2,"*" ;ACCEPT ANYTHING BY DEFAULT HERE TOO
PUSHJ P,NAS3I1 ;SETUP USER ID/ET AL
STOPCD <NAS3I1 failed in NANIP1>
SKIPL T1,.IONP3(IO) ;DID IT ALL FIT?
STOPCD <Strings too big in NANIP1>
HRRZM T1,.I1NSC+1(IO) ;SET TSK.-STYLE NPD BYTE COUNT
;NOW GET A TASK CHANNEL
MOVX M0,IO.NET!IO.ANF!IO.NEP;FLAG PASSIVE ANF-STYLE NETWORK CHANNEL
IORM M0,.IOCCF(IO) ;UPDATE CHANNEL CONTROL
PUSHJ P,NAS4I1 ;ASSIGN TSK: CHANNEL
POPJ P, ;ERROR
MOVX P1,.TKFEP ;FUNCTION: ENTER PASSIVE
MOVE T1,[4,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;ENTER PASSIVE CONNECT WAIT
JRST NACIE1 ;PROCESS TSK. CONNECT ERROR
;ALL DONE HERE
JRST .POPJ1## ;RETURN AWAITING A CONNECTION
;HERE FOR DECNET-STYLE ENTER PASSIVE
NDNIP1: MOVE P3,[6,,.IONNM] ;8-BIT POINTER
PUSHJ P,N6TO8 ;CONVERT TO 8-BIT NODE NAME
STOPCD <Node name N6TO8 failed in NTNIP>
HRLI P3,$NTNBL ;SELECT MAXIMUM NAME BLOCK LENGTH
MOVSM P3,.IONNM(IO) ;SET BYTE,,WORD COUNTER IN NAME BLOCK
;COMMON CODE TO SETUP THE NSP. ARGUMENTS
PUSHJ P,NDS1I1 ;INITIALIZE THE NSP. ARG BLOCK
STOPCD <NDS1I1 failed in NDNIP1>
;"QUEUE" THE REQUEST WITH NETWORK SERVICES VIA THE MONITOR
MOVX M0,IO.NET!IO.DCN;THE "NETWORK-BASED COMMUNICATIONS" BIT
IORM M0,.IOCCF(IO) ;SET IN THE CDB
XMOVEI P3,.I1NSC(IO) ;NSP. CONNECT BLOCK ADDRESS
SETZ P2, ;NO CHANNEL YET
MOVE P1,[.NSFEP,,.NSAA1+1] ;"ENTER PASSIVE" FUNCTION
TXO P1,NS.WAI ;*** IT STILL DOESN'T WORK!!!!!!!!!
XMOVEI M0,P1 ;NSP. ARG BLOCK TO
NSP. M0, ;ASK FOR A PASSIVE NETWORK CHANNEL
JRST NDCIE1 ;PROCESS NSP CONNECT ERROR
HRRZM P2,.IONCH(IO) ;SUCCESS, SAVE NETWORK CHANNEL
MOVX P1,IO.NET!IO.NEP;"PASSIVE NETWORK COMMUNICATIONS" BITS
IORM P1,.IOCCF(IO) ;ADJUST THE CDB ACCORDINGLY
JRST .POPJ1## ;SUCCESSFUL RETURN
;RANDOM SUBROUTINES FOR ENTER ACTIVE/PASSIVE
;As ANF-10 basically doesn't support any of the "wonderous" errata of
;DECnet such as user-id, password, ad nauseum, the TSK. monitor call
;was invented to give the user fuller control over the network logical
;link. In particular, in conjunction with versions 3 and later of the
;DECnet Compatible Port (in the DN8x), the "network process descriptor"
;was made available to the "user" in order to encode all that stuff in
;such a way that the DCP can convert it into something the DECnet side
;understood. The result is a very arcane NPD string (for which honesty
;requires that I not claim any credit) given to the TSK. in the active
;and passive init functions. The form of that NPD string, for the first
;time anywhere ever put in writing, is:
;
; <0> ;leading null byte
; DST ;"destination" process identifier
; <0> ;punctuation byte
; SRC ;"source" process identifier
; <0> ;punctuation byte
; USERID ;user id string
; <0> ;punctuation byte
; PASSWORD ;password string for user id
; <0> ;punctuation byte
; ACCOUNT ;account string for user id
; <0> ;punctuation byte
; OPTDATA ;"optional user data" a la DECnet connect init
; <0> ;punctuation byte
;
;DST and SRC both are one of the following forms:
;
; OBJ ;format 0: DECnet object type
; OBJ.NAM ;format 1: DECnet object type and task name
; ; note the "." punctuation character
; OBJ.[P,PN]NAM ;format 2: DECnet object type, user ppn and name
; ; note the ".", "[" and "]" punctuation
;
;OBJ is the object type as an ASCII octal number - e.g., "21" for DAP.
;NAM, USERID, PASSWORD, ACCOUNT, and OPTDATA are all "ASCII" character
;strings - i.e., 7-bit bytes (with no nulls).
;NAS1I1 - INITIALIZE FOR STRING MAGIC
NAS1I1: MOVE P3,[XWD <<.NSCUD+.NSDPN+.NSDPN>*5>,.I1NSC+2]
PUSHJ P,NP3P4 ;SET BYTE COUNTER AND POINTER
STOPCD <NP3P4 failed in NAS1I1>
MOVSI T1,(POINT 7,(IO)) ;TSK. USES 7-BIT BYTES
HLLM T1,.IONP4(IO) ;SO OVERRIDE .IONP4
XMOVEI T1,NTYPO ;BYTE TYPER
JRST .POPJ1## ;RETURN
;NAS2I1 - ENCODE SOURCE AND DESTINATION "NPD"S
NAS2I1: XMOVEI P1,.IONDF(IO) ;ADDRESS DESTINATION NPD FIELDS
PUSHJ P,NAS1N0 ;ENCODE ONE "NPD"
STOPCD <NAS1N0 failed in NAS2I1>
XMOVEI P1,.IONSF(IO) ;ADDRESS SOURCE NPD FIELDS
PUSHJ P,NAS1N0 ;ENCODE ONE MORE "NPD"
STOPCD <NAS1N0 failed in NAS2I1>
JRST .POPJ1## ;SUCCESSFUL SO FAR
;NAS3I1 - ENCODE USER ID, PASSWORD, ACCOUNT STRING, OPTIONAL DATA
NAS3I1: XMOVEI P1,.IONUS(IO) ;ADDRESS OF USER ID STRING BLOCK
PUSHJ P,NAS8S0 ;ENCODE USER ID STRING
STOPCD <NAS8S0 - user id - failed in NAS3I1>
XMOVEI P1,.IONPW(IO) ;ADDRESS OF PASSWORD STRING BLOCK
PUSHJ P,NAS8S0 ;ENCODE PASSWORD STRING
STOPCD <NAS8S0 - password - failed in NAS3I1>
XMOVEI P1,.IONAC(IO) ;ADDRESS OF ACCOUNT STRING BLOCK
PUSHJ P,NAS8S0 ;ENCODE ACCOUNT STRING
STOPCD <NAS8S0 - account - failed in NAS3I1>
XMOVEI P1,.IONUD(IO) ;ADDRESS OF OPTIONAL DATA STRING BLOCK
PUSHJ P,NAS8S0 ;ENCODE OPTIONAL DATA
STOPCD <NAS8S0 - optional data - failed in NAS3I1>
PJRST NAS0B0 ;CAP OFF WITH A NULL
;NAS4I1 - GET TASK CHANNEL, SETUP FOR TSK.
;Note that ANF TSK: channels must be run UU.AIO (non-blocking) so that
;a "dummy" IN can be performed in order to kick the monitor into sending
;data requests to the "other" guy. If the dummy IN is not performed, then
;both sides end up "deadlocked" trying to send the initial DAP CONFIG
;message, with neither side having sent any data requests!
NAS4I1: MOVX P1,FO.ASC!.FOCRE;ASSIGN CHANNEL, CREATE CHANNEL
MOVX P2,UU.PHY!UU.AIO!UU.IBC!.IOBYT ;DEVIOS WORD
MOVSI P3,'TSK' ;DEVICE NAME IS TSK:
MOVSI P4,.IONOH(IO) ;OUTPUT RING HEADER ADDRESS
HRRI P4,.IONIH(IO) ;INPUT RING HEADER ADDRESS
MOVE T1,[4,,P1] ;FILOP. ARG POINTER TO
FILOP. T1, ;ASSIGN A TSK CHANNEL
JRST NAS4I9 ;FILOP. ERROR
LDB P2,[POINTR P1,FO.CHN] ;EXTRACT CHANNEL NUMBER RETURNED
MOVEM P2,.IONCH(IO) ;SAVE FOR POSTERITY
SETOM .I1NSP+0(IO) ;DUMMY SOURCE NPD NODE NUMBER
SETZM .I1NSP+1(IO) ;DUMMY SOURCE NPD PROCESS ID STRING
MOVEI P3,.I1NSP(IO) ;ADDRESS OF "SOURCE" NPD FOR TSK.
HRLI P3,3 ;LENGTH OF SAME
MOVEI P4,.I1NSC(IO) ;ADDRESS OF "DESTINATION" NPD FOR TSK.
HRLI P4,<.NSCUD+1+.NSDPN+1+.NSDPN+1> ;LENGTH OF SAME
JRST .POPJ1## ;SUCCESSFUL RETURN
;HERE WHEN FILOP. OPEN TSK: FAILS
NAS4I9: LDB P2,[POINTR P1,FO.CHN] ;EXTRACT CHANNEL NUMBER, IF ANY
CAIE P2,0 ;DID MONITOR ASSIGN US A CHANNEL?
RESDV. P2, ;YES (PROBABLY), STOMP IT
JFCL ;HO HUM
SETZ M0, ;NO ERROR CODE SELECTED YET
MOVE T2,T1 ;POSITION ERROR CODE
XMOVEI T4,NAS4IT ;AND ERROR CODE TRANSLATION TABLE
PUSHJ P,.CFIND## ;TRY TO MAP FILOP. ERROR
MOVEI T1,$EFTNA ;FALLBACK "TASK DEVICE NOT AVAILABLE"
MOVE M0,T1 ;POSITION ERROR CODE IN ERROR AC
POPJ P, ;ERROR RETURN
;FILOP. OPEN ERRORS
NAS4IT: $EFISU,,ERISU% ;ILLEGAL SEQUENCE OF UUOS
$EFILU,,ERILU% ;ILLEGAL FILOP. CALL
$EFNLI,,ERNLI% ;ILLEGAL NOT LOGGED IN
$EFENC,,ERENC% ;EXCEEDED NETWORK CAPACITY
$EFTNA,,ERTNA% ;TASK DEVICE NOT AVAILABLE
$EFNSN,,ERUNN% ;NO SUCH NODE NAME
$EFNPC,,ERNPC% ;NO PER-PROCESS SPACE AVAILABLE
$EFNFC,,ERNFC% ;NO FREE I/O CHANNELS
0 ;THAT ABOUT DOES IT
;NAS1N0 - ENCODE ONE "NPD"
NAS1N0: PUSHJ P,NAS0B0 ;START OFF WITH A NULL
JFCL ;CAN'T HAPPEN
NAS1N1: HRRZ T1,0(P1) ;OBJECT TYPE
JUMPE T1,[SKIPE T1,P2 ;NONE, SELECT DEFAULT
PUSHJ P,.TCHAR## ;OUTPUT DEFAULT, IF ANY
JRST .POPJ1##] ;THAT'S ALL FOR THIS NPD
XMOVEI T2,.TOCTW## ;OBJECT TYPE IS OUTPUT IS OCTAL
CAIN T1,-1 ;UNLESS -1,
XMOVEI T2,.TASTR## ;IN WHICH CASE OUTPUT IS "*"
PUSHJ P,0(T2) ;DO WHATEVER'S APPROPRIATE
HLRZ T1,0(P1) ;FORMAT TYPE
JUMPE T1,.POPJ1## ;0 = OBJECT TYPE ONLY
SOJE T1,NASIN3 ;1 = OBJECT TYPE AND NAME
SOJE T1,NASIN5 ;2 = OBJECT TYPE, PPN, AND NAME
STOPCD <Illegal format type in NASIN1>
;HERE FOR FORMAT 1 - OBJ.NAM
NASIN3: PUSHJ P,.TDOT## ;SEPARATE OBJECT TYPE AND NAME
ADDI P1,.IONSN-.IONSF;RELOCATE P1 TO NAME STRING BLOCK ADDRESS
JRST NAS8S1 ;COPY NAME STRING
;HERE FOR FORMAT 2 - OBJ.[P,PN]NAM
NASIN5: PUSHJ P,.TDOT## ;SEPARATE OBJECT TYPE AND PPN/NAME
ADDI P1,.IONSP-.IONSF;RELOCATE P1 TO PPN
MOVE T1,0(P1) ;FETCH USER PPN
PUSHJ P,.TPPNW## ;AND TYPE IT OUT AS "[P,PN]"
ADDI P1,.IONSN-.IONSP;RELOCATE P1 TO NAME STRING BLOCK ADDRESS
JRST NAS8S1 ;COPY NAME STRING
;NAS8S0 - COPY 8-BIT STRING BLOCK
NAS8S0: PUSHJ P,NAS0B0 ;START OFF WITH A NULL
JFCL ;CAN'T HAPPEN
NAS8S1: HLRZ T4,0(P1) ;GET ACTUAL BYTE COUNT
JUMPE T4,[SKIPE T1,P2 ;NONE, SELECT DEFAULT NAME
PUSHJ P,.TCHAR## ;ISSUE DEFAULT NAME
JRST .POPJ1##] ;AND THAT'S THAT
MOVE T3,[POINT 8,1(P1)] ;BYTE POINTER TO 8-BIT NAME STRING
NAS8S4: ILDB T1,T3 ;GET NEXT NAME CHARACTER
CAIE T1,0 ;COMPRESS OUT NULLS
PUSHJ P,.TCHAR## ;ISSUE ONE MORE CHARACTER
SOJG T4,NAS8S4 ;LOOP FOR WHOLE NAME
JRST .POPJ1## ;SUCCESSFUL RETURN
;NAS0B0 - OUTPUT NULL BYTE
NAS0B0: SETZ T1, ;A NULL BYTE
NAS0B1: PUSHJ P,NTYPO ;ISSUE ONE CHARACTER
JRST .POPJ1## ;SUCCESSFUL RETURN ALWAYS
;NDS1I1 - SETUP FOR DECNET NSP. ENTER ACTIVE OR PASSIVE
;SETUP THE SOURCE PROCESS DESCRIPTOR BLOCK
NDS1I1: MOVEI P1,.NSDPN+1 ;LENGTH OF PROCESS DESCRIPTOR BLOCK
MOVEM P1,.I1NSS+.NSDFL(IO) ;SET IN PROCESS BLOCK
MOVE P1,.IONSF(IO) ;SOURCE FORMAT,,OBJECT TYPE
HLREM P1,.I1NSS+.NSDFM(IO) ;SET FORMAT TYPE IN PROCESS BLOCK
HRREM P1,.I1NSS+.NSDOB(IO) ;SET OBJECT TYPE IN PROCESS BLOCK
MOVE P1,.IONSP(IO) ;SOURCE "PPN"
MOVEM P1,.I1NSS+.NSDPP(IO) ;SET IN PROCESS BLOCK
XMOVEI P1,.IONSN(IO) ;SOURCE NAME BLOCK ADDRESS
MOVEM P1,.I1NSS+.NSDPN(IO) ;SET IN SOURCE PROCESS BLOCK
MOVEI M0,$NTNBL ;LENGTH OF A NAME BLOCK
HRRM M0,@P1 ;SET WORD COUNT OF SOURCE TASK NAME
;SETUP THE DESTINATION PROCESS DESCRIPTOR BLOCK
NDS1I3: MOVEI P1,.NSDPN+1 ;LENGTH OF PROCESS DESCRIPTOR BLOCK
MOVEM P1,.I1NSD+.NSDFL(IO) ;SET IN PROCESS BLOCK
MOVE P1,.IONDF(IO) ;DESTINATION FORMAT,,OBJECT TYPE
HLREM P1,.I1NSD+.NSDFM(IO) ;SET FORMAT TYPE IN PROCESS BLOCK
HRREM P1,.I1NSD+.NSDOB(IO) ;SET OBJECT TYPE IN PROCESS BLOCK
MOVE P1,.IONDP(IO) ;DESTINATION "PPN"
MOVEM P1,.I1NSD+.NSDPP(IO) ;SET IN PROCESS BLOCK
XMOVEI P1,.IONDN(IO) ;DESTINATION NAME BLOCK ADDRESS
MOVEM P1,.I1NSD+.NSDPN(IO) ;SET IN DESTINATION PROCESS BLOCK
MOVEI M0,$NTNBL ;LENGTH OF A NAME BLOCK
HRRM M0,@P1 ;SET WORD COUNT OF DESTINATION TASK NAME
;SETUP NSP. CONNECT BLOCK POINTERS
NDS1I5: MOVEI P1,.NSCUD+1 ;LENGTH OF CONNECT BLOCK
MOVEM P1,.I1NSC+.NSCNL(IO) ;SET CONNECT BLOCK LENGTH (WORDS)
XMOVEI P1,.IONNM(IO) ;NODE NAME ADDRESS
MOVEM P1,.I1NSC+.NSCND(IO) ;SET IN CONNECT BLOCK
XMOVEI P1,.I1NSS(IO) ;SOURCE PROCESS BLOCK ADDRESS
MOVEM P1,.I1NSC+.NSCSD(IO) ;SET IN CONNECT BLOCK
XMOVEI P1,.I1NSD(IO) ;DESTINATION PROCESS BLOCK ADDRESS
MOVEM P1,.I1NSC+.NSCDD(IO) ;SET IN CONNECT BLOCK
MOVEI M0,$NTSBL ;MAXIMUM "STRING BLOCK ADDRESS"
XMOVEI P1,.IONUS(IO) ;USER ID ADDRESS
MOVEM P1,.I1NSC+.NSCUS(IO) ;SET IN CONNECT BLOCK
HRRM M0,@P1 ;SET STRING BLOCK WORD COUNT
XMOVEI P1,.IONPW(IO) ;USER PASSWORD ADDRESS
MOVEM P1,.I1NSC+.NSCPW(IO) ;SET IN CONNECT BLOCK
HRRM M0,@P1 ;SET STRING BLOCK WORD COUNT
XMOVEI P1,.IONAC(IO) ;USER ACCOUNT DATA ADDRESS
MOVEM P1,.I1NSC+.NSCAC(IO) ;SET IN CONNECT BLOCK
HRRM M0,@P1 ;SET STRING BLOCK WORD COUNT
XMOVEI P1,.IONUD(IO) ;USER DATA ADDRESS
MOVEM P1,.I1NSC+.NSCUD(IO) ;SET IN CONNECT BLOCK
HRRM M0,@P1 ;SET STRING BLOCK WORD COUNT
JRST .POPJ1## ;RETURN HAPPILY
;NTNCW -- WAIT FOR CONNECT CONFIRM/CONNECT INITIATE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,NTNCW
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network died (channel aborted), error code is returned
;in M0.
;
;On normal return, an active channel has successfully connected to a
;remote network process, or a passive channel has received a "Connect
;Initiate" request and must either accept or reject it.
;
;The connect block is filled in accordingly.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNCW
INTERN NTNCW0, NTNCW1
.NTNCW: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNCW0: PUSHJ P,.SAVE4## ;SAVE THE P'S
NTNCW1: SKIPN P2,.IONCH(IO) ;NETWORK CHANNEL
STOPCD <No network channel in NTNCW>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANCW1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNCW1 ;YES
STOPCD <Neither ANF nor DECnet in NTNCW>
;HERE FOR ANF CONNECT WAIT
NANCW1: MOVX P1,.TKFWT ;FUNCTION: WAIT FOR CONNECT EVENT
MOVE T1,[2,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;WAIT FOR A CONNECT EVENT
JRST NACIE1 ;PROCESS TSK. CONNECT ERROR
;LINK IS UP AND ACTIVE, READ IN TSKSER'S NPD
NANCW3: MOVEI P4,.I1NSC(IO) ;ADDRESS OF OUR TSK. NPD BLOCK
HRLI P4,<.NSCUD+1+.NSDPN+1+.NSDPN+1> ;LENGTH OF SAME
SETZ P3, ;NO SOURCE WANTED
MOVX P1,.TKFRS ;FUNCTION: READ STATUS
MOVE T1,[4,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;READ IN STATUS AND NPD STRING
JRST NACIE1 ;PROCESS TSK. CONNECT ERROR
CAIN P3,.TKSOK ;IS THE LINK ESTABLISHED AND "RUNNING"
JRST NANCW5 ;YES
PUSHJ P,NTZAP0 ;*** NO, GET RID OF IT
JFCL ;*** HO HUM
MOVEI M0,$EFURO ;*** ASSUME "NO FILE SERVICE" FOR NOW
POPJ P, ;*** NO LINK
;SET NODE NAME FOR INTERESTED PARTIES
NANCW5: MOVE T3,.I1NSC(IO) ;RETURNED NODE NAME (OCTAL)
PUSHJ P,.NDNAM## ;TRY TO MAKE A PRINTABLE NAME OUT OF IT
MOVEM T1,.ION6M(IO) ;SAVE IN CASE ANYONE IS INTERESTED
;DO A "DUMMY" IN TO TRICK MONITOR INTO SENDING DATA REQUESTS
NANCW6: MOVS T2,.IONCH(IO) ;NETWORK TSK CHANNEL NUMBER
HRRI T2,.FOINP ;FUNCTION: INPUT
MOVE T1,[1,,T2] ;FILOP. ARG POINTER TO
FILOP. T1, ;EXECUTE A "DUMMY" IN (IT MIGHT EVEN WORK!)
JFCL ;IGNORE ERRORS HERE, CATCH 'EM LATER
;ALL DONE IF AN "ACTIVE" LINK, GRUNDGE IF A PASSIVE ONE
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN T1,IO.NEP ;ACTIVE OR PASSIVE?
JRST .POPJ1## ;ACTIVE (DCP RETURNS USELESS NPD)
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;PASSIVE LINK, DECODE THE NPD "CONNECT" INFORMATION
NANCW7: MOVE P3,.I1NSC+1(IO) ;RETURNED NPD BYTE COUNT
MOVE P4,[POINT 7,.I1NSC+2(IO)] ;POINTER TO RETURNED NPD STRING
PUSHJ P,NAS0R0 ;READ IN FIRST BYTE
CAIE T1,0 ;MUST BE A NULL
STOPCD <Junk returned NPD in NANCW5>
XMOVEI P1,.IONDF(IO) ;ADDRESS OF "DESTINATION" NPD STUFF
PUSHJ P,NAS3R0 ;DECODE DESTINATION INFO
STOPCD <NAS3R0 (dest) failed in NANCW5>
XMOVEI P1,.IONSF(IO) ;ADDRESS OF "SOURCE" NPD STUFF
PUSHJ P,NAS3R0 ;DECODE SOURCE INFO
STOPCD <NAS3R0 (source) failed in NANCW5>
XMOVEI P1,.IONUS(IO) ;ADDRESS OF USER ID STRING BLOCK
PUSHJ P,NAS2R0 ;DECODE USER ID
STOPCD <NAS2R0 (userid) failed in NANCW5>
XMOVEI P1,.IONPW(IO) ;ADDRESS OF PASSWORD STRING BLOCK
PUSHJ P,NAS2R0 ;DECODE PASSWORD
STOPCD <NAS2R0 (password) failed in NANCW5>
XMOVEI P1,.IONAC(IO) ;ADDRESS OF ACCOUNT STRING BLOCK
PUSHJ P,NAS2R0 ;DECODE ACCOUNT STRING
STOPCD <NAS2R0 (account) failed in NANCW5>
XMOVEI P1,.IONUD(IO) ;ADDRESS OF USER DATA STRING BLOCK
PUSHJ P,NAS2R0 ;DECODE USER DATA
STOPCD <NAS2R0 (usrdata) failed in NANCW5>
;ALL CONNECT INFO RETURNED
JRST .POPJ1## ;RETURN SUCCESSFULLY
;HERE FOR DECNET CONNECT WAIT
NDNCW1: TXNE T1,IO.NEP ;NETWORK PASSIVE CHANNEL?
JRST NDNCW3 ;YES
;HERE TO WAIT FOR ACTIVE LINK TO BE READY
XMOVEI P3,.IONUD(IO) ;OPTIONAL CONNECT CONFIRM DATA BLOCK ADDRESS
MOVEI M0,$NTSBL ;MAXIMUM "STRING BLOCK LENGTH"
HRRM M0,@P3 ;SET DATA BLOCK MAXIMUM WORD COUNT
MOVE P1,[NS.WAI!<.NSFRC,,.NSAA1+1>] ;READ CONNECT INFO
XMOVEI M0,P1 ;ADDRESS OF NSP. ARG BLOCK TO
NSP. M0, ;READ CONNECT CONFIRM DATA, WAIT IF NEEDED
JRST NDCXE1 ;FAILED
LDB P2,[POINTR P2,NS.STA] ;GET CURRENT LINK STATE
CAIN P2,.NSSRN ;LINK STATE READY?
JRST .POPJ1## ;YES, LINK IS UP AND RUNNING, ALL SET THEN
MOVEI M0,NSRBO% ;ASSUME CONNECT REJECTED
CAIN P1,.NSSDR ;"DISCONNECT RECEIVED"?
JRST NDCXE1 ;PROCESS "NSP. ERROR"
STOPCD <Funny state in active NDNCW>
;HERE TO WAIT FOR PASSIVE LINK TO BE READY
;
;ASSUMES CONNECT BLOCK IS CORRECTLY SETUP BY NTNIP
NDNCW3: XMOVEI P3,.I1NSC(IO) ;CONNECT BLOCK ADDRESS
MOVE P1,[NS.WAI!<.NSFRI,,.NSAA1+1>] ;READ CONNECT INIT ARGUMENT
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;READ CONNECT INIT DATA
JRST NDCXE1 ;FAILED
PUSHJ P,TSAV12## ;SAVE T2
MOVEI P4,.IONNM ;8-BIT NODE NAME OFFSET
PUSHJ P,N8TO6 ;MAKE A 6-BIT NAME OUT OF IT
JFCL ;DUH?
MOVEM T2,.ION6M(IO) ;SET 6-BIT NAME FOR INTERESTED PARTIES
JRST .POPJ1## ;RETURN WITH PASSIVE CONNECTION READY
;ANF SUBROUTINES FOR NANCW
;NAS0R0 - READ NEXT NPD BYTE
NAS0R0: SOSGE P3 ;ANY MORE DATA?
TDZA T1,T1 ;NO, RETURN A NULL
ILDB T1,P4 ;YES, RETURN NEXT NPD BYTE
POPJ P, ;RETURN
;NAS0R3 - READ OCTAL NPD SUBSTRING
NAS0R3: SETZ T2, ;INITIALIZE OCTAL VALUE
NAS0R4: PUSHJ P,NAS0R0 ;READ NEXT BYTE
CAIL T1,"0" ;IS IT OCTAL?
CAILE T1,"7" ; . . .
POPJ P, ;NO, END OF SUBSTRING
LSH T1,^D33 ;YES, POSITION AND
ROTC T1,^D03 ;ACCUMULATE OCTAL OBJECT TYPE
JRST NAS0R4 ;READ IN REST OF OBJECT TYPE
;NAS2R0 - READ STRING
NAS2R0: SETZ T3, ;INITIALIZE ACTUAL BYTE COUNTER
MOVE T4,[POINT 8,1(P1)] ;AND BYTE POINTER
NAS2R1: PUSHJ P,NAS0R0 ;READ NEXT BYTE
JUMPE T1,NAS2R3 ;NULL TERMINATES STRING
IDPB T1,T4 ;ACCUMULATE STRING
AOJA T3,NAS2R1 ;AND COUNT IT UP
NAS2R3: HRLM T3,0(P1) ;STORE ACTUAL BYTE COUNT
JRST .POPJ1## ;SUCCESSFUL RETURN
;NAS3R0 - READ ENCODED NPD STRING
NAS3R0: PUSHJ P,NAS0R3 ;READ IN OCTAL SUBSTRING
HRRZM T2,0(P1) ;ASSUME FORMAT = 0; OBJECT TYPE RETURNED
JUMPE T1,.POPJ1## ;IF FORMAT 0 THEN ALL DONE
CAIE T1,"." ;ELSE MUST HAVE PUNCTUATION HERE
STOPCD <Junk encoded NPD string in NAS3R3>
MOVE T2,P4 ;PRESERVE COPY OF BYTE POINTER
PUSHJ P,NAS0R0 ;READ FIRST "NAME" STRING CHARACTER
CAIN T1,"[" ;LOOK LIKE A PPN?
JRST NAS3R5 ;YUP, MUST BE FORMAT 2
;FORMAT 1, SIMPLE NAME
NAS3R3: MOVEI T1,1 ;TASK NAME COMING UP, FORMAT TYPE 1
HRLM T1,0(P1) ;SET NEW FORMAT TYPE
ADDI P1,.IONDN-.IONDF;SET P1 TO TASK NAME STRING BLOCK
MOVE P4,T2 ;RESTORE BYTE POINTER TO FIRST NAME CHAR
AOJA P3,NAS2R0 ;AND READ NAME STRING
;FORMAT 2 - PPN AND NAME
NAS3R5: ADDI P1,.IONDP-.IONDF;RELOCATE P1 TO PPN WORD
PUSHJ P,NAS0R3 ;READ IN OCTAL SUBSTRING (PROJECT)
CAIE T2,0 ;MUST NOT BE BLANK
CAIE T1,"," ;AND MUST BE PROPERLY PUNCTUATED
STOPCD <Junk encoded project NPD string in NAS3R5>
HRLM T2,0(P1) ;STORE PROJECT NUMBER
PUSHJ P,NAS0R3 ;READ IN ANOTHER OCTAL SUBSTRING (PROGRAMMER)
CAIE T2,0 ;MUST NOT BE BLANK
CAIE T1,"]" ;AND MUST BE PROPERLY PUNCTUATED
STOPCD <Junk encoded programmer NPD string in NAS3R5>
HRRM T2,0(P1) ;STORE PROGRAMMER NUMBER
ADDI P1,.IONDN-.IONDP;RELOCATE P1 TO NAME STRING BLOCK
JRST NAS2R0 ;AND READ REMAINING NPD NAME STRING
;NTNCA -- PASSIVE CHANNEL CONNECT ACCEPT
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T3,<DAT>
; PUSHJ P,NTNCA
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <DAT> is the address
;of any optional connect data to be sent as part of the connect accept
;(must be 0 if no optional data).
;
;On error return the network aborted.
;
;On successful return the network channel is "up and running". Normal
;communications may take place.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNCA
INTERN NTNCA0, NTNCA1
.NTNCA: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNCA0: PUSHJ P,.SAVE4## ;SAVE SOME ACS
NTNCA1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNCA>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANCA1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNCA1 ;YES
STOPCD <Neither ANF nor DECnet in NTNCA>
;HERE FOR ANF CONNECT ACCEPT
NANCA1: JRST .POPJ1## ;CONFIRM FAIT ACCOMPLI
;HERE FOR DECNET CONNECT ACCEPT
NDNCA1: MOVE P3,T3 ;OPTIONAL USER CONNECT DATA
MOVE P1,[.NSFAC,,.NSAA1+1] ;"ACCEPT CONNECT" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;ACCEPT THE CONNECT INITIATE
JRST NDCXE1 ;FAILED, CLEAN UP
JRST .POPJ1## ;CHANNEL UP AND RUNNING
;NTNCR -- PASSIVE CHANNEL CONNECT REJECT
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<DAT>
; MOVX T3,<RSN>
; PUSHJ P,NTNCR
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; <RSN> is the NSP reason why
;the connection is being rejected; and <DAT> is the address
;of any optional connect data to be sent as part of the connect reject
;(must be 0 if no optional data).
;
;On error return the network aborted.
;
;On successful return the connect initiate has been rejected. The
;network channel has been aborted and released.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNCR
INTERN NTNCR0, NTNCR1
.NTNCR: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNCR0: PUSHJ P,.SAVE4## ;SAVE SOME ACS
NTNCR1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNCR>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANCR1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNCR1 ;YES
STOPCD <Neither ANF nor DECnet in NTNCR>
;HERE FOR ANF CONNECT REJECT
NANCR1: MOVEI P3,100(T3) ;POSITION "ABORT" CODE
MOVEI P1,.TKFEI ;FUNCTION: ENTER IDLE STATE (DISCONNECT)
MOVE M0,[3,,P1] ;TSK. ARG POINTER TO
TSK. M0, ;BREAK (SEND DISCONNECT) THE NET LINK
JRST NANAB1 ;ABORT THE LINK
PJRST NTNRL1 ;AND RELEASE THE TASK CHANNEL
; (CONSISTENT WITH SILLY DECNET NSP. UUO)
;HERE FOR DECNET CONNECT REJECT
NDNCR1: DMOVE P3,T2 ;OPTIONAL USER REJECT DATA, REASON
MOVE P1,[.NSFRJ,,.NSAA2+1] ;"REJECT CONNECT" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;REJECT THE CONNECT INITIATE
PJRST NTNRL1 ;HUH?? WE DON'T WANT IT!!!!!
PJRST NTFIN1 ;MARK NETWORK CHANNEL DEFUNCT
SUBTTL Network Link Control - Link management
;NTNRS -- RETURN NETWORK CHANNEL STATUS
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,NTNRS
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network died.
;
;On normal return the network status is returned in T2.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNRS
INTERN NTNRS0, NTNRS1
.NTNRS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNRS0: PUSHJ P,.SAVE4## ;NEED SOME ACS
NTNRS1: STOPCD <NTNRS called but not yet implemented>
SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNRS>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANRS1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNRS1 ;YES
STOPCD <Neither ANF nor DECnet in NTNRS>
;HERE FOR ANF RETURN STATUS
NANRS1: HALT
;HERE FOR DECNET RETURN STATUS
NDNRS1: MOVE P1,[.NSFRS,,.NSAA1+1] ;"READ STATE" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;READ NETWORK STATE
JRST NDRXE1 ;CONVERT ERROR CODE
MOVE T2,P3 ;RETURN STATE IN T2
HALT
;NTNSQ -- SET NETWORK CHANNEL QUOTA AND PERCENTAGES
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T2,<QTA>
; MOVX T3,<PCT>
; PUSHJ P,NTNSQ
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; <QTA> is the "link quota"
;for the current network channel; <PCT> is the relative percentage of
;the link quota to be devoted to input buffering (integer range 1 to 99).
;
;On error return the monitor would not accept the range specified; error
;code is in M0.
;
;On normal return the channel parameters have been set as requested.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNSQ
INTERN NTNSQ0, NTNSQ1
.NTNSQ: PUSHJ P,.SACIO## ;SWITCH TO IO CONTEXT
NTNSQ0: PUSHJ P,.SAVE4## ;SAVE THE P'S
NTNSQ1: SKIPN P2,.IONCH(IO) ;GET NETWORK CHANNEL
STOPCD <No network channel in NTNSQ>
MOVE T1,.IOCCF(IO) ;GET CHANNEL CONTROL FLAGS
TXNE T1,IO.ANF ;ANF NETWORK PROTOCOL?
JRST NANSQ1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK PROTOCOL?
JRST NDNSQ1 ;YES
STOPCD <Neither ANF nor DECnet in NTNSQ>
;HERE FOR ANF SET LINK QUOTAS
NANSQ1: JRST .POPJ1## ;SO MUCH FOR THAT
;HERE FOR DECNET SET LINK QUOTAS
NDNSQ1: MOVE P1,[.NSFSQ,,.NSAA2+1] ;NSP. FUNCTION WORD
SKIPG P3,T2 ;LINK QUOTA
SETO P3, ;NONE SPECIFIED
SKIPG P4,T3 ;RELATIVE PERCENT INPUT
SETO P4, ;NONE SPECIFIED
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;SET LINK QUOTA AND PERCENTAGE
JRST NDRXE1 ;FAILED?
JRST .POPJ1## ;SUCCESSFUL RETURN
SUBTTL Network Link Control - Link termination
;NTNSD -- NETWORK DISCONNECT
;CALL IS:
;
; MOVE T1,<CDB>
; MOVX T3,<DAT>
; PUSHJ P,NTNSD
; error return
; normal return
;
;Where <CDB> is the address of the I/O <CDB>; <RSN> is the NSP reason
;code for why the network link is disconnecting; and <DAT> is the address
;of any optional disconnect data to be sent as part of the disconnect
;process (must be 0 if no optional data).
;
;On error return the network died.
;
;On successful return the disconnect has been sent (but the network
;channel is still "active" and able to receive data sent by the other
;side).
;
;Uses T1, T2, T3, T4.
ENTRY .NTNSD
INTERN NTNSD0, NTNSD1
.NTNSD: PUSHJ P,.SACIO## ;SETUP I/O CDB ADDRESS
NTNSD0: PUSHJ P,.SAVE4## ;SAVE A FEW ACS
NTNSD1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNSD>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANSD1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNSD1 ;YES
STOPCD <Neither ANF nor DECnet in NTNSD>
;HERE FOR ANF SYNCHRONOUS DISCONNECT
NANSD1: MOVX P1,.TKFEI ;FUNCTION: ENTER "IDLE" STATE
MOVE T1,[2,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;SEND A DISCONNECT INITIATE
JRST NARXE1 ;CONVERT TSK. ERROR CODE
JRST .POPJ1## ;SUCCESSFUL
;HERE FOR DECNET SYNCHRONOUS DISCONNECT
NDNSD1: MOVE P3,T3 ;OPTIONAL USER DATA
MOVE P1,[.NSFSD,,.NSAA1+1] ;"SYCHRONOUS DISCONNECT" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;SEND DISCONNECT INITIATE
JRST NDRXE1 ;CONVERT ERROR CODE
JRST .POPJ1## ;SUCCESSFUL RETURN
;NTNAB -- NETWORK ABORT
;CALL IS:
;
; MOVE T1,<CDB>
; MOVX T3,<DAT>
; PUSHJ P,NTNAB
; error return
; normal return
;
;Where <CDB> is the address of the I/O <CDB>; <RSN> is the NSP reason
;code for aborting the network link; and <DAT> is the address
;of any optional disconnect data to be sent as part of the disconnect
;and abort process (must be 0 if no optional data).
;
;On error return the network died.
;
;On successful return the network channel has been aborted and
;released.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNAB
INTERN NTNAB0, NTNAB1
.NTNAB: PUSHJ P,.SACIO## ;SETUP I/O CDB ADDRESS
NTNAB0: PUSHJ P,.SAVE4## ;SAVE A FEW ACS
NTNAB1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNAB>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANAB1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNAB1 ;YES
STOPCD <Neither ANF nor DECnet in NTNAB>
;HERE FOR ANF ABORT
NANAB1: RESDV. P2, ;ZAPETH THE I/O CHANNEL DEAD
JFCL ;HUH?
PJRST NTFIN1 ;AND CLEAN OUT THE NETWORK DATABASE
;HERE FOR DECNET ABORT
NDNAB1: MOVE P3,T3 ;OPTIONAL USER DATA
MOVE P1,[.NSFAB,,.NSAA1+1] ;"ABORT" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;ABORT THE CHANNEL
PJRST NTNRL1 ;HUH?? BY DAMN, GET RID OF THE BLOODY THING
PJRST NTFIN1 ;MARK THE NETWORK CHANNEL DEFUNCT
;NTNRD -- READ DISCONNECT REASON AND OPTIONAL DATA
;CALL IS:
;
; MOVX T1,<CDB>
; MOVX T3,<ADR>
; PUSHJ P,NTNRD
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <ADR> is the address
;to receive any optional user disconnect data (returned in 8-bit format).
;
;The error return is taken if ???
;
;On normal return, any "Optional User Data" has been read into the
;specified string block in normal 8-bit format. The disconnect reason
;(as supplied by the network services) is returned in T2.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNRD
INTERN NTNRD0, NTNRD1
.NTNRD: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNRD0: PUSHJ P,.SAVE4## ;SAVE A FEW ACS
NTNRD1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNRD>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANRD1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNRD1 ;YES
STOPCD <Neither ANF nor DECnet in NTNRD>
;HERE FOR ANF READ DISCONNECT REASON
NANRD1: JRST .POPJ1## ;SO MUCH FOR THAT
;HERE FOR DECNET READ DISCONNECT REASON
NDNRD1: MOVE P3,T3 ;ADDRESS OF "STRING" BLOCK
MOVE P1,[.NSFRC,,.NSAA2+1] ;READ DISCONNECT DATA
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;READ OPTIONAL DISCONNECT DATA
JRST NDRXE1 ;CONVERT ERROR CODE
MOVE T2,P3 ;RETURN DISCONNECT REASON
JRST .POPJ1## ;SUCCESSFUL RETURN
;NTNRL -- RELEASE NETWORK CHANNEL
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,NTNRL
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;On error return the network died first.
;
;On normal return the network channel has been released.
;
;Uses T1, T2, T3, T4.
ENTRY .NTNRL
INTERN NTNRL0, NTNRL1
.NTNRL: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTNRL0: PUSHJ P,.SAVE4 ;SAVE SOME ACS
NTNRL1: SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTNRL>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NANRL1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDNRL1 ;YES
STOPCD <Neither ANF nor DECnet in NTNRL>
;HERE FOR ANF RELEASE
NANRL1: MOVS P1,P2 ;POSITION CHANNEL IN LH FOR FILOP.
HRRI P1,.FOREL ;FUNCTION: RELEASE
MOVE T1,[1,,P1] ;FILOP. ARG POINTER TO
FILOP. T1, ;RELEASE TSK CHANNEL
PJRST NTZAP1 ;*** HO HUM, JUST BLOW IT AWAY
PJRST NTFIN1 ;CLEAN OUT THE NETWORK DATABASE
;HERE FOR DECNET RELEASE
NDNRL1: MOVE P1,[.NSFRL,,.NSACH+1] ;"RELEASE CHANNEL" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;RELEASE THE CHANNEL
JRST NDRXE1 ;ERROR, CONVERT CODE
JRST NTFIN1 ;FINISH OFF THE NETWORK
;NTZAP -- ZAP A NETWORK CHANNEL
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,NTZAP
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB.
;
;NTZAP is used to unconditionally "ZAP" any network I/O in progress.
;If the CDB is not currently network-active, NTZAP simply returns. If
;any network activity is pending, it is thrown away, the network link
;(or channel if you prefer) is RELEASed/RESET, I/O buffers are de-al-
;located, and so on.
;
;NTZAP should be used as a unknown-state cleanup mechanism which doesn't
;care what happens, just as long as the CDB is cleaned up. Errors are
;suppressed.
;
;The error return is not utilized.
;
;On normal return, any network I/O has been RESET, buffers deallocated,
;and the CDB cleaned up (network-wise).
;
;Uses T1, T2, T3, T4.
ENTRY .NTZAP
INTERN NTZAP0, NTZAP1
.NTZAP: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
NTZAP0: PUSHJ P,.SAVE4## ;PRESERVE THE PRESERVED REGISTERS
NTZAP1: ;FEEL FREE TO TRASH THE TEMPS
SKIPN P2,.IONCH(IO) ;GOT A NETWORK CHANNEL IN USE?
PJRST NTFIN6 ;NO, JUST BLAST SOME BITS ON G.P.'S
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NAZAP1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDZAP1 ;YES
STOPCD <Neither ANF nor DECnet in NTZAP>
;HERE FOR ANF ZAP
NAZAP1: RESDV. P2, ;STOMPETH UPON WHATEVER IS THERE
JFCL ;WELL, I TRIED!
PJRST NTFIN1 ;CLEAN OUT THE NETWORK DATABASE
;HERE FOR DECNET ZAP
NDZAP1: MOVE P1,[.NSFRL,,.NSACH+1] ;"RELEASE CHANNEL" FUNCTION
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;RELEASE THE CHANNEL
JFCL ;WELL, I TRIED!
JRST NTFIN1 ;FINISH OFF THE NETWORK
SUBTTL Network Link Control - Support routines
;NTINI - COMMON ACTIVE/PASSIVE NETWORK COMMUNICATIONS INITIALIZATION
ENTRY .NTINI
INTERN NTINI0, NTINI1
.NTINI: PUSHJ P,.SACIO## ;SET UP I/O CDB INDEX
NTINI0: PUSHJ P,.SAVE4## ;SAVE THE P'S
NTINI1: PUSHJ P,TSAV14## ;SAVE THE T'S, ON G.P.S
SKIPN P2,.IONCH(IO) ;ASSURE NETWORK CHANNEL
STOPCD <No network channel in NTINI>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NAINI1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDINI1 ;YES
STOPCD <Neither ANF nor DECnet in NTINI>
;HERE FOR ANF INITIALIZATION
NAINI1: TXNE T1,IO.NBA ;NETWORK BUFFERS ALLOCATED?
STOPCD <IO.NBA in NAINI1>
;ALLOCATE NETWORK INPUT AND OUTPUT BUFFERS
NAINI2: MOVEI P1,.TKFRX ;FUNCTION: READ STATUS AND MESSAGE SIZES
SETZB P3,P4 ;JUST TO MAKE SURE . . .
MOVE T1,[4,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;READ STATE OF TASK CHANNEL
JRST [MOVEI P1,.TKFRS ;FUNCTION: READ STATUS
MOVE T1,[3,,P1] ;TSK. ARG POINTER TO
TSK. T1, ;READ STATE OF TASK CHANNEL
STOPCD <TSK. (.TKFRS) failed in NAINI2>
MOVEI P4,$NABFS ;FAKE UP A DEFAULT SEGMENT SIZE
JRST .+1] ;CONTINUE ONWARDS
CAIE P3,.TKSOK ;IS THE LINK "UP AND RUNNING"?
JRST [CAIE P3,.TKSID ;"IDLE" (RECEIVED DISCONNECT)?
STOPCD <Network link status not "RUNNING" in NAINI>
JRST NARXS1] ;TRANSLATE DISCONNECT REASON
ANDI P4,-1 ;WANT JUST MESSAGE LENGTH (IGNORE RLN FIELD)
MOVEM P4,.IONLB(IO) ;SET NETWORK BUFFER SIZE (8-BIT BYTES)
MOVEM P4,.IONLM(IO) ;WHICH IS ALSO PRELIMINARY MAXIMUM MESSAGE SIZE
ADDI P4,3 ;ROUND UP, AND
LSH P4,-2 ;TRUNCATE TO -10 WORD COUNT
MOVEM P4,.IONLW(IO) ;SET NETWORK BUFFER SIZE (-10 WORDS)
MOVSI T2,$NAIBF ;NUMBER OF INPUT BUFFERS TO USE
HRRI T2,$NAIBX(P4) ;SIZE OF INDIVIDUAL INPUT BUFFER
XMOVEI T4,.IONIH(IO) ;ADDRESS OF INPUT BUFFER RING HEADER
PUSHJ P,IOBFA1## ;ALLOCATE INPUT BUFFERS
STOPCD <Can't allocate ANF input buffer(s)>
DMOVEM T2,.IONIB(IO) ;SAVE BUFFER ID FOR DEALLOCATION
MOVSI T2,1 ;ALWAYS USE ONE OUTPUT BUFFER (IT'S A LONG
; STORY, THAT'S JUST THE WAY TOPS10 WORKS)
HRR T2,P4 ;SIZE OF INDIVIDUAL OUTPUT BUFFER
XMOVEI T4,.IONOH(IO) ;ADDRESS OF OUTPUT BUFFER RING HEADER
PUSHJ P,IOBFA1## ;ALLOCATE OUTPUT BUFFERS
STOPCD <Can't allocate ANF output buffer(s)>
DMOVEM T2,.IONOB(IO) ;SAVE BUFFER ID FOR DEALLOCATION
MOVX T1,BF.IBC ;THE INHIBIT-BUFFER-CLEARING BIT
IORM T1,.IONOH(IO) ;LEAVE MY BUFFER ALONE!!!
MOVX T1,IO.NBA ;THE NETWORK-BUFFERS-ALLOCATED BIT
IORM T1,.IOCCF(IO) ;SET IN CDB
MOVX T1,NS.EOM ;THE END-OF-MESSAGE FLAG
MOVEM T1,.IONIS(IO) ;PRESET FOR RNMSG
JRST .POPJ1## ;READY FOR ANF NETWORK I/O
;HERE FOR DECNET INITIALIZATION
NDINI1: TXNE T1,IO.NBA ;NETWORK BUFFERS ALLOCATED?
JRST NDINI6 ;YES, JUST RESET COUNTERS
;ALLOCATE NETWORK INPUT AND OUTPUT BUFFERS
NDINI2: MOVE P1,[.NSFRS,,.NSAA2+1] ;RETURN STATUS FUNCTION
SETZB P3,P4 ;ON G.P.'S
XMOVEI M0,P1 ;NSP. ARG POINTER TO
NSP. M0, ;READ NETWORK MESSAGE SEGMENT SIZE
JRST NDRXE1 ;OOPS
LDB T1,[POINTR P2,NS.STA] ;EXTRACT THE LINK STATE
CAIE T1,.NSSRN ;LINK HAD BETTER BE "RUNNING" AT THIS POINT
STOPCD <Network link status not "RUNNING" in NDINI>
MOVEM P3,.IONLB(IO) ;SET NETWORK BUFFER SIZE (8-BIT BYTES)
MOVEM P3,.IONLM(IO) ;WHICH IS ALSO PRELIMINARY MAXIMUM MESSAGE SIZE
ADDI P3,3 ;ROUND UP, AND
LSH P3,-2 ;TRUNCATE TO -10 WORD COUNT
MOVEM P3,.IONLW(IO) ;SET NETWORK BUFFER SIZE (-10 WORDS)
MOVE T1,P3 ;NETWORK BUFFER LENGTH (-10 WORDS)
LSH T1,1 ;ONE INPUT, AND ONE OUTPUT BUFFER
SKIPN T2,.IOXFF(IO) ;DOES THE CDB HAVE ANY EXTRA SPACE?
JRST NDINI3 ;NO, MUST ALLOCATE FROM MANAGED MEMORY
ADD T2,T1 ;YES, T2:=PROPOSED NEW .IOXFF
CAML T2,.IOXSZ(IO) ;WILL THE TWO BUFFERS FIT?
JRST NDINI3 ;NO, MUST ALLOCATE FROM MANAGED MEMORY
EXCH T2,.IOXFF(IO) ;YES, GLOM ONTO IT
ADD T2,IO ;RELOCATE INTO PHYSICAL (RELATIVELY) MEMORY
JRST NDINI4 ;SET ADDRESS(S)
;ALLOCATE BUFFERS FROM MANAGED MEMORY
NDINI3: PUSHJ P,.MMGWD## ;ALLOCATE SOME MANAGED MEMORY
STOPCD <Network buffer memory allocation failed in NDINI3>
NDINI4: SETZM (T2) ;CLEAR START OF BUFFER
HRLZ M0,T2 ;CONCOCT A
HRRI M0,1(T2) ; BLT POINTER TO
MOVE T1,.IONLW(IO) ;LENGTH OF ONE BUFFER (-10 WORDS)
LSH T1,1 ;ALLOW FOR TWO BUFFERS
ADD T1,T2 ;T1:=END (+1) OF NETWORK BUFFERS
BLT M0,-1(T1) ;CLEAR NETWORK BUFFERS
MOVEM T2,.IONIB(IO) ;SET ADDRESS OF NETWORK INPUT BUFFER
ADD T2,.IONLW(IO) ;OFFSET TO NEXT BUFFER
MOVEM T2,.IONOB(IO) ;WHICH BECOMES THE NETWORK OUTPUT BUFFER
MOVX T1,IO.NBA ;THE NETWORK-BUFFERS-ALLOCATED BIT
IORM T1,.IOCCF(IO) ;SET IN THE CDB
NDINI6: MOVX T1,NS.EOM ;END-OF-MESSAGE-SEEN FLAG
MOVEM T1,.IONIS(IO) ;PRESET TO KEEP RNMSG HAPPY
SETZM .IONIC(IO) ;CURRENTLY HAVE NO INPUT DATA BYTES
PJRST XDBUF6 ;SETUP OUTPUT BUFFER COUNTER/POINTER
;NTFIN - FINISH OFF THE NETWORK CHANNEL
ENTRY .NTFIN
INTERN NTFIN0, NTFIN1
.NTFIN: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
NTFIN0: PUSHJ P,.SAVE4## ;PROTECT THE P'S
NTFIN1: MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
SETZM .IONCH(IO) ;NOTE NO MORE CHANNEL
SETZM .ION6M(IO) ; . . .
TXNE T1,IO.ANF ;ANF NETWORK CHANNEL?
JRST NAFIN1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK CHANNEL?
JRST NDFIN1 ;YES
STOPCD <Neither ANF nor DECnet in NTFIN>
;HERE FOR ANF CLEANUP
NAFIN1: TXNN T1,IO.NBA ;NETWORK BUFFERS ALLOCATED?
JRST NAFIN6 ;NO, NOTHING TO DEALLOCATE
DMOVE T2,.IONOB(IO) ;OUTPUT BUFFER ID
XMOVEI T4,.IONOH(IO) ;ADDRESS OF OUTPUT BUFFER RING HEADER
PUSHJ P,IOBFZ1## ;DEALLOCATE THE OUTPUT BUFFERS
STOPCD <Can't deallocate ANF output buffer(s)>
DMOVE T2,.IONIB(IO) ;INPUT BUFFER ID
XMOVEI T4,.IONIH(IO) ;ADDRESS OF INPUT BUFFER RING HEADER
PUSHJ P,IOBFZ1## ;DEALLOCATE THE INPUT BUFFERS
STOPCD <Can't deallocate ANF input buffer(s)>
NAFIN6: PJRST NTFIN6 ;FINAL CLEAN UP
;HERE FOR DECNET CLEANUP
NDFIN1: TXNN T1,IO.NBA ;NETWORK BUFFERS ALLOCATED?
JRST NDFIN6 ;NO, NOTHING TO DEALLOCATE
SKIPLE T2,.IONIB(IO) ;ADDRESS OF NETWORK INPUT BUFFER
CAIGE T2,.JBDA ;REASONABLE ADDRESS?
STOPCD <Network input buffer trashed in NDFIN1>
SKIPLE T3,.IONOB(IO) ;ADDRESS OF NETWORK OUTPUT BUFFER
CAIGE T2,.JBDA ;REASONABLE ADDRESS?
STOPCD <Network output buffer trashed in NDFIN1>
SUB T3,.IONLW(IO) ;BACK UP ONE BUFFERS' WORTH
CAMN T2,T3 ;ARE THE TWO BUFFERS ADJACENT?
JRST NDFIN3 ;YES
;RANDOM BUFFER ALLOCATION, MUST HAVE COME FROM MANAGED MEMORY AS SEPARATE HUNKS
MOVE T1,.IONLW(IO) ;SIZE OF ONE NETWORK BUFFER
PUSHJ P,.MMFWD## ;FREE UP NETWORK INPUT BUFFER
STOPCD <Network input buffer deallocation failed in NDFIN1>
MOVE T1,.IONLW(IO) ;SIZE OF ONE NETWORK BUFFER
MOVE T2,.IONOB(IO) ;ADDRESS OF OUTPUT BUFFER
PUSHJ P,.MMFWD## ;FREE UP NETWORK OUTPUT BUFFER
STOPCD <Network output buffer deallocation failed in NDFIN1>
JRST NDFIN6 ;NO MORE BUFFERS
;NETWORK BUFFERS CONTIGUOUS, MUST HAVE COME AS ONE HUNK
NDFIN3: MOVE T1,.IONLW(IO) ;SIZE OF SINGLE NETWORK BUFFER
LSH T1,1 ;SIZE OF BOTH NETWORK BUFFERS
ADD T3,T1 ;T3:=END ADDRESS OF BUFFER ALLOCATION
SUB T3,IO ;TURN INTO RELATIVE OFFSET INTO CDB
JUMPLE T3,NDFIN5 ;IF NOT WITHIN CDB THEN FROM MANAGED MEMORY
CAMLE T3,.IOXSZ(IO) ;WITHIN CDB EXTRA SPACE?
JRST NDFIN5 ;NO, MUST BE FROM MANAGED MEMORY
CAIGE T3,.IOMAX ;ENSURE NOT WITHIN FIXED PART OF CDB
STOPCD <Network buffers trashed in NDFIN3>
CAMN T3,.IOXFF(IO) ;NETWORK BUFFERS LAST THING ALLOCATED?
MOVEM T2,.IOXFF(IO) ;YES, RECLAIM "EXTRA" SPACE
JRST NDFIN6 ;MARK BUFFERS DEALLOCATED
NDFIN5: PUSHJ P,.MMFWD## ;FREE UP COMBINED NETWORK BUFFERS
STOPCD <Network buffers deallocation failed in NDFIN5>
NDFIN6:;PJRST NTFIN6 ;FINAL CLEANUP
;HERE FOR FINAL CLEANUP OF THE CDB
NTFIN6: SETZM .IONIB(IO) ;NO MORE INPUT BUFFERS
SETZM .IONOB(IO) ;NO MORE OUTPUT BUFFERS
MOVX T1,IO.CNR!IO.NBA;BITS TO CLEAR ON NETWORK RELEASE
ANDCAM T1,.IOCCF(IO) ;CLEAR UP THE CDB
JRST .POPJ1## ;SUCCESSFUL RETURN
;N6TO8 - CONVERT 6-BIT FORMAT INTO 8-BIT FORMAT
;CALL IS:
;
; MOVX T2,<N6M>
; MOVX P3,<N8P>
; PUSHJ P,N6TO8
; error return
; normal return
;
;Where <N6M> is the 6-bit name (implicit maximum of 6 characters); and
;<N8P> is the 8-bit storage pointer in the form count,,offset where
;"count" is the maximum byte count for the string, and "offset" is the
;offset in the I/O CDB for the 8-bit format string.
;
;The error return is taken if the 6-bit name is too big for the 8-bit
;string maximum length (with code $EFRSB in M0).
;
;On normal return, the name has been stored as an 8-bit byte string
;in standard format (first word assumed byte count but left untouched).
;The RH(P3) contains the actual byte count of the converted byte string.
;
;Uses P3, P4.
N6TO8: PUSHJ P,NP3P4 ;SETUP .IONP3/.IONP4 AS COUNTER/POINTER
POPJ P, ;OOPS, ERROR
N6TO80: PUSHJ P,TSAV12## ;SAVE T1 AND T2
XMOVEI T1,NTYPO ;OUR SPECIAL "TYPEOUT" ROUTINE
PUSHJ P,.XTYPO## ;SET IT UP
MOVE T1,T2 ;POSITION 6-BIT NAME
PUSHJ P,.TSIXN## ;AND "TYPE" THE NAME
DMOVE P3,.IONP3(IO) ;FETCH TERMINAL BYTE COUNTER/POINTER
JUMPL P3,.POPJ1## ;SUCCESSFUL IF NAME FIT
MOVEI M0,$EFRSB ;STRING TOO BIG
POPJ P, ;ERROR
;N6XO8 - CONVERT 6-BIT (DOUBLE-WORD) FORMAT INTO 8-BIT FORMAT
;CALL IS:
;
; MOVX T2,<N6X>
; MOVX P3,<N8P>
; PUSHJ P,N6XO8
; error return
; normal return
;
;Where <N6X> is the 6-bit name (implicit maximum of 12 characters); and
;<N8P> is the 8-bit storage pointer in the form count,,offset where
;"count" is the maximum byte count for the string, and "offset" is the
;offset in the I/O CDB for the 8-bit format string.
;
;The error return is taken if the 6-bit name is too big for the 8-bit
;string maximum length (with code $EFRSB in M0).
;
;On normal return, the name has been stored as an 8-bit byte string
;in standard format (first word assumed byte count but left untouched).
;The RH(P3) contains the actual byte count of the converted byte string.
;
;Uses P3, P4.
ENTRY .N6XO8
.N6XO8:
N6XO8: PUSHJ P,NP3P4 ;SETUP .IONP3/.IONP4 AS COUNTER/POINTER
POPJ P, ;OOPS, ERROR
N6XO80: PUSHJ P,TSAV13## ;SAVE THE T'S
JUMPE T2,N6XO85 ;ENTER LOOP, SUPPRESSING NULL NAME
N6XO82: SETZ T1, ;CLEAR CHAR ACCUMULATOR
LSHC T1,6 ;NEXT NAME CHARACTER
ADDI T1,"0"-'0' ;ASCIIZE IT
PUSHJ P,NTYPO ;AND ADD IT TO THE STRING
LSH T2,-6 ;RE-POSITION NAME FRAGMENT
LSHC T2,6 ;AND POSITION WHOLE NAME
N6XO85: JUMPN T2,N6XO82 ;LOOP IF MORE TO DO
JUMPN T3,N6XO82 ;LOOP IF MORE TO DO
DMOVE P3,.IONP3(IO) ;FETCH TERMINAL BYTE COUNTER/POINTER
JUMPL P3,.POPJ1## ;SUCCESSFUL IF NAME FIT
MOVEI M0,$EFRSB ;STRING TOO BIG
POPJ P, ;ERROR
;N7TO8 - CONVERT 7-BIT FORMAT INTO 8-BIT FORMAT
;CALL IS:
;
; MOVX T2,<ADR>
; MOVX P3,<N8P>
; PUSHJ P,N6TO8
; error return
; normal return
;
;Where <ADR> is the address of the 7-bit ASCIZ string; and
;<N8P> is the 8-bit storage pointer in the form count,,offset where
;"count" is the maximum byte count for the string, and "offset" is the
;offset in the I/O CDB for the 8-bit format string.
;
;The error return is taken if the 7-bit string is too big for the 8-bit
;string maximum length (with code $EFRSB in M0).
;
;On normal return, the string has been stored as an 8-bit byte string
;in standard format (first word assumed byte count but left untouched).
;The RH(P3) contains the actual byte count of the converted byte string.
;
;Uses P3, P4.
ENTRY .N7TO8
.N7TO8: PUSHJ P,NP3P4 ;SETUP .IONP3/.IONP4 AS COUNTER/POINTER
POPJ P, ;OOPS, ERROR
N7TO80: PUSHJ P,TSAV12## ;SAVE T1 AND T2
XMOVEI T1,NTYPO ;OUR SPECIAL "TYPEOUT" ROUTINE
PUSHJ P,.XTYPO## ;SET IT UP
MOVE T1,T2 ;POSITION 7-BIT STRING ADDRESS
PUSHJ P,.TSTRG## ;AND "TYPE" THE STRING
DMOVE P3,.IONP3(IO) ;FETCH TERMINAL BYTE COUNTER/POINTER
JUMPL P3,.POPJ1## ;SUCCESSFUL IF NAME FIT
MOVEI M0,$EFRSB ;STRING TOO BIG
POPJ P, ;ERROR
;N8TO6 - CONVERT 8-BIT FORMAT STRING INTO 6-BIT NAME
;CALL IS:
;
; MOVX P4,<NDX>
; PUSHJ P,N8TO6
; error return
; normal return
;
;Where <NDX> is the index into the I/O CDB of the 8-bit format byte
;string.
;
;The error return is not utilized.
;
;On normal return T2 contains the 6-bit name (or at least the first
;6 characters' worth).
;
;Uses T1, T2, P2, P3, P4.
N8TO6: ADD P4,IO ;CONVERT TO WORD ADDRESS
HLRZ P3,@P4 ;GET BYTE COUNT
HRLI P4,(POINT 8,,32);CONCOCT A BYTE POINTER
N8TO60: MOVE P2,[POINT 6,T2] ;6-BIT NAMIFIER
SETZ T2, ;INITIALIZE NAME
JRST N8TO65 ;ENTER LOOP
N8TO62: TLNE P2,770000 ;ROOM IN WORD FOR ANOTHER CHARACTER?
IDPB T1,P2 ;YES, STUFF IN NEXT CHARACTER
N8TO65: ILDB T1,P4 ;NEXT 8-BIT BYTE
SUBI T1,"A"-'A' ;SIXBITIFY THE SEVEN-BIT ASCII CHARACTER
SOJGE P3,N8TO62 ;LOOP FOR REST OF STRING
JRST .POPJ1## ;SUCCESSFUL RETURN
;NP3P4 - SETUP .IONP3/.IONP4 AS BYTE COUNT/BYTE POINTER
;CALL IS:
;
; MOVX P3,<8BP>
; PUSHJ P,NP3P4
; error return
; normal return
;
;Where <8BP> is the prototype 8-bit format pointer in the form count,,offset
;where "count" is the maximum byte count of the string and "offset" is the
;byte string offset into the I/O CDB.
;
;On error return the specified index was outside of all possible CDB offsets
;
;On normal return .IONP3 will contain an AOBJN counter of the form -max,,0 and
;.IONP4 will contain the byte pointer for IDPBs.
;
;Uses P3 and P4.
NP3P4: HRRZ P4,P3 ;WORD OFFSET INTO THE CDB
ANDCMI P3,-1 ;MAXIMUM OFFSET,,0
CAILE P4,.IOMAX ;WITHIN RANGE?
STOPCD <8-bit format index outside of I/O CDB bounds in NP3P4>
HRLI P4,(POINT 8,(IO),32) ;CONVERT TO 8-BIT BYTE POINTER
TLC P3,-1 ;MAKE COUNT INTO AOBJN POINTER
DMOVEM P3,.IONP3(IO) ;SETUP COUNTER/POINTER
; (THIS WAY THE RH(.IONP3) IS AN UP-TO-DATE
; COUNT OF BYTES ACTUALLY STORED, WHILE
; LH IS NEGATIVE IF NOT YET OVERFLOWED)
JRST .POPJ1## ;READY FOR CALLS TO NTYPO
;NTYPO - HELPER FOR N6TO8, ETC.
NTYPO: EXCH P3,.IONP3(IO) ;GET CUMULATIVE COUNTER
AOBJP P3,.+2 ;ROOM FOR ANOTHER 8-BIT BYTE?
IDPB T1,.IONP4(IO) ;YES
EXCH P3,.IONP3(IO) ;RESTORE CALLER'S P3
POPJ P, ;RETURN
SUBTTL Network I/O Control
;RNEAT -- EAT [REST OF] NETWORK MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RNEAT
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died.
;
;On normal return the network input message has been completely read, and
;is now ready for the next input message (i.e., RNBYT will return
;with no data available, RNMSG must be called to start the next input
;message processing).
;
;Uses ac T2.
RNEAT: SETZM .IONIC(IO) ;WE CAN CHEAT A BIT HERE
PUSHJ P,RNBYT1 ;READ A NETWORK BYTE
CAIA ;PROBABLY NONE LEFT
JRST RNEAT ;LOOP BACK FOR MORE DATA
JUMPE M0,.POPJ1## ;SUCCESSFUL RETURN
POPJ P, ;NETWORK DIED
;RNBYT -- READ ONE NETWORK BYTE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RNBYT
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return either the network died (M0 has the error code) or there
;are no more bytes left in the current input message (M0 has 0).
;
;On normal return the next data byte from the network channel is in T2.
;
;Uses ac T2.
ENTRY .RNBYT
INTERN RNBYT0, RNBYT1
.RNBYT: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RNBYT0:
RNBYT1: SOSGE .IONIC(IO) ;ANY BYTES LEFT?
JRST RNBYT2 ;NO, AT LEAST NOT IN OUR BUFFER
ILDB T2,.IONIP(IO) ;YES, READ THE NEXT BYTE
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;HERE TO SEE IF NETWORK MESSAGE ENDED, OR MERELY SEGMENTED AND STILL MORE
;BYTES LEFT.
RNBYT2: MOVE T2,.IONIS(IO) ;GET INPUT STATE
TXNE T2,NS.EOM ;MORE INPUT COMING?
JRST RNBYT5 ;NO, END OF MESSAGE SEEN, NULL RETURN
;READ IN NEXT MESSAGE SEGMENT FROM MONITOR
PUSHJ P,RNBUF0 ;REFILL OUR BYTE BUFFER
POPJ P, ;NETWORK DIED
JRST RNBYT1 ;TRY AGAIN
RNBYT5: SETZ M0, ;RETURN NULL TO INDICATE END OF MESSAGE
POPJ P, ;EMPTY RETURN
;RNMSG -- READ IN ONE NETWORK MESSAGE
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RNMSG
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died (M0 has error code).
;
;On successful return the first byte of the message is in T2.
;
;Uses T2.
ENTRY .RNMSG
INTERN RNMSG0, RNMSG1
.RNMSG: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RNMSG0:
RNMSG1: MOVE T2,.IONIS(IO) ;LAST INPUT STATE
TXNE T2,NS.EOM ;DOES THE MONITOR STILL HAVE DATA?
SKIPLE .IONIC(IO) ;NO, DO WE STILL HAVE DATA?
STOPCD <RNMSG called with network data still outstanding>
;HIGHER-UP'S ARE IN SYNC, START UP A NEW MESSAGE
RNMSG4: PUSHJ P,RNBUF0 ;FILL UP OUR INPUT BUFFER
POPJ P, ;NETWORK DIED
PUSHJ P,RNBYT0 ;GET FIRST BYTE OF NEW MESSAGE
CAIA ;OH YEAH?
JRST .POPJ1## ;SUCCESSFUL RETURN
JUMPN M0,.POPJ## ;ERROR RETURN IF ERROR
WARNCD <Null network message returned in RNMSG4>
JRST RNMSG4 ;HO HUM GO TRY AGAIN
;RNBUF -- READ BUFFER OF NETWORK DATA FROM MONITOR
;CALL IS:
;
; MOVX T1,<CDB>
; PUSHJ P,RNBUF
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died (error code is in M0).
;
;On normal return network bytes are available via RNMSG/RNBYT.
;
;Uses T1.
ENTRY .RNBUF
INTERN RNBUF0, RNBUF1
.RNBUF: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
RNBUF0:
RNBUF1: PUSHJ P,TSAV14## ;SAVE THE T'S AS ADVERTISED
RNBUF2: SKIPN T2,.IONCH(IO) ;GET NETWORK CHANNEL
STOPCD <No network channel in RNBUF>
MOVE T1,.IOCCF(IO) ;GET CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF CHANNEL?
JRST RABUF1 ;YES
TXNE T1,IO.DCN ;DECNET CHANNEL?
JRST RDBUF1 ;YES
STOPCD <Neither ANF nor DECnet in RNBUF>
;HERE FOR ANF NETWORK INPUT
RABUF1: MOVX T1,.TKFIN ;FUNCTION: INPUT
MOVE M0,[3,,T1] ;TSK. ARG POINTER TO
TSK. M0, ;READ NETWORK INPUT DATA
JRST RABUF4 ;ERROR
SKIPG .IONIC(IO) ;DID WE GET ANYTHING BACK?
WARNCD <Null network buffer returned in RABUF1>,,,RABUF1
CAIE T3,.TKTDR ;DATA WITH EOM?
TDZA T1,T1 ;NO
MOVX T1,NS.EOM ;YES
MOVEM T1,.IONIS(IO) ;SET EOM FLAG FOR RNMSG
JRST .POPJ1## ;RETURN WITH NETWORK INPUT DATA
;TSK. INPUT FAILED
RABUF4: CAIE M0,TKUDW% ;"IN UUO" DIDN'T WORK?
JRST RABUF6 ;NO, MORE SERIOUS
TXNE T3,IO.ERR ;ERROR OR NON-BLOCKING?
JRST NAIOE1 ;NETWORK I/O FAILURE
MOVE T1,[HB.RIO+^D10000] ;WAKE ON ASYNC I/O, TIMEOUT IN 10 SEC
HIBER T1, ;WAIT FOR ACTIVITY
STOPCD ;HIBER UUOS JUST SIMPLY DO NOT FAIL
JRST RABUF1 ;TRY AGAIN
;TSK. FAILED, NOT "I/O ERROR"
RABUF6: CAIE M0,TKILS% ;MAYBE FUNNY STATE (E.G., DISCONNECTED)?
JRST NARXE1 ;TSK. UUO FAILED
JRST NARXS1 ;BAD STATE - LOOK FOR DISCONNECT REASON
;HERE FOR DECNET NETWORK INPUT
RDBUF1: MOVE T1,[<.NSFDR,,.NSAA2+1>!NS.WAI] ;NETWORK READ FUNCTION
MOVE T3,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN T3,IO.NBT ;WANT THIS READ NON-BLOCKING?
SKIPE .IOSCH(IO) ;OR IS THERE A I/O SCHEDULER LURKING ABOUT?
TXZ T1,NS.WAI ;YES TO ONE OF THE ABOVE, NON-BLOCKING READ
MOVE T3,.IONLB(IO) ;NUMBER OF BYTES WE CAN HANDLE
SKIPN T4,.IONIB(IO) ;ADDRESS OF NETWORK INPUT BUFFER
STOPCD <No network input buffer in RNBUF>
HRLI T4,(POINT 8,) ;NICE BYTE POINTER
XMOVEI M0,T1 ;ARG BLOCK POINTER TO
NSP. M0, ;READ IN NETWORK DATA
JRST NDRXE1 ;NETWORK MUST HAVE DIED
TXNN T2,NS.IDA!NS.NDA;INPUT DATA AVAILABLE?
TDZA M0,M0 ;NO
HRRZ M0,P ;YES
MOVEM M0,.IONIA(IO) ;SET NETWORK DATA AVAILABLITY FLAG
CAIGE T3,0 ;DID DATA OVERFLOW THE BUFFER?
STOPCD <NSP. receive overflowed data buffer in RNBUF>
MOVN T3,T3 ;NEGATE COUNT NOT USED
ADD T3,.IONLB(IO) ;P3:=COUNT OF BYTES RETURNED
JUMPG T3,RNBUF4 ;PROCESS RETURNED DATA
;NO DATA AVAILABLE, SEE WHAT TO DO (CALL SCHEDULER OR RETURN NON-BLOCKING)
MOVEI M0,$EINTI ;NON-BLOCKING NETWORK INPUT
MOVX T2,IO.NBT ;THE NON-BLOCKING FLAG
TDNE T2,.IOCCF(IO) ;CALLER WANT NON-BLOCKING?
POPJ P, ;YES
SKIPN .IOSCH(IO) ;IS SCHEDULER SUPPLIED?
STOPCD <Non-blocking return in RNBUF>
;NO DATA AVAILABLE, MUST "BLOCK" THIS PROCESS VIA THE I/O SCHEDULER
MOVX T1,$SCNTI ;NETWORK INPUT WAIT
PUSHJ P,@.IOSCH(IO) ;CALL THE SCHEDULER
POPJ P, ;BEING ABORTED?
JRST RNBUF1 ;TRY TRY AGAIN
;GOT SOME DATA
RNBUF4: MOVEM T3,.IONIC(IO) ;SET NEW INPUT BYTE COUNT
MOVE T4,.IONIB(IO) ;START ADDRESS OF NETWORK INPUT BUFFER
HRLI T4,(POINT 8,) ;REGENERATE INPUT BUFFER BYTE POINTER
MOVEM T4,.IONIP(IO) ;AND BYTE POINTER TOO
MOVEM T1,.IONIS(IO) ;AND THE STATE (NS.EOM)
JRST .POPJ1## ;SUCCESSFUL RETURN
;XNBYT -- SEND OUT ONE NETWORK BYTE
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<byte>
; PUSHJ P,XNBYT
; error return
; normal return
;
;Where <CDB> is the address of the I/O CDB; and <byte> is the 8-bit byte
;to be shipped verbatim over the network channel.
;
;On error return the network died. T1 and T2 are preserved such that the
;call to XNBYT may be re-executed.
;
;On normal return the data byte has been placed in the pending output
;buffer awaiting transmission.
;
;XNBYT will automatically send message segments (transmit sans EOM) if
;network buffer fills up.
;
;Preserves all acs.
ENTRY .XNBYT
INTERN XNBYT0, XNBYT1
.XNBYT: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XNBYT0:
XNBYT1: SOSGE .IONOC(IO) ;ROOM FOR MORE DATA?
JRST XNBYT2 ;NO
IDPB T2,.IONOP(IO) ;YES, STUFF AWAY THIS BYTE
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;BUFFER FULL, TRY TO OUTPUT IT AND MAKE ROOM FOR MORE DATA
XNBYT2: SKIPN .IONOP(IO) ;FIRST CALL?
JRST XNBYT6 ;YES
MOVE M0,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN M0,IO.DAP ;THIS CHANNEL TALKING DAPESE?
JRST XNBYT6 ;NO, IMAGE BYTE STREAM
MOVE M0,.IODPF(IO) ;YES, GET DAP CONTROL FLAGS
TXNE M0,ID.SNM ;OK TO SEGMENT NETWORK MESSAGES
JRST XNBYT5 ;YES (BUT DOUBLE-CHECK POINTERS)
STOPCD <DAP logic overran network buffer in XNBYT>
;TRANSMIT OLD BUFFER, MAKE ROOM FOR NEW DATA
XNBYT5: SKIPN .IODO3(IO) ;GOT A "LENGTH" FIELD SAVED?
SKIPE .IODO5(IO) ;OR A "BITCNT" FIELD SAVED?
STOPCD <XNBYT5-segmented DAP message with length/bitcount fields>
XNBYT6: MOVX M0,IO.ENM ;THE END-NETWORK-MESSAGE BIT
ANDCAM M0,.IOCCF(IO) ;CLEAR IN THE CDB
PUSHJ P,XNBUF0 ;SEND WHAT WE HAVE, MAKE NEW BUFFER READY
POPJ P, ;BLETCH
SKIPG .IONOC(IO) ;BETTER BE ROOM!
STOPCD <XNBUF returned successfully with a 0-length buffer in XNBYT>
JRST XNBYT1 ;NOW GO TRY AGAIN
;XNFLS -- FLUSH OUT THE NETWORK BUFFER
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XNFLS
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died.
;
;On successful return the network output buffer is empty and ready
;to be filled via calls to XNBYT.
;
;Preserves all acs.
ENTRY .XNFLS
INTERN XNFLS0, XNFLS1
.XNFLS: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XNFLS0:
XNFLS1: MOVE M0,.IONOC(IO) ;CURRENT NETWORK BYTE COUNT
SKIPN .IONOX(IO) ;IF PARTIALLY-OUTPUT BUFFER PENDING
CAME M0,.IONLM(IO) ;OR IF CURRENT BUFFER IS NOT EMPTY
PJRST XNBUF0 ;THEN SHIP CURRENT NETWORK DATA
JRST .POPJ1## ;NO NETWORK DATA, SUCCESSFUL BY DEFINITION
;XNEOM -- SEND ONE NETWORK MESSAGE
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XNEOM
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died.
;
;On successful return the current network output message has been given
;to the monitor for transmission to the remote receiver.
;
;Preserves all acs.
ENTRY .XNEOM
INTERN XNEOM0, XNEOM1
.XNEOM: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XNEOM0:
XNEOM1: MOVX M0,ID.SNM ;THE OK-TO-SEGMENT BIT
ANDCAM M0,.IODPF(IO) ;ALERT THE CONSISTENCY CHECKER (XNBYT)
MOVX M0,IO.ENM ;THE END-NETWORK-MESSAGE BIT
IORM M0,.IOCCF(IO) ;SET IN THE CDB FOR XNBUF TO SEE
PJRST XNBUF0 ;AND OUTPUT WHAT IS THERE
;XNBUF -- SEND BUFFER OF NETWORK DATA
;Call is:
;
; MOVX T1,<CDB>
; PUSHJ P,XNBUF
; error return
; normal return
;
;Where <CDB> is the address of the associated I/O CDB.
;
;On error return the network died.
;
;On successful return the current output buffer has been given to the
;monitor for transmission to the remote receiver.
;
;If the flag IO.ENM in .IOCCF(IO) has been set non-zero then the message
;will be sent as complete, otherwise it will be sent as a partial message
;segment with end of message to come later.
;
;Preserves all acs.
ENTRY .XNBUF
INTERN XNBUF0, XNBUF1
.XNBUF: PUSHJ P,.SACIO## ;SETUP I/O CDB INDEX
XNBUF0:
XNBUF1: PUSHJ P,TSAV14## ;SAVE THE T'S AS ADVERTISED
SKIPN T2,.IONCH(IO) ;FETCH NETWORK CHANNEL NUMBER
STOPCD <No network channel in XNBUF>
MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL
TXNE T1,IO.ANF ;ANF NETWORK?
JRST XABUF1 ;YES
TXNE T1,IO.DCN ;DECNET NETWORK?
JRST XDBUF1 ;YES
STOPCD <Neither ANF nor DECnet in XNBUF>
;HERE FOR ANF NETWORK OUTPUT
XABUF1: MOVX T3,.TKTDR ;ASSUME DATA WITH EOM
MOVE T4,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN T4,IO.ENM ;WANT EOM SENT?
MOVX T3,.TKTDT ;NO, DATA WITHOUT EOM
MOVX T1,.TKFOT ;FUNCTION: OUTPUT
MOVE M0,[3,,T1] ;TSK. ARG POINTER TO
TSK. M0, ;OUTPUT NETWORK DATA
JRST XABUF4 ;ERROR
MOVX T4,IO.ENM ;THE EOM REQUEST FLAG
ANDCAM T4,.IOCCF(IO) ;CLEAR FOR NEXT TIME
JRST .POPJ1## ;SUCCESSFUL
XABUF4: CAIE M0,TKUDW% ;"OUT UUO" DIDN'T WORK?
JRST XABUF6 ;CHECK FOR DISCONNECTED
TXNE T3,IO.ERR ;ERROR OR NON-BLOCKING?
JRST NAIOE1 ;NETWORK I/O ERROR
SETOM .IONOC(IO) ;MAKE SURE NOONE GETS CONFUSED
MOVE T1,[HB.RIO+^D10000] ;WAKE ON ASYNC I/O, TIMEOUT IN 10 SEC
HIBER T1, ;WAIT FOR ACTIVITY
STOPCD ;HIBER UUOS ALWAYS WORK THESE DAYS!
JRST XABUF1 ;TRY AGAIN
;TSK. FAILED, NOT "I/O ERROR"
XABUF6: CAIE M0,TKILS% ;MAYBE FUNNY STATE (E.G., DISCONNECTED)?
JRST NARXE1 ;TSK. UUO FAILED
JRST NARXS1 ;BAD STATE - LOOK FOR DISCONNECT REASON
;HERE FOR DECNET NETWORK OUTPUT
XDBUF1: SKIPE T3,.IONOX(IO) ;PARTIALLY-OUTPUT BUFFER?
JRST XDBUF3 ;YES
MOVE T3,.IONLM(IO) ;SIZE OF OUTPUT [MESSAGE-SIZE-LIMITED] BUFFER
SKIPLE T2,.IONOC(IO) ;OUTPUT BUFFER FULL?
SUB T3,T2 ;NO, CALCULATE AMOUNT OF DATA PRESENT
SETOM .IONOC(IO) ;IN CASE "INTERRUPTED"
SKIPN T4,.IONOB(IO) ;ADDRESS OF OUTPUT BUFFER
STOPCD <No network output buffer in XDBUF1>
TLOA T4,(POINT 8,) ;MAKE INTO BYTE POINTER
XDBUF3: MOVE T4,.IONOY(IO) ;PICK UP SAVED BYTE POINTER
CAIGE T3,0 ;BETTER HAVE A NON-NEGATIVE LENGTH
STOPCD <Byte count negative in XDBUF3> ;***
MOVE T2,.IONCH(IO) ;NO, HAVE DATA, GET NETWORK CHANNEL NUMBER
MOVE T1,[.NSFDS,,.NSAA2+1] ;SEND FUNCTION
SKIPN .IOSCH(IO) ;GOT AN I/O SCHEDULER?
TXO T1,NS.WAI ;NO, THEN BLOCKING SEND
MOVX M0,IO.ENM ;THE END-NETWORK-MESSAGE BIT
TDNE M0,.IOCCF(IO) ;IS IT SET IN THE CHANNEL CONTROL WORD?
TXO T1,NS.EOM ;YES
ANDCAM M0,.IOCCF(IO) ;IN ANY CASE, CLEAR IT WHEN DONE
XMOVEI M0,T1 ;ARG POINTER TO
NSP. M0, ;SEND BUFFER OF DATA
JRST NDRXE1 ;NETWORK MUST HAVE DIED
MOVEM T1,.IONOS(IO) ;SAVE NETWORK OUTPUT STATUS (NS.EOM)
DMOVEM T3,.IONOX(IO) ;SET COMPLETION CODE
TXNN T2,NS.IDA!NS.NDA;IS THERE INPUT PENDING?
TDZA M0,M0 ;NO
HRRZ M0,P ;YES
MOVEM M0,.IONIA(IO) ;SET INPUT AVAILABILITY FLAG
;SETUP BYTE POINTER/COUNTER FOR XNBYT
XDBUF4: JUMPN T3,XDBUF8 ;WAIT FOR COMPLETION IF NEEDED
XDBUF6: MOVE T1,.IONLM(IO) ;NETWORK [MESSAGE-SIZE-LIMITED] BUFFER SIZE
MOVEM T1,.IONOC(IO) ;SET IN CDB
MOVE T2,.IONOB(IO) ;ADDRESS OF OUTPUT BUFFER
HRLI T2,(POINT 8,) ;MAKE INTO BYTE POINTER
MOVEM T2,.IONOP(IO) ;SET IN CDB
JRST .POPJ1## ;SUCCESS RETURN
;COULDN'T OUTPUT ENTIRE BUFFER, MUST WAIT
XDBUF8: MOVEI M0,$EINTO ;NON-BLOCKING NETWORK OUTPUT STATUS
SKIPN .IOSCH(IO) ;UNLESS AN I/O SCHEDULER IS SUPPLIED
STOPCD <Non-blocking return in XDBUF8>
;CALL THE SCHEDULER
MOVX T1,$SCNTO ;NETWORK OUTPUT WAIT
PUSHJ P,@.IOSCH(IO) ;WAIT FOR SOMETHING TO HAPPEN
POPJ P, ;MUST BE ABORT
JRST XDBUF1 ;TRY OUTPUTTING AGAIN
SUBTTL Network Error Handling
;NACIE - TSK. error cleanup.
NACIE1: MOVEM T1,P4 ;SAVE TSK. ERROR CODE
PUSHJ P,NTZAP0 ;BLAST AWAY THE TSK. CHANNEL (IF ANY)
STOPCD <NTZAP failed in NACIE1>
CAIL P4,0 ;NEGATIVE ERROR CODE ILLEGAL
CAILE P4,NAERRL ;KNOWN TSK. ERROR CODE?
SETO P4, ;NO
HLRZ M0,NAERRT(P4) ;FETCH CONNECT ERROR CODE
POPJ P, ;PROPAGATE ERROR TO CALLER
;NARXE - TSK. error cleanup (sending/receiving data)
NARXE1: PUSHJ P,.SAVE4## ;RABUF/XABUF DON'T SAVE THE PEAS
MOVEM M0,P4 ;SAVE TSK. ERROR CODE
MOVE P3,.IOCCF(IO) ;PRESERVE A COPY OF CCF FLAGS
NARXE3: PUSHJ P,NTZAP0 ;BLAST AWAY THE TSK. CHANNEL
STOPCD <NTZAP failed in NARXE1>
CAIL P4,0 ;NEGATIVE ERROR CODE ILLEGAL
CAILE P4,NAERRL ;KNOWN TSK. ERROR CODE?
SETO P4, ;NO
HRRZ M0,NAERRT(P4) ;FETCH I/O ERROR CODE
NARXE7: MOVEM M0,.IOER2(IO) ;SAVE "SUB-STATE" CODE
MOVEI M0,$EINLA ;GENERIC "NETWORK LINK ABORTED"
POPJ P, ;PASS ERROR TO CALLER
;TSK. error table
$EFXXX,,$EIXXX ;-- - UNKNOWN ERROR CODE
NAERRT: $EFXXX,,$EIXXX ;00 - UNKNOWN ERROR CODE
$EFNNS,,$EIXXX ;01 - NO NETWORK (TSKSER) SUPPORT
$EFABE,,$EIABE ;02 - ARGUMENT BLOCK ERROR (TOO SHORT)
$EFPRV,,$EIPRV ;03 - NO PRIVILEGES
$EFILF,,$EIILF ;04 - ILLEGAL FUNCTION
$EFBCN,,$EIBCN ;05 - ILLEGAL CHANNEL (NOT TSK:, ETC)
$EFPBL,,$EIXXX ;06 - ILLEGAL NPD (PROCESS DESCRIPTOR)
$EFPBL,,$EIXXX ;07 - ILLEGAL NPD (TOO SHORT)
$EFWRS,,$EIWRS ;10 - ILLEGAL CHANNEL STATE FOR FUNCTION
$EFALF,,$EIALF ;11 - ALLOCATION FAILURE
$EFALF,,$EIXXX ;12 - NO FREE LINKS (SHOULDN'T HAPPEN)
$EFNSN,,$EIXXX ;13 - NO SUCH NODE
$EFXXX,,$EINLK ;14 - I/O REQUEST FAILED (NO LINK?)
NAERRL==.-NAERRT ;LENGTH OF ERROR TABLE
;NARXS - TSK. error (sending/receiving data) -- wrong state
NARXS1: PUSHJ P,.SAVE4## ;RABUF/XABUF DON'T SAVE THE PEAS
MOVEM M0,P4 ;SAVE TSK. ERROR CODE
MOVE P3,.IOCCF(IO) ;PRESERVE A COPY OF CCF FLAGS
MOVEI T1,.TKFRS ;FUNCTION: READ STATE
MOVE T2,.IONCH(IO) ;SET TASK CHANNEL
SETOB T3,T4 ;JUST TO MAKE SURE SOMETHING RETURNED
MOVE M0,[3,,T1] ;TSK. ARG POINTER TO
TSK. M0, ;READ TASK CHANNEL STATE
JRST NARXE3 ;FORGET IT, BLOW IT AWAY
CAIE T3,.TKSID ;IS THE LINK NOW "IDLE" (I.E., DISCONNECTED)?
JRST NARXE3 ;NO, STRANGE STATE, BLOW IT AWAY
MOVE M0,[4,,T1] ;YES, CAN NOW SETUP TO SAFELY
TSK. M0, ;READ LINK STATE AND DISCONNECT CODE
JRST NARXE3 ;OH WELL, WE TRIED
MOVE T2,T4 ;POSITION ANF DISCONNECT CODE
MOVEI T4,NARXST ;ANF-TO-NFT DISCONNECT TRANSLATION TABLE
PUSHJ P,.CFIND## ;TRY TO TRANSLATE THE DISCONNECT REASON
MOVEI T1,$EIUXS ;HO HUM
MOVE P4,T1 ;POSITION NFT ERROR/EXCEPTION CODE
PUSHJ P,NTZAP0 ;BLOW AWAY THE TSK CHANNEL ON OUR SIDE
JFCL ;HAH!
MOVE M0,P4 ;POSITION OUR TRANSLATED ERROR/EXCEPTION CODE
JRST NARXE7 ;RETURN ERROR CODE
;TSK. disconnect reason translation table (I/O transfer level)
NARXST: $EIDBO,,^O00 ;"NORMAL" DISCONNECT (E.G., FILOP./RELEASE)
$EIURO,,^O01 ;NO SUCH OBJECT TYPE
$EIRES,,^O02 ;NO RESOURCES/TOO MANY CONNECTS
$EIOTB,,^O03 ;OBJECT BUSY
$EIURO,,^O04 ;OBJECT NOT AVAILABLE
$EILNS,,^D03 + 100 ;NODE SHUTTING DOWN
$EIABM,,^D09 + 100 ;ABORT BY DIALOG PROCESS
$EIUID,,^D34 + 100 ;INVALID USERID/PASSWORD
$EIUAC,,^D36 + 100 ;INVALID ACCOUNT STRING
$EIIMG,,^D43 + 100 ;ERROR IN IMAGE FIELD/STRING
0
;NAIOE - TSK. error cleanup (I/O errors)
NAIOE1: MOVEM T3,.IOER3(IO) ;REMEMBER TSK I/O STATUS AS TERTIARY STATUS
PUSHJ P,NTZAP0 ;BLOW AWAY WHATEVER'S LEFT
JFCL ;HOHUM
MOVE T3,.IOER3(IO) ;RETRIEVE TSK I/O STATUS WORD
TXCE T3,IO.IMP ;"IMPROPER MODE"
MOVEI M0,$EIIMP ;YUP
TXCE T3,IO.DER ;"DEVICE ERROR"
MOVEI M0,$EIDEV ;YUP
TXCE T3,IO.DTE ;"DATA ERROR"
MOVEI M0,$EIDAT ;YUP
TXCE T3,IO.BKT ;"BLOCK TOO LARGE"
MOVEI M0,$EIBKT ;YUP
TXCE T3,IO.ERR ;ALL ERROR BITS LIT?
JRST NAIOE4 ;NO, SET ERROR AS TRANSLATED
MOVEI M0,$EIUCM ;*** YEAH, CALL IT "NO COMMUNICATION"
;*** SHOULD DO DEVOP. AND TRANSLATE!
;*** BUT THIS IS ONLY MEANINGFUL NETWORK
;*** ERROR, SO . . .
NAIOE4: MOVEM M0,.IOER2(IO) ;SET "NLA" SUBSTATE AS SECONDARY STATUS
MOVEI M0,$EINLA ;RETURN A "LINK ABORTED" ERROR
POPJ P, ;TO WHOMEVER...
;NDCIE - NSP. error cleanup, call with P2/Channel number if any
NDCIE1: CAIE M0,P1 ;POSSIBLY THE "UNIMPLEMENTED" ERROR RETURN?
JRST NDCXE1 ;NO
MOVX T1,%CNST2 ;YES
GETTAB T1, ;GET MONITOR "CONFIG" FLAGS
STOPCD <GETTAB(%CNST2) failed in NDCIE1>
TXNE T1,ST%D36 ;IS DECNET-36 IMPLEMENTED?
JRST NDCXE1 ;YES
MOVEI M0,$EFNNS ;NO, THEN ERROR IS "NO NETWORK SOFTWARE"
POPJ P, ;AND THAT IS THAT
NDCXE1: MOVEM M0,P4 ;PRESERVE NSP. ERROR CODE
HRRZM P2,.IONCH(IO) ;STORE CHANNEL IF THE MONITOR GAVE US ONE
PUSHJ P,NTZAP0 ;AND BLAST IT TO SMITHEREENS
STOPCD <NTZAP failed in NDCIE1>
CAIL P4,0 ;NEGATIVE ERROR CODE UNKNOWN
CAILE P4,NDERRL ;KNOWN NSP ERROR CODE?
SETO P4, ;NO
HLRZ M0,NDERRT(P4) ;FETCH CONNECT ERROR CODE
POPJ P, ;PASS ERROR TO CALLER
;NDRXE - NSP. error cleanup (sending/receiving data)
NDRXE1: MOVEM M0,P4 ;PRESERVE NSP. ERROR CODE
MOVE P3,.IOCCF(IO) ;PRESERVE COPY OF CHANNEL CONTROL FLAGS
PUSHJ P,NTZAP0 ;BLAST NSP CHANNEL TO SMITHEREENS
STOPCD <NTZAP failed in NDRXE1>
CAIL P4,0 ;NEGATIVE ERROR CODE UNKNOWN
CAILE P4,NDERRL ;KNOWN NSP ERROR CODE?
SETO P4, ;NO
HRRZ M0,NDERRT(P4) ;FETCH ERROR CODE
MOVEM M0,.IOER2(IO) ;SAVE "SUB-STATE" CODE
MOVEI M0,$EINLA ;GENERIC "NETWORK LINK ABORTED"
POPJ P, ;PASS ERROR TO CALLER
;NSP. error table
$EFXXX,,$EIXXX ;-- - UNKNOWN ERROR CODE
NDERRT: $EFXXX,,$EIXXX ;00 - UNKNOWN ERROR CODE
$EFABE,,$EIABE ;01 - ARGUMENT BLOCK ERROR
$EFALF,,$EIALF ;02 - ALLOCATION FAILURE
$EFBCN,,$EIBCN ;03 - BAD CHANNEL NUMBER
$EFBFT,,$EIBFT ;04 - BAD FORMAT TYPE IN PROCESS BLOCK
$EFCFE,,$EICFE ;05 - CONNECT BLOCK FORMAT ERROR
$EFIDL,,$EIIDL ;06 - INTERRUPT DATA TOO LONG
$EFIFM,,$EIIFM ;07 - ILLEGAL FLOW CONTROL MODE
$EFILF,,$EIILF ;10 - ILLEGAL NSP. FUNCTION CODE
$EFJQX,,$EIJQX ;11 - JOB QUOTA EXHAUSTED
$EFLQX,,$EILQX ;12 - LINK QUOTA EXHAUSTED
$EFNCD,,$EINCD ;13 - NO CONNECT DATA TO READ
$EFPIO,,$EIPIO ;14 - PERCENTAGE INPUT OUT OF BOUNDS
$EFPRV,,$EIPRV ;15 - NO PRIVILEGES
$EFSTB,,$EISTB ;16 - SEGMENT SIZE TOO BIG
$EFNSN,,$EINSN ;17 - UNKNOWN NODE NAME
$EFUXS,,$EIUXS ;20 - UNEXPECTED STATE: UNSPECIFIED
$EFWNA,,$EIWNA ;21 - WRONG NUMBER OF ARGUMENTS
$EFWRS,,$EIWRS ;22 - LINK IN WRONG STATE
$EFCBL,,$EICBL ;23 - CONNECT BLOCK LENGTH ERROR
$EFPBL,,$EIPBL ;24 - PROCESS BLOCK LENGTH ERROR
$EFSBL,,$EISBL ;25 - STRING BLOCK LENGTH ERROR
$EFUDS,,$EIUDS ;26 - UNEXPECTED STATE: DISCONNECT SENT
$EFUDC,,$EIUDC ;27 - UNEXPECTED STATE: DISCONNECT CONFIRMED
$EFUCF,,$EIUCF ;30 - UNEXPECTED STATE: NO CONFIDENCE
$EFULK,,$EIULK ;31 - UNEXPECTED STATE: NO LINK
$EFUCM,,$EIUCM ;32 - UNEXPECTED STATE: NO COMMUNICATION
$EFUNR,,$EIUNR ;33 - UNEXPECTED STATE: NO RESOURCES
$EFRBO,,$EIRBO ;34 - CONNECT REJECTED: REJECTED BY OBJECT
$EFDBO,,$EIDBO ;35 - DISCONNECTED BY OBJECT
$EFRES,,$EIRES ;36 - CONNECT REJECTED: NO RESOURCES
$EFUXN,,$EIUXN ;37 - CONNECT REJECTED: UNKNOWN NAME
$EFRNS,,$EIRNS ;40 - CONNECT REJECTED: NODE SHUT DOWN
$EFURO,,$EIURO ;41 - CONNECT REJECTED: UNRECOGNIZED OBJECT
$EFIOF,,$EIIOF ;42 - CONNECT REJECTED: BAD OBJECT NAME FORMAT
$EFOTB,,$EIOTB ;43 - CONNECT REJECTED: OBJECT FULL/BUSY
$EFABM,,$EIABM ;44 - CONNECT REJECTED: ABORTED BY MANAGEMENT
$EFABO,,$EIABO ;45 - CONNECT REJECTED: ABORTED BY OBJECT
$EFINF,,$EIINF ;46 - CONNECT REJECTED: INVALID NODE NAME FORMAT
$EFLNS,,$EILNS ;47 - CONNECT REJECTED: LOCAL NODE SHUT DOWN
$EFUID,,$EIUID ;50 - CONNECT REJECTED: INVALID USERID
$EFNRO,,$EINRO ;51 - CONNECT REJECTED: NO RESPONSE FROM OBJECT
$EFNUR,,$EINUR ;52 - NODE UNREACHABLE
$EFNLK,,$EINLK ;53 - NO LINK
$EFDSC,,$EIDSC ;54 - DISCONNECT COMPLETE
$EFIMG,,$EIIMG ;55 - IMAGE FIELD TOO LONG
$EFUAC,,$EIUAC ;56 - CONNECT REJECTED: INVALID ACCOUNT DATA
$EFBCF,,$EIBCF ;57 - BAD COMBINATION OF FLAGS
$EFADE,,$EIADE ;60 - ADDRESS CHECK
NDERRL==.-NDERRT ;LENGTH OF ERROR TRANSLATION TABLE
END