Trailing-Edge
-
PDP-10 Archives
-
BB-PBDEB-BB_1990
-
10,7/swil/swilio.mac
There are 7 other files named swilio.mac in the archive. Click here to see a list.
TITLE .IO SWIL I/O routines
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
COMMENT \
COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1984,1986,1988. ALL RIGHTS RESERVED.
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.
\
SUBTTL Version and Revision History
MAJVER==13 ;MAJOR VERSION LEVEL
MINVER==0 ;MINOR (MAINTENANCE RELEASE) LEVEL
CSTVER==0 ;CUSTOMER VERSION (WHO LAST . . .)
EDTVER==1057 ;EDIT LEVEL
%%IO==:<BYTE (3)CSTVER(9)MAJVER(6)MINVER(18)EDTVER>
%%SWIL==:%%SWIL ;SHOW (AND SYNCHRONIZE) SWIL VERSION
IF2,< PURGE CSTVER,MAJVER,MINVER,EDTVER>
;INITIAL CREATION
;1000 RDH 01-Jan-84
; Incorporate into SWIL %12(1000), sync edit level at 1000.
;1005 RDH 12-Oct-84
; Implement support for "Stream-CR" and "Stream-LF" VAX files.
;1015 DRB 29-Jan-85
; ORNIX5 incorrectly tests for passive connection (assumes .IOCCF
; loaded into M0, and it isn't).
;1022 LEO 09-Sep-85
; Do Copyrights.
;1040 RDH 3-Jan-86
; ORNIX5 doesn't pass incoming DAP (e.g., aborting ACCOMP) messages
; back up to FAL. Supersedes edit 1015.
;1041 RDH 4-Jan-86
; No support for network Line Sequence Numbers.
;1042 RDH 23-Jan-86
; Implement /IOMODE:A8CII.
;1044 BSC 16-Jun-86
; Fix ? UNKNOWN ISF FLAGS IN IRAS90 when VAX file with FORTRAN carriage
; carriage control record starts with "0" or "-" which requires
; conversion to multiple line-feeds. AC T1 was getting trashed.
;1047 TL 4-Dec-86
; Fix VAX receives of records like <FF>text<EOR>more when IS.ICL is set.
; See detailed description in SWIDEF.
;1051 KDO 20-Mar-87
; Add ULTRIX support.
;1057 JJF 10-Apr-89 SPR:10-36155
; Implement support for 'append-mode' files.
; Invent a new .IOCCF flag, named IO.APP, to indicate that the
; remote wants to append to the file, and/or the file has been
; placed into append mode. Add code to the output initialization
; routines to do a FILOP. append function if the flag is lit.
; Modules: SWIL, SWILIO
SUBTTL INPUT SERVICE ROUTINES
;All Input Service Routines are called with the I/O CDB address in
;register T1.
;
;On the error/exception return M0 has the error/exception code
;
;On normal return, data is passed in T2 (and if needed T3, T4).
;
;In all cases, T1 is preserved, as is any other T register not used
;to return data.
ENTRY .IOIIN
.IOIIN: PUSHJ P,IOIIN0 ;DO THE WORK
POPJ P, ;ERROR
PJRST @.IOISR(T1) ;DISPATCH TO SELECTED INPUT SERVICE ROUTINE
IOIIN0: PUSHJ P,.SACIO## ;SELECT I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S
SETZM .IOISF(IO) ;CLEAR OUT INPUT PROCESSING FLAGS
XMOVEI P3,.POPJ1## ;SUCCESSFUL RETURNER
MOVEM P3,.IOISS(IO) ;NO SPECIAL CLOSE PROCESSING REQUIRED
MOVX P1,IO.IOA ;THE I/O-ACTIVE FLAG
IORB P1,.IOCCF(IO) ;FLAG I/O BEING PERFORMED
TXNE P1,IO.NET ;LOCAL OR REMOTE (NETWORK) I/O?
JRST IRINI ;REMOTE
;LOCAL, FALL INTO ILINI
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;ILINI -- INPUT, LOCAL, INITIALIZATION
ILINI: TXNE P1,IO.IBA ;INPUT BUFFERS ALLOCATED?
JRST ILINI4 ;YES, SELECT ISR AND START I/O
;NO INPUT BUFFERS, GENERATE SOME FOR FREE
PUSHJ P,FILBI1## ;SETUP INPUT BUFFERS
POPJ P, ;OH WELL
;SELECT ISR BASED ON FILE MODE AND OPTIONS
ILINI4: MOVE P4,.IOIOC(IO) ;I/O CONTROL
LDB P2,[POINTR P4,IC.MOD] ;GET FILE MODE
XMOVEI P3,. ;GET OUR SECTION IN LH
HRR P3,MOISTB(P2) ;SELECT ISR BASED ON FILE MODE ALONE
TXNE P4,IC.RSI ;USER WANT RECORD-STRUCTURED I/O?
HRRI P3,ILREC ;YES, TOO BAD
TXNE P4,IC.BLK ;USER WANT BLOCK MODE BUFFERS
HRRI P3,ILBLK ;YES, LET HIM DO HIS OWN STUFF THEN
TXNE P4,IC.MCY!IC.MEY;WANT TO READ MACY11-PACKED DATA?
HRRI P3,ILMCI ;YES, USE MACY11 ISR
MOVEM P3,.IOISR(IO) ;SET ISR IN THE CDB
;INITIALIZE COUNTERS
SETZM .IOIUC(IO) ;NO BUFFERS READ YET
JRST .POPJ1## ;INPUT INITIALIZED
;ILASC -- INPUT, LOCAL, ASCII CHARACTERS
ILASB: PUSHJ P,ILBUF ;ASK MONITOR FOR ANOTHER BUFFER
POPJ P, ;ERROR
ILASC: SOSGE .IOIBC(T1) ;ANY CHARACTERS LEFT?
JRST ILASB ;NO, GET A NEW BUFFER-FULL
ILDB T2,.IOIBP(T1) ;YES, RETREIVE THE NEXT ASCII CHARACTER
MOVE M0,@.IOIBP(T1) ;FETCH A COPY OF THE WORD
TRZE M0,1 ;A LINE-SEQUENCE-NUMBER?
JRST ILASN ;YES (YUCH)
JUMPE T2,ILASC4 ;NO, WATCH OUT FOR NULLS
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;CHECK OUT A NULL
ILASC4: MOVE M0,.IOIOC(T1) ;I/O CONTROL BITS
TXNN M0,IC.LSN ;LSN DEFEATS NULLS
TXNN M0,IC.NUL ;USER WANT NULLS AS NORMAL CHARACTERS?
JRST ILASC ;NO, EAT THE NULL
JRST .POPJ1## ;YES, SUCCESSFUL RETURN
;LINE-SEQUENCE-NUMBER DETECTED, SLURP IT UP AND SEE WHAT TO DO WITH IT
ILASN: PUSHJ P,TSAV14## ;FOR FUNNY GRUNDGE BELOW
MOVE T4,M0 ;PRESERVE COPY OF LSN
MOVNI T3,4 ;AN LSN IS 5 CHARACTERS
ADDM T3,.IOIBC(T1) ;SO MARK ALL 5 AS "SOSGE"ED
MOVSI T3,(POINT 7,,34);ALSO FAKE OUT THE BYTE POINTER
HLLM T3,.IOIBP(T1) ;SO ILDB WILL START ON NEXT WORD
CAMN T4,[<ASCII/ />] ;IS THIS AN SOS-STYLE PAGE-MARK?
JRST ILASP ;PROBABLY
SETZ T2, ;INITIALIZE LSN
ILASN1: SETZ T3, ;CLEAR OUT FOR NEXT LSN DIGIT
LSHC T3,^D7 ;SHIFT UP NEXT ASCII DIGIT CHARACTER
CAIL T3,"0" ;IS IT A DECIMAL DIGIT?
CAILE T3,"9" ;IS IT A DECIMAL DIGIT?
JRST [MOVX M0,$EILLN ;NO, LUDICROUS LINE NUMBER
POPJ P,] ;RETURN
IMULI T2,^D10 ;MAKE ROOM FOR NEW DECADE
ADDI T2,-"0"(T3) ;ADD IN THIS DECADE
JUMPN T4,ILASN1 ;LOOP FOR ALL FIVE DIGITS
MOVEM T2,-T2(P) ;ASSUME USER WILL WANT THE LSN RETURNED
;NOW CHECK FOR SOS'S <TAB>, EATING INTERVENING NULLS
MOVE T3,.IOIOC(T1) ;A SAFE COPY OF THE I/O CONTROL BITS
ILASN3: PUSHJ P,ILBYT ;READ NEXT INPUT BYTE
JRST [CAIN M0,$EIEOF ;ERROR - END OF FILE?
MOVX M0,$EIEFL ;YES, ERROR, EOF READING LSN
POPJ P,] ;RETURN EXCEPTION CODE
MOVE M0,@.IOIBP(T1) ;COPY OF WHOLE WORD TOO
TRZE M0,1 ;THIS WORD ALSO CLAIM TO BE AN LSN?
JRST [MOVX M0,$EIMLN ;YES, MULTIPLE LINE NUMBERS
POPJ P,] ;ERROR RETURN
JUMPE T2,[TXNN P1,IC.NUL ;USER WANT NULLS?
JRST ILASN3 ;NO, EAT IT, KEEP SEARCHING
JRST ILASN8] ;YES, VALID DATA CHARACTER
CAIE T2,.CHTAB ;VALID CHARACTER, SOS-STYLE <TAB>?
JRST ILASN8 ;NO, VALID DATA CHARACTER
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;NOW SCAN TO NEXT VALID DATA CHARACTER, SUPPRESSING NULLS IF NEED BE
ILASN5: PUSHJ P,ILBYT ;GET NEXT INPUT BYTE
JRST [CAIN M0,$EIEOF ;END OF FILE?
MOVX M0,$EIEFL ;YES, ERROR
POPJ P,] ;ERROR RETURN
MOVE M0,@.IOIBP(T1) ;COPY OF WORD ALSO
TRZE M0,1 ;MAKE SURE NOT ANOTHER LSN
JRST [MOVX M0,$EIMLN ;ERROR - MULTIPLE LSN
POPJ P,] ;ERROR RETURN
JUMPE T2,[TXNN P1,IC.NUL ;USER SAY NULL IS VALID DATA?
JRST ILASN5 ;NO, EAT THE NULL
JRST ILASN8] ;YES, RETURN NULL AS DATA CHAR
;HERE WITH T2 HAVING FIRST VALID CHARACTER AFTER THE LSN
ILASN8: EXCH T2,-T2(P) ;ASSUME USER DOESN'T WANT THE LSN
MOVE T3,.IOIOC(T1) ;FETCH I/O CONTROL FLAGS
TXNN T3,IC.LSN ;DID I GUESS RIGHT?
JRST .POPJ1## ;YEAH, HOW CONVENIENT
EXCH T2,-T2(P) ;NO, RETURN THE LSN THEN
MOVEM T2,.IOIS0(T1) ;AND REMEMBER THE DATA CHARACTER
XMOVEI T2,ILASN9 ;SET STATE INTERCEPT
MOVEM T2,.IOISR(T1) ;TO RETURN DATA CHARACTER NEXT CALL
MOVEI M0,$EILSN ;NOTE A LINE SEQUENCE NUMBER ENCOUNTERED
POPJ P, ;AND TAKE EXCEPTION RETURN THIS CALL
;RETURN SAVED DATA CHARACTER
ILASN9: XMOVEI T2,ILASC ;RESTORE NORMAL ASCII INPUT
MOVEM T2,.IOISR(T1) ;SET ISR IN CDB
MOVE T2,.IOIS0(T1) ;FETCH SAVED CHARACTER
JRST .POPJ1## ;SUCCESSFUL RETURN
;HERE ON SOS-STYLE PAGE MARK COMING UP
ILASP: PUSHJ P,ILBYT ;GET NEXT 7-BIT BYTE
JRST [CAIN M0,$EIEOF ;ERROR - END OF FILE?
MOVEI M0,$EIEFL ;YES, ERROR, EOF READING LSN
POPJ P,] ;PROPAGATE ERROR
MOVE M0,@.IOIBP(T1) ;COPY OF WHOLE WORD TOO
TRZE M0,1 ;CAN'T BE ANOTHER LSN
JRST [MOVEI M0,$EIMLN ;MULTIPLE LSN'S
POPJ P,] ;RETURN ERROR
CAIE T2,.CHCRT ;THIS MUST BE A <CR>
JRST [MOVEI M0,$EILLN ;NOT, LUDICROUS LINE NUMBER
POPJ P,] ;RETURN ERROR
PUSHJ P,ILBYT ;GET NEXT 7-BIT BYTE
JRST [CAIN M0,$EIEOF ;ERROR - END OF FILE?
MOVEI M0,$EIEFL ;YES, ERROR, EOF READING LSN
POPJ P,] ;PROPAGATE ERROR
CAIE T2,.CHFFD ;THIS MUST BE A <FF>
JRST [MOVEI M0,$EILLN ;NOT, LUDICROUS LINE NUMBER
POPJ P,] ;RETURN ERROR
MOVEM T2,-T2(P) ;THIS IS THE DESIRED <FF>
MOVNI T3,3 ;THERE ARE THREE MORE NULLS THERE
ADDM T3,.IOIBC(T1) ;SO SKIP PAST THEM
MOVSI T3,(POINT 7,,34);ALSO FAKE OUT
HLLM T3,.IOIBP(T1) ;THE BYTE POINTER
MOVE T3,.IOIOC(T1) ;GET INPUT I/O CONTROL FLAGS
TXNN T3,IC.LSN ;CALLER WANT INPUT LSNS?
JRST .POPJ1## ;NO, JUST RETURN <FF>
MOVSI T2,(1B0) ;YES, FORMAT SOS-STYLE PAGE MARK
MOVEM T2,-T2(P) ;AND RETURN THAT TO THE CALLER
MOVEI M0,$EILSN ;AS AN LSN
POPJ P, ;TAKE EXCEPTION RETURN
;ILBYT -- INPUT, LOCAL, BYTE STREAM
ILBYB: PUSHJ P,ILBUF ;ASK FOR ANOTHER BUFFER
POPJ P, ;ERROR (OR END OF FILE)
ILBYT: SOSGE .IOIBC(T1) ;ANY BYTES LEFT IN CURRENT BUFFER?
JRST ILBYB ;NO, ASK FOR ANOTHER BUFFER'S WORTH
ILDB T2,.IOIBP(T1) ;GET NEXT DATA BYTE
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;ILREC -- INPUT, LOCAL, RECORD-STRUCTURED I/O
ILREC: STOPCD <Record-structured local I/O illegal>
;ILBLK -- INPUT, LOCAL, BLOCK-AT-A-TIME MODE
ILBLB: PUSHJ P,ILBUF ;ASK MONITOR FOR A BUFFER
POPJ P, ;ERROR (OR END OF FILE)
ILBLK: MOVE T2,.IOIUC(T1) ;RETURN VIRTUAL BLOCK NUMBER (OR SOMETHING)
SETO T3, ;FLAG EMPTY
EXCH T3,.IOIBC(T1) ;ACCOUNT FOR THIS BUFFER'S WORTH OF DATA
MOVE T4,.IOIBP(T1) ;BYTE POINTER TO THE DATA
JRST .POPJ1## ;SUCCESSFUL RETURN
;ILMCY -- INPUT, LOCAL, MACY11 PACKED
;MACY11 packing involves writing 8-bit bytes packed four to a 36-bit word,
;but not in an obvious manner. The four bytes are layed out as follows:
;
; 2 9 10 17 20 27 28 35
; +--+--------+--------+--+--------+--------+
; | | two | one | | four | three |
; +--+--------+--------+--+--------+--------+
;
;This format can be thought of as aligning one -11 16-bit word per -10
;halfword (although it should be emphasized that the packing is in
;terms of bytes, so that the "16-bit words" might be (and often are)
;split across "18-bit halfwords"!).
;
;The record structure imposed is:
;
; 000001 ;record header
; length ;count of bytes (includes MACY11 header - 6 bytes)
; address ;for .LDA files, address to load record
; ; ignored for pure data records
; -data- ;length-6 data bytes
; ...cks ;one-byte checksum (not included in count)
;
;The output variables (in the CDB) are used as follows:
;
; .IOIS0 ;record "address" (typically meaningless, but preserved)
; .IOIS1 ;record (actual data) byte count
; .IOIS2 ;ILMCB (byte-stuffing) state
; .IOIS3 ;ILMCR (record-header) state
; .IOIS4 ;ILMCB 36-bit word
; .IOIS5 ;MACY11 checksum value
;The ISR call is:
;
; MOVX T3,<CNT>
; MOVX T4,<PTR>
; PUSHJ P,@.IOISR
; error return
; normal return
;
;Where <CNT> is the maximum count of bytes that can fit in the user-supplied
;record buffer; and <PTR> is the byte pointer to the record buffer.
;
;On error return an error code is in M0 - such as record format error.
;
;On normal return T2 has the record "address" (as per the .LDA/MACY11 format
;typically ignored for data files), T3 has the count of bytes returned in
;the current record, and T4 is unchanged (points to start of record).
;HERE TO INITIALIZE MACY11 INPUT (FROM ILINI)
ILMCI: SETZM .IOIS3(T1) ;NOT IN A RECORD STATE
SETZM .IOIS2(T1) ;NOT IN A WORD EITHER
XMOVEI M0,ILMCY ;THE NORMAL MACY11 ISR
MOVEM M0,.IOISR(T1) ;SET FOR REST OF THE WORLD
;FALL INTO ILMCY
;HERE TO INPUT ONE MACY11 LOGICAL DATA BYTE (CALLED AS AN ISR)
ILMCY: PUSHJ P,.SAVE2## ;NEED A COUPLA MORE ACS HERE
PUSHJ P,TSAV14## ;SAVE/STORE THE T'S
PUSHJ P,ILMCR ;FIRE UP A DATA RECORD
POPJ P, ;I/O ERROR? OR WORSE?
MOVE T2,.IOIS0(T1) ;GET RECORD "ADDRESS"
MOVEM T2,-T2(P) ;AND SET FOR CALLER (IF HE CARES)
MOVN T3,-T3(P) ;NEGATE CALLER'S BYTE COUNT
SUBI T3,1 ;ALLOW FOR LOOPEDNESS
HRLZ P1,T3 ;CONVERT TO AOBJN COUNTER
SKIPA P2,-T4(P) ;CALLER'S BUFFER BYTE POINTER
;LOOP READING THE RECORD, LH(P1) = BYTES TO GO, RH(P1) = BYTES RETURNED
ILMCY3: IDPB T2,P2 ;STORE ANOTHER DATA BYTE IN CALLER'S BUFFER
ILMCY4: SOSGE .IOIS1(T1) ;ANY DATA LEFT?
JRST ILMCY6 ;NOPE, ALL GONE
PUSHJ P,ILMCB ;INPUT THIS 8-BIT BYTE
JRST ILMCY8 ;I/O ERROR?
ADDM T2,.IOIS5(T1) ;ACCUMULATE MACY11 CHECKSUM
AOBJN P1,ILMCY3 ;LOOP FOR REST OF RECORD
SOJA P1,ILMCY4 ;RECORD OVERFLEW USER'S BUFFER, DISCARD DATA
ILMCY6: PUSHJ P,ILMCB ;READ CHECKSUM BYTE
JRST ILMCY8 ;OH BOTHER
SETZM .IOIS3(T1) ;CLEAR RECORD STATE
HRRZM P1,-T3(P) ;RETURN COUNT OF BYTES STORED FOR CALLER
JUMPL P1,.POPJ1## ;SUCCESSFUL RETURN IF RECORD FIT CALLER'S BUFFER
MOVEI M0,$EIRTB ;OOPS - RECORD TOO BIG FOR CALLER'S BUFFER
POPJ P, ;C'EST LA VIE!
;HERE ON I/O ERROR READING RECORD
ILMCY8: HRRZM P1,-T3(P) ;RETURN WHAT WE MANAGED TO READ
POPJ P, ;PROPAGATE ERROR RETURN
; NOTE THAT .IOIS3 IS "IN-A-RECORD-STATE"
; AND WILL EAT THE REST OF THE RECORD UPON
; SUBSEQUENT CALLS.
; THIS WON'T WORK IN NON-BLOCKING MODE!
;ILMCR - MACY11 RECORD STARTUP
ILMCR: SKIPL T4,.IOIS3(T1) ;GET RECORD STATE, USUALLY 0 = START NEW RECORD
CAILE T4,^D12 ;LOOK GOOD?
STOPCD <Record state (.IOIS3) trashed in ILMCR>
JRST @ILMCTA(T4) ;YES, START/RESUME RECORD STARTUP
;HERE TO START UP A NEW MACY11 INPUT DATA RECORD
;STAGE 0 - SEARCH FOR "000001" RECORD STARTUP
ILMCR0: PUSHJ P,ILMCB ;GET A PACKED BYTE
POPJ P, ;DIED?
JUMPE T2,ILMCR0 ;EAT THE NULLS (RECORD FILLER)
CAIE T2,1 ;MUST BE THE LOW ORDER OF "000001"
JRST ILMCRE ;NO, RECORD FORMAT ERROR
AOS .IOIS3(T1) ;STAGE ONE
ILMCR1: PUSHJ P,ILMCB ;GET THE HIGH-ORDER "000001"
POPJ P, ;DIED
JUMPN T2,ILMCRE ;IF NOT 0 THEN BAD RECORD FORMAT
AOS .IOIS3(T1) ;STAGE TWO
ILMCR2: PUSHJ P,ILMCB ;GET LOW-ORDER LENGTH
POPJ P, ;DIED
MOVEM T2,.IOIS1(T1) ;HANG ON TO IT
AOS .IOIS3(T1) ;STAGE THREE
ILMCR3: PUSHJ P,ILMCB ;GET HIGH-ORDER LENGTH BYTE
POPJ P, ;DIED
LSH T2,^D08 ;POSITION
IOR T2,.IOIS1(T1) ;AND GET FULL RECORD LENGTH
SUBI T2,6 ;DISCOUNT RECORD HEADER
MOVEM T2,.IOIS1(T1) ;SET DATA BYTE COUNT
AOS .IOIS3(T1) ;STAGE FOUR
ILMCR4: PUSHJ P,ILMCB ;GET LOW-ORDER ADDRESS
POPJ P, ;DIED
MOVEM T2,.IOIS0(T1) ;STASH IT AWAY
AOS .IOIS3(T1) ;STAGE FIVE
ILMCR5: PUSHJ P,ILMCB ;GET HIGH-ORDER ADDRESS
POPJ P, ;DIED
LSH T2,^D08 ;POSITION
IORM T2,.IOIS0(T1) ;GENERATE RECORD "ADDRESS"
AOS .IOIS3(T1) ;STAGE SIX (IN A RECORD)
SETZM .IOIS5(T1) ;INITIALIZE CHECKSUM VALUE
JRST .POPJ1## ;SUCCESSFUL RETURN, READY TO READ DATA
;HERE WHEN ERROR READING A RECORD, FINISH OFF THE STATED LENGTH
ILMCR6: PUSHJ P,ILMCB ;EAT A BYTE
POPJ P, ;HO HUM
SOSL .IOIS1(T1) ;STILL MORE TO DO (INC CHECKSUM BYTE)?
JRST ILMCR6 ;YES
SETZM .IOIS3(T1) ;NO, FINISHED OFF OLD RECORD,
JRST ILMCR0 ;START UP A NEW RECORD
;HERE ON BAD RECORD FORMAT
ILMCRE: MOVEI M0,^D10 ;STAGE "10"
MOVEM M0,.IOOS3(T1) ;SET DISPATCH
MOVEI M0,$EIRFE ;RECORD FORMAT ERROR
POPJ P, ;ERROR RETURN
;HERE ON RECORD FORMAT ERROR CONTINUATION, LOOK FOR "000001"
;THERE IS NO REALLY RELIABLE WAY TO RECOVER FROM A CORRUPTED FILE,
;BUT THIS AT LEAST GIVES THE USER A FIGHTING CHANCE
ILMCS0: MOVEI T2,^D10 ;WE ARE STAGE TEN
MOVEM T2,.IOIS3(T1) ;NOTE THAT (IN CASE HERE FROM ILMCS1)
PUSHJ P,ILMCB ;GET ANOTHER BYTE
POPJ P, ;DIED?
JUMPN T2,ILMCS0 ;SEARCH FOR 000
PUSHJ P,ILMCB ;GET ANOTHER BYTE
POPJ P, ;DIED?
JUMPN T2,ILMCS0 ;(MACY11 ALWAYS HAS FILLER BETWEEN RECORDS)
PUSHJ P,ILMCB ;GET ANOTHER BYTE
POPJ P, ;DIED?
JUMPN T2,ILMCS0 ;WANT THREE FILLER BYTES
AOS .IOIS3(T1) ;STAGE ELEVEN
ILMCS1: PUSHJ P,ILMCB ;GET ANOTHER BYTE
POPJ P, ;DIED?
JUMPE T2,ILMCS1 ;GOBBLE UP THE RECORD FILLERS
CAIE T2,001 ;LOOK LIKE A RECORD STARTUP?
JRST ILMCS0 ;NO, BACK TO STAGE TEN
AOS .IOIS3(T1) ;STAGE TWELVE
ILMCS2: PUSHJ P,ILMCB ;GET ANOTHER BYTE
POPJ P, ;OH WELL
JUMPN T2,ILMCS0 ;IF NOT "000001" THEN NOT START OF RECORD
MOVEI T3,2 ;YES, ENTER STAGE TWO
MOVEM T3,.IOIS3(T1) ;SET NEW RECORD PROCESSING STAGE
JRST ILMCR2 ;AND DISPATCH TO NEW STATE
;HERE TO INPUT ONE PHYSICAL 8-BIT MACY11-PACKED BYTE
;
;THIS IS NOT CALLED AS AN ISR!
ILMCB: SOSGE T2,.IOIS2(T1) ;ADVANCE [UN]PACKING STATE
JRST ILMCB5 ;NEED A NEW WORD
ILMCB1: LDB T2,ILMCTB(T2) ;EXTRACT NEW CURRENT PACKED BYTE
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
ILMCB5: PUSHJ P,ILBYT ;ADVANCE TO ANOTHER -10 WORD
POPJ P, ;ERROR
MOVEM T2,.IOIS4(T1) ;SAVE LATEST 4 PACKED BYTES
MOVEI T2,3 ;VIRGIN UNPACKING STATE IS 4 BYTES LEFT
MOVEM T2,.IOIS2(T1) ;SET FOR ILMCB
JRST ILMCB1 ;AND INPUT THE FIRST ONE
;MACY11 TABLES
;RECORD STARTUP STATE DISPATCH TABLE (USED IN ERROR RETRY)
ILMCTA: IFIW ILMCR0 ;STAGE 0
IFIW ILMCR1 ;STAGE 1
IFIW ILMCR2 ;STAGE 2
IFIW ILMCR3 ;STAGE 3
IFIW ILMCR4 ;STAGE 4
IFIW ILMCR5 ;STAGE 5
IFIW ILMCR6 ;STAGE 6
IFIW [STOPCD] ;STAGE 7
IFIW [STOPCD] ;STAGE 8
IFIW [STOPCD] ;STAGE 9
IFIW ILMCS0 ;STAGE 10
IFIW ILMCS1 ;STAGE 11
IFIW ILMCS2 ;STAGE 12
;BYTE-PACKING (36-BIT WORD IN .IOIS4)
ILMCTB: POINT 8,.IOIS4(T1),27 ;BYTE 4
POINT 8,.IOIS4(T1),35 ;BYTE 3
POINT 8,.IOIS4(T1),9 ;BYTE 2
POINT 8,.IOIS4(T1),17 ;BYTE 1
;ILBUF -- INPUT, LOCAL, GET NEXT BUFFER FROM MONITOR
ILBUF: PUSHJ P,.SACIO## ;SET IO
ILBUF0: PUSHJ P,TSAV14## ;PRESERVE THE USER'S T'S
;ASK FOR ANOTHER BUFFER OF DATA
ILBUF1: HRLZ T2,.IOCHN(IO) ;I/O CHANNEL NUMBER
HRRI T2,.FOINP ;"INPUT" FUNCTION
MOVE T1,[1,,T2] ;FILOP. ARG POINTER TO
FILOP. T1, ;READ NEW BUFFER
JRST ILBUF4 ;HMMM, CHECK OUT POSSIBLE ERROR
SKIPG .IOIBC(IO) ;ENSURE THAT THE MONITOR GAVE US SOMETHING
STOPCD <FILOP IN returned successfully with no data in ILBUF>
AOS .IOIUC(IO) ;INCREMENT IN UUO COUNT
JRST .POPJ1## ;SUCCESSFUL RETURN
;CHECK OUT INPUT EXCEPTION CONDITION
ILBUF4: TXNE T1,IO.EOF!IO.ERR;ERROR AND/OR END OF FILE?
JRST ILBUF6 ;YES, GO HANDLE
MOVE T3,.IOIOM(IO) ;GET I/O MODE
TXNN T3,IM.AIO ;FILE OPEN FOR NON-BLOCKING I/O?
STOPCD <FILOP IN failed with no error/EOF bits in ILBUF>
MOVX T1,$SCNBI ;SCHEDULER - NON-BLOCKING INPUT
PUSHJ P,@.IOSCH(IO) ;CALL THE SCHEDULER
POPJ P, ;DUH?
JRST ILBUF1 ;TRY INPUTTING AGAIN
;ERROR OR END OF FILE
ILBUF6: TXNN T1,IO.ERR ;ERROR?
JRST IEIEF ;NO, EOF, SET INPUT END OF FILE
;I/O ERROR, TRY TO FIGURE OUT WHAT HAPPENED
MOVEM T1,.I1IOS(IO) ;SAVE TOPS-10 I/O STATUS WORD
TXC T1,IO.ERR ;FLIP ALL THE BITS
TXCN T1,IO.ERR ;WERE ALL BITS SET?
JRST ILBUE3 ;YES, EXTENDED I/O ERROR STATUS
LDB T2,[POINTR .I1DTY(IO),TY.DEV] ;GET DEVICE TYPE
CAIN T2,.TYDSK ;IS IT A DISK?
JRST ILBUD1 ;YES, MORE GUESSWORK INVOLVED
;RANDOM I/O ERROR ENCODED INTO IO.ERR, TRANSLATE DIRECTLY AND RETURN
ILBUE1: TXNE T1,IO.BKT ;"BLOCK TOO LARGE" ?
MOVEI M0,$EIBKT ;YES
TXNE T1,IO.DTE ;"DATA CHECKSUM/PARITY ERROR" ?
MOVEI M0,$EIDAT ;YES
TXNE T1,IO.DER ;"DEVICE ERROR"
MOVEI M0,$EIDEV ;YES
TXNE T1,IO.IMP ;"IMPROPER MODE"
MOVEI M0,$EIIMP ;YES
POPJ P, ;RETURN I/O ERROR
;EXTENDED I/O ERROR, NEED TO RETRIEVE EXTENDED ERROR CODE
ILBUE3: PUSHJ P,IOERX1 ;RETRIEVE AND TRANSLATE EXTENDED I/O ERROR CODE
MOVSI M0,$EIXXX ;UNKNOWN ERROR
HLRZ M0,M0 ;POSITION INPUT TRANSLATION
POPJ P, ;RETURN I/O ERROR
;DISK ERROR, SNIFF AROUND A BIT
ILBUD1: MOVE T2,.IOCHN(IO) ;I/O CHANNEL
MOVEM T2,.I1NSP+.DCNAM(IO) ;SET IN DSKCHR BLOCK
MOVSI T2,.I1NSL ;LENGTH AND
HRRI T2,.I1NSP(IO) ;ADDRESS OF DSKCHR BLOCK
DSKCHR T2, ;READ ALL ABOUT THAT UNIT/STRUCTURE
JRST ILBUE1 ;FORGET IT
MOVEI M0,$EIOFL ;DEVICE OFFLINE
TXNE T2,DC.OFL ;IS DISK UNIT OFFLINE?
POPJ P, ;YES, ERROR
JRST ILBUE1 ;NOTHING MUCH FOR NOW
;IOIIE -- INPUT, ERROR, INPUT-NOT-OPEN
ENTRY .IOIIE
.IOIIE: MOVX M0,$EIINO ;INPUT-NOT-OPEN STATUS
POPJ P, ;RETURN ERROR CODE
;IEIEF -- INPUT, ERROR, END-OF-FILE
IEIEF: XMOVEI M0,IEIEF1 ;ADDRESS TO KEEP RETURNING EOF
MOVEM M0,.IOISR(IO) ;SET NEW INPUT STATE
IEIEF1: MOVEI M0,$EIEOF ;END-OF-FILE STATUS
POPJ P, ;RETURN EXCEPTION CODE
;INITIALIZE FOR REMOTE FILE READ
IRINI: MOVD1 T1,ORG ;GET FILE ORGANIZATION
CAIE T1,$DVOSQ ;IS IT SEQUENTIAL?
STOPCD <DAP file organization not "sequential" in IRINI>
MOVE T1,.IOIOC(IO) ;GET I/O CONTROL
TXNE T1,IC.BLK!IC.DMP;FUNNY MODE SET?
STOPCD <Block/Dump mode selected in IRINI>
;LOOKS OK, INITIALIZE VARIABLES AS NEEDED
MOVEI T1,177777 ;CRC POLYNOMIAL SEED
MOVEM T1,.IODIK(IO) ;SET FOR FILE DATA CRC COMPUTATION
;DISPATCH TO DATATYPE-DEPENDENT FINAL INITIALIZATION
MOVD T1,DTY ;GET DAP DATA TYPE FIELD
TFNE T1,ASC ;ASCII CHARACTER DATA?
JRST IRIA ;YES
TFNE T1,IMG ;BINARY (IMAGE) DATA?
JRST IRIB ;YES
STOPCD <DAP data type neither ASCII nor binary in IRINI>
;INITIALIZE FOR REMOTE ASCII CHARACTER DATA READ
IRIA: MOVE T1,.IOIOC(IO) ;GET I/O CONTROL FLAGS
TXNE T1,IC.RSI ;WANTING BYTE MODE I PRESUME
STOPCD <Record-structured I/O selected in IRIA>
MOVD1 T2,RFM ;RECORD FORMAT
MOVD T3,RAT ;RECORD ATTRIBUTES FLAGS
TFZ T3,<MCY,NSB> ;REMOTE MACY11-PACKING DOESN'T AFFECT US
JSP T4,.CDISP## ;DISPATCH ON FORMAT TYPE
IRIA10,,$DVFNR ;"NO FORMAT"
IRIA10,,$DVFFX ;FIXED-LENGTH RECORDS
IRIA10,,$DVFVR ;VARIABLE-LENGTH RECORDS
IRIA10,,$DVFVF ;VARIABLE-LENGTH WITH FIXED CONTROL
IRIA10,,$DVFST ;ASCII "STREAM"
IRIA10,,$DVFSC ;ASCII "STREAM-CR"
IRIA10,,$DVFSL ;ASCII "STREAM-LF"
0 ;NONE OTHER
STOPCD <Unknown record format in IRIA>
;KNOWN FORMAT, CHECK OUT ATTRIBUTES
IRIA10: TFZ T3,<FCC,ILC,PRN,EFC,CCC,LSA> ;MASK OUT JUNK
FJUMPE T3,RAT,IRIA14 ;ERROR IF ANY RECORD ATTRIBUTES LEFT OVER
STOPCD <Unknown or illegal record format/attributes in IRIA>
IRIA14: MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNE T1,IO.NEP ;ACTIVE OR PASSIVE LINK?
JRST IRIA20 ;PASSIVE, NO STARTUP NEEDED
PUSHJ P,DPSII1## ;ACTIVE, NEED CONTROL(CONNECT), CONTROL(GET)
POPJ P, ;BUMMER
IRIA20: XMOVEI T2,IRAS ;ASCII INPUT SERVICE ROUTINE
MOVEM T2,.IOISR(IO) ;SET IN CDB DISPATCH
XMOVEI T2,IRACL ;ASCII CLOSE INPUT PROCESSOR
MOVEM T2,.IOISS(IO) ;SET SPECIAL SHUTDOWN FUNCTION
JRST .POPJ1## ;INPUT INITIALIZED
;HERE TO SHUTDOWN THE REMOTE ASCII INPUT DATA STREAM
;
; *** NOTE ***
;
; ENTERED FROM CLOSE AT SACIO LEVEL
IRACL: SKIPG T1,.IODIM(IO) ;IN A DAP MESSAGE?
JRST .POPJ1## ;NO, ALL SET THEN (CLOSE WILL EAT ANY NEW DATA)
CAIE T1,$DHDAT ;YES, IS IT DATA?
STOPCD <Non-data DAP message outstanding in IRACL>
PUSHJ P,RDEAT1## ;A DATA MESSAGE, SIMPLY EAT THE REST OF IT
POPJ P, ;FAILED?
JRST .POPJ1## ;READY FOR CLOSE TO DO ITS THING
;REMOTE ASCII ISR. HANDLES ALL FORMS (STREAM, VAX, ETC.)
IRAS: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
IRAS02: XMOVEI T1,IRAS ;NOT-WITHIN-A-RECORD STATE
MOVEM T1,.IOISR(IO) ;SET IN CASE OF ERROR RESTART
SKIPLE .IODIM(IO) ;BETTER NOT BE IN A MESSAGE
STOPCD <DAP input message in progress in IRAS>
PUSHJ P,RDMSG1## ;START UP A NEW MESSAGE
POPJ P, ;NETWORK DIED?
CAIN T2,$DHDAT ;IS IT EXPECTED DATA?
JRST IRAS20 ;YES, START UP A NEW TEXT RECORD
;INPUT MESSAGE NOT DATA, SEE IF STATUS (MAYBE EOF).
IRAS10: CAIE T2,$DHSTS ;LOOKING AT A STATUS MESSAGE?
JRST IRAS17 ;NO
PUSHJ P,RDSTS1## ;READ AND CONVERT THE DAP STATUS
POPJ P, ;ERROR READING STATUS?
CAIE M0,$EGOIP ;"OPERATION IN PROGRESS"
CAIN M0,$EGAOK ;"A-OK"
JRST IRAS02 ;YES, IGNORE IT, LOOK FOR A NEW ONE
CAIE M0,$EIEOF ;END OF FILE?
POPJ P, ;RETURN CODE (ERROR, ETC.)
MOVE T1,.IOISF(IO) ;GET INPUT SERVICE FLAGS
TXNE T1,IS.IVI ;VAX-PRINT-FILE FORMAT INITIALIZED?
TXNN T1,IS.IVC ;YES, WAS LAST THING <CR>?
JRST IEIEF ;NO TO ONE OF THE ABOVE, SET EOF STATUS
XMOVEI T1,IEIEF1 ;YES, FLAG TO RETURN EOF STATUS
MOVEM T1,.IOISR(IO) ;ON NEXT ISR CALL
MOVEI T2,.CHLFD ;MEANWHILE, GENERATE A TRAILING <LF> CHAR
PJRST IRAS47 ;AND RETURN THAT FOR THIS ISR CALL
IRAS17: MOVE M0,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN M0,IO.NEP ;ACTIVE OR PASSIVE LINK?
STOPCD <Received DAP message neither DATA nor STATUS in IRAS>
PUSHJ P,RDMSR1## ;PASSIVE, RE-EAT THE MESSAGE
POPJ P, ;DUH?
MOVEI M0,$EINMP ;TELL FAL THAT AN INPUT MESSAGE IS PENDING
POPJ P, ;TAKE EXCEPTION RETURN
;HERE TO START UP A NEW DATA RECORD, HANDLING ALL THE PERMUTATIONS . . .
IRAS20: PUSHJ P,RDDAT1## ;STARTUP DATA MESSAGE READING
POPJ P, ;ERROR?
MOVD1 P1,RFM ;GET RECORD FORMAT
MOVD P2,RAT ;AND RECORD ATTRIBUTES
CAIE P1,$DVFVF ;VARIABLE WITH FIXED CONTROL HEADER?
JRST IRAS30 ;NO, ALL OTHERS ARE FAIRLY STRAIGHTFORWARD
;HERE FOR VARIABLE-LENGTH RECORDS WITH FIXED-LENGTH CONTROL HEADER
;IT MUST BE EITHER A VAX "PRINT" FILE, OR THE LINE-SEQUENCE NUMBER
;FOR LINE-SEQUENCED ASCII.
MOVD1 T3,FSZ ;GET FIXED-HEADER SIZE
JUMPE T3,IRAS30 ;IF 0, IGNORE IT
TFNE P2,LSA ;LINE-SEQUENCED ASCII?
JRST IRAS30 ;YES, HANDLED AT IRAS30
;HERE FOR NON-LSN FIXED CONTROL HEADERS (E.G., VAX PRINT FILE)
IRAS28: PUSHJ P,RDBYC0## ;GET LOW-ORDER HEADER BYTE
JRST IRAS29 ;ERROR, CAN'T END HERE
MOVEM T2,.IOISH(IO) ;SET LOW-ORDER HEADER BYTE
SOJLE T3,IRAS30 ;END OF HEADER?
PUSHJ P,RDBYC0## ;GET HIGH-ORDER HEADER BYTE
JRST IRAS29 ;ERROR, CAN'T END HERE
LSH T2,1*^D8 ;POSITION HIGH-ORDER BYTE
IORM T2,.IOISH(IO) ;AND MERGE IT IN
SOJLE T3,IRAS30 ;END OF HEADER?
PUSHJ P,RDBYC0## ;GET ANOTHER BYTE (???)
JRST IRAS29 ;ERROR, CAN'T END HERE
LSH T2,2*^D8 ;POSITION THIRD BYTE
IORM T2,.IOISH(IO) ;AND MERGE IT IN
SOJLE T3,IRAS30 ;END OF HEADER?
PUSHJ P,RDBYC0## ;GET ANOTHER BYTE (???)
JRST IRAS29 ;ERROR, CAN'T END HERE
LSH T3,2*^D8 ;POSITION FOURTH BYTE
IORM T2,.IOISH(IO) ;AND MERGE IT IN
SOJLE T3,IRAS30 ;END OF HEADER?
STOPCD <Fixed-header greater than four bytes in IRAS20>
;ERRORS
IRAS29: JUMPN M0,.POPJ## ;PROPAGATE NETWORK DEATH
MOVEI M0,$EIRFE ;RECORD FORMAT ERROR
POPJ P, ;RETURN OUR OWN ERROR
;NOW START THE ACTUAL DATA PORTION OF THE RECORD
IRAS30: MOVX T3,IS.IVI!IS.IVC;THE IMPORTANT CROSS-RECORD FLAG(S)
ANDM T3,.IOISF(IO) ;CLEAR OUT JUNK POSSIBLY LEFT BY ERROR
MOVX T3,IS.ICL!IS.ICE;THE IMPLIED <CR><LF> AT EOR FLAGS
TFZE P2,ILC ;IMPLIED <LF>-<CR> ENVELOPE?
IORM T3,.IOISF(IO) ;YES, FLAG [PROBABLY] NEED <CR><LF> AT EOR
; NOTE THAT VAX/VMS "STREAM-CR/LF" FORMATS
; COME ACCROSS WITH IMPLIED LFCR ATTRIBUTES
; WITH EMBEDDED CARRIAGE CONTROL WHICH WILL
; OVERRIDE IS.ICL (SEE IRAS60/FOLLOWING).
XMOVEI T1,IRAS60 ;IN-A-RECORD STATE DISPATCH
MOVEM T1,.IOISR(IO) ;SET NEW STATE DISPATCH
; THIS IS DONE HERE SO THAT SHOULD IRAFC/ETC
; GET AN ERROR, THE REST OF THE RECORD CAN
; CONTINUE TO BE READ, ALBEIT PROBABLY NOT
; CORRECTLY. HOWEVER, THIS SHOULD AT LEAST
; GIVE THE USER A CHANCE TO SEE THE DATA!
;NOW HANDLE THE FUNNY RECORD ATTRIBUTE CASES - FORTRAN, VAX PRINT FILE, ETC.
TFZE P2,PRN ;VAX "PRINT" FILE FORMAT?
JRST IRAS40 ;YES, HANDLE PRINT FILE FUNNIES
TFNE P2,LSA ;LINE SEQUENCED ASCII?
JSP P1,IRALS ;YES, HANDLE LSN
TFZE P2,CCC ;COBOL CARRIAGE CONTROL?
JSP P1,IRACC ;YES, HANDLE COBOL (???)
TFZE P2,FCC ;FORTRAN CARRIAGE CONTROL?
JSP P1,IRAFC ;YES, HANDLE FORTRAN SILLYNESS
IRAS36: MOVE T1,.IOIOC(IO) ;GET I/O CONTROL
TFNE P2,LSA ;IS LSN AVAILABLE?
TXNN T1,IC.LSN ; AND DOES THE USER WANT LSN'S?
JRST IRAS61 ;NO, JUST RETURN DATA
MOVE T1,.IOISH(IO) ;GET FIXED-LENGTH HEADER WORD
MOVEM T1,-T2(P) ;AND SET TO RETURN IT
MOVEI M0,$EILSN ;FLAG LSN EXCEPTION RETURN
POPJ P, ;AND GIVE THE CALLER THE LSN
;HERE TO HANDLE VAX PRINT-FILE FORMAT RECORDS
;
;Each record has a two-byte fixed-length header which is interpreted
;as a prefix carriage-control byte and a postfix carriage-control byte.
;
;Each carriage-control byte is interpreted as follows:
;
; BIT 7 6 5 4 3 2 1 0
;
; 0 <====LF COUNT=====> ;Count of line feeds
; 1 0 0 <=CTL CHAR==> ;Control character 000 - 037
; 1 1 0 <=CTL CHAR==> ;Control character 200 - 237
; 1 x 1 x x x x x ;Reserved/Unimplemented
;FIRST, SAVE POSTFIX CARRIAGE CONTROL FOR EVENTUAL END-OF-RECORD (IRAS90)
IRAS40: LDB T2,[POINTR .IOISH(IO),^O377_^D08] ;GET POSTFIX CARRIAGE-CONTROL
JUMPE T2,IRAS45 ;IF NULL, NO POSTFIX CARRIAGE CONTROL
TRZE T2,200 ;LINEFEEDS OR CHARACTER?
JRST IRAS42 ;CHARACTER
MOVX T1,IS.INL ;LINEFEED(S), THE "N" LINEFEEDS FLAG
IORM T1,.IOISF(IO) ;SET IN I/O FLAGS
JRST IRAS44 ;AND SET IS.IXX TO LF COUNT
IRAS42: TRZE T2,100 ;UPPER OR LOWER CONTROL?
TRO T2,200 ;UPPER
TRZE T2,40 ;RESERVED?
MOVEI T2,"?" ;*** NEEDS ERROR CODE DEFERRED
IRAS44: DPB T2,[POINTR .IOISF(IO),IS.IXX] ;SAVE POSTFIX CONTROL CHARACTER
;NOW PROCESS PREFIX CARRIAGE-CONTROL
IRAS45: LDB T2,[POINTR .IOISH(IO),^O377_^D00] ;GET PREFIX CARRIAGE-CONTROL
JUMPE T2,IRAS61 ;IF NULL, START UP DATA
TRZN T2,200 ;LINEFEED(S) OR CHARACTER
JRST IRAS48 ;LINEFEED(S)
TRZE T2,100 ;UPPER OR LOWER CONTROL?
TRO T2,200 ;UPPER
TRZE T2,40 ;RESERVED?
MOVEI T2,"?" ;*** NEEDS ERROR CODE NOW
IRAS47: MOVEM T2,-T2(P) ;POSITION RETURNED DATA CHARACTER
JRST .POPJ1## ;RETURN "DATA" CHARACTER TO USER
;LEADING <LF>'S
IRAS48: MOVX T1,IS.IVI ;THE "INITIALIZED" FLAG
TDNN T1,.IOISF(IO) ;IS THIS FIRST TIME HERE?
JRST [IORM T1,.IOISF(IO) ;YES, FLAG THAT FACT
SOJE T2,IRAS61 ;SUPPRESS FIRST LEADING <LF>
JRST .+1] ;MULTIPLE LEADING <LF>S
MOVEM T2,.IOIS0(IO) ;SAVE LF COUNT
MOVEI T2,.CHLFD ;RETURN A <LF> CHARACTER
XMOVEI T1,IRAS49 ;SPECIAL HACK ISR FOR MULTIPLE LFS
SOSE .IOIS0(IO) ;NEED MORE THAN ONE LF?
MOVEM T1,.IOISR(IO) ;YES
JRST IRAS47 ;RETURN THIS LINEFEED
;SPECIAL INTERMEDIATE ISR FOR MULTIPLE-LINEFEEDS
IRAS49: SOSGE .IOIS0(T1) ;NEED ANOTHER LINEFEED?
JRST IRAS60 ;NO
MOVEI T2,.CHLFD ;YES
JRST .POPJ1## ;SUCCESS RETURN WITH "DATA" CHARACTER
;HERE TO START UP AN ASCII DATA RECORD
;ENTER HERE AS AN ISR
IRAS60: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S
IRAS61: MOVD1 T1,RFM ;DAP RECORD FORMAT
CAIN T1,$DVFNR ;UNFORMATTED ASCII?
JRST IRAS63 ;YES, SIMPLEST CASE (NO PROCESSING NEEDED)
CAIE T1,$DVFSC ;ASCII "STREAM-CR"?
CAIN T1,$DVFSL ;ASCII "STREAM-LF"?
JRST IRAS70 ;YES, WEIRD TWIST ON G.P. ASCII ISR
JRST IRAS80 ;NO, USE GENERAL-PURPOSE NETWORK ASCII ISR
;HERE TO DEAL WITH UNFORMATTED ASCII (E.G., TOPS10)
IRAS63: XMOVEI T2,IRAS65 ;SELECT UNFORMATTED ASCII ISR
MOVEM T2,.IOISR(IO) ;AND SET IT FOR FUTURE CALLS
MOVE T1,IO ;REPOSITION CDB ADDRESS
PUSHJ P,IRAS65 ;GET FIRST CHARACTER IN DAP "RECORD"
POPJ P, ;PROPAGATE ERROR TO USER
MOVEM T2,-T2(P) ;POSITION RETURN DATA BYTE
JRST .POPJ1## ;SUCCESS RETURN
;ENTER HERE AS AN ISR (UNFORMATTED ASCII)
IRAS65: PUSHJ P,.RDBYC## ;GET A DATA BYTE
CAIA ;OOPS, ERROR/EXCEPTION RETURN
JRST .POPJ1## ;SUCCESS RETURN WITH DATA BYTE IN T2
;GOT ERROR/EXCEPTION, MUST SWITCH TO "IRASXX CONTEXT" TO PROCESS ERROR
PUSHJ P,.SACIO## ;SELECT I/O CONTEXT
PUSHJ P,.SAVE4## ;PROTECT THE P'S
PUSHJ P,TSAV14## ;PROTECT THE T'S
JRST IRAS90 ;DECIPHER THE ERROR/EXCEPTION RETURN
;HERE TO DEAL WITH ASCII "STREAM-CR" OR "STREAM-LF" RECORDS
IRAS70: XMOVEI T2,IRAS72 ;SELECT "STREAM-CR/LF" ISR
MOVEM T2,.IOISR(IO) ;AND SET IT FOR FUTURE CALLS
JRST IRAS73 ;FIRE UP FIRST DATA CHARACTER
;ENTER HERE AS AN ISR
IRAS72: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S
IRAS73: PUSHJ P,RDBYC1## ;GET NEXT DAP DATA BYTE
JRST IRAS90 ;NO MORE DATA BYTES?
MOVEM T2,-T2(P) ;POSITION RETURN DATA BYTE
CAIGE T2," " ;IF NOT CONTROL CHARACTER
CAIN T2,.CHTAB ;OR IF A TAB
JRST .POPJ1## ;THEN SUCCESSFUL RETURN NOW
;EMBEDDED CONTROL CHARACTER, SEE IF END OF RECORD
MOVD1 T1,RFM ;GET DAP RECORD FORMAT FIELD
CAIN T1,$DVFSC ;ASCII "STREAM-CR" FORMAT?
CAIE T2,.CHCRT ;YES, IS THIS A <CR>?
CAIA ;NO
JRST IRAS75 ;STREAM-CR AND A <CR>, SEE IF EOR
CAIN T1,$DVFSL ;ASCII "STREAM-LF" FORMAT?
CAIE T2,.CHLFD ;YES, IS THIS A <LF>?
JRST IRAS85 ;NO, TREAT AS RANDOM EMBEDDED CONTROL CHAR
;CHECK FOR EOR, IF SO THEN TIME TO GENERATE <CR><LF> SEQUENCE
IRAS75: PUSHJ P,RDBYT1## ;READ ANOTHER DAP DATA BYTE
JRST IRAS76 ;NO MORE DATA (WHICH IS WHAT WE WANT HERE)
HRROM T2,.IODIR(IO) ;FLAG DATA BYTE TO BE RE-READ NEXT CALL
JRST IRAS87 ;TREAT AS RANDOM EMBEDDED CARRIAGE CONTROL
IRAS76: HRLI M0,400000 ;FLAG EXCEPTION RETURN
MOVEM M0,.IODIR(IO) ;FOR NEXT CALL TO RDBYT
TRNE M0,777777 ;HIT A REAL ERROR, OR JUST NO MORE DATA?
JRST IRAS87 ;ERROR, RETURN CHAR NOW, ERROR NEXT CALL
MOVEI T2,.CHCRT ;EOR, RETURN <CR> FIRST
MOVEM T2,-T2(P) ;SET RETURN DATA BYTE
MOVX T1,IS.ILF ;THE LF-AT-EOR FLAG
IORM T1,.IOISF(IO) ;MARK THAT WE NEED A <LF> LATER
JRST IRAS87 ;SUCCESS RETURN, CLEARING IMPLIED LFCR
;GENERAL PURPOSE NETWORK ASCII ISR, HANDLING MOST OF THE RECORD-STRUCTURED
;CASES, RSX/VAX IMPLIED LFCR, "PRINT" FILES, ETC.)
IRAS80: XMOVEI M0,IRAS82 ;SELECT THE G.P. ASCII ISR
MOVEM M0,.IOISR(IO) ;AND SET IT FOR FUTURE CALLS
JRST IRAS83 ;GO READ FIRST DATA CHARACTER
;ENTER HERE AS AN ISR
IRAS82: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S
IRAS83: PUSHJ P,RDBYC1## ;GET NEXT DAP DATA BYTE
JRST IRAS90 ;NO MORE DATA BYTES?
MOVEM T2,-T2(P) ;POSITION RETURN DATA BYTE
CAIGE T2," " ;IF NOT CONTROL CHARACTER
CAIN T2,.CHTAB ;OR IF A TAB
CAIA ;DATA CHARACTER, MANIPULATE ICL IF NECESSARY
JRST IRAS85 ;EMBEDDED CONTROL
;WE HAVE A LIVE DATA CHARACTER. HOWEVER, A PRECEEDING IMBEDDED CONTROL
;CHARACTER COULD HAVE CLEARED IS.ICL. TO PREVENT CONCATENATING THE NEXT
;RECORD TO THIS ONE, WE WANT TO RE-SET IS.ICL IF IT ONCE WAS SET. IS.ICE
;TELLS ALL.
MOVX M0,IS.ICE ;WAS IMPLIED <CR><LF> ENVELOPE SET AT START
TDNN M0,.IOISF(IO) ;OF THIS RECORD?
JRST .POPJ1## ;NO, SUCCESSFUL RETURN
MOVX M0,IS.ICL ;YES, RE-SET IT NOW
IORM M0,.IOISF(IO) ;TO PREVENT GRATITUIOUS CONCATENATIONS
JRST .POPJ1## ;SUCCESSFUL RETURN
;EMBEDDED CONTROL CHARACTER, CHECK IT OUT
IRAS85: CAIL T2,.CHLFD ;IF A <LF>, <VT>, OR <FF>
CAILE T2,.CHFFD ; . . .
CAIL T2,.CHDLE ;OR A <DLE>, <DC1>, <DC2>, <DC3>, OR <DC4>
CAILE T2,.CHDC4 ; . . .
CAIL T2,.CHCNZ ;OR A <SUB>, OR <ESC>
CAILE T2,.CHESC ; . . .
JRST .POPJ1## ;RETURN RANDOM CONTROL CHARACTER
IRAS87: MOVX M0,IS.ICL ;THE IMPLIED <CR><LF> FLAG
ANDCAM M0,.IOISF(IO) ;EMBEDDED CARRIAGE-CONTROL ENCOUNTERED
JRST .POPJ1## ;RETURN ASCII CHARACTER
;HERE AT EOR, CHECK FOR IMPLIED <CR><LF> ETC.
IRAS90: JUMPE M0,IRAS92 ;OK IF JUST EOR
POPJ P, ;ELSE REAL ERROR, DIE
;ENTER HERE AS AN ISR
IRAS91: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14 ;AND THE T'S TOO
IRAS92: MOVX T1,IS.ICE ;CLEAR IMPLIED CRLF ENVELOPE FLAGE
ANDCAB T1,.IOISF(IO) ;IN CASE SET, AND GET STATUS
JUMPE T1,IRAS02 ;IF NOTHING SPECIAL PENDING, START UP A NEW REC
TXNE T1,IS.INL ;"N" LINEFEED-FLAG SET?
JRST IRAS97 ;YES
TXZE T1,IS.ICL ;IMPLIED <CR><LF> STILL PENDING?
TXO T1,IS.ICR!IS.ILF;YES, FLAG NEED <CR> AND <LF>
MOVEI T2,.CHCRT ;A <CR>
TXZE T1,IS.ICR ;NEED A <CR>?
JRST IRAS99 ;YES
MOVEI T2,.CHLFD ;A <LF>
TXZE T1,IS.ILF ;NEED A <LF>?
JRST IRAS99 ;YES
LDB T2,[POINTR T1,IS.IXX] ;SPECIAL CHARACTER
TXZE T1,IS.IXX ;SPECIAL CHARACTER NEEDED?
JRST IRAS99 ;YES
TXZ T1,IS.IVI!IS.IVC;CLEAR JUNK FLAGS
JUMPE T1,IRAS02 ;AND START UP A NEW RECORD
STOPCD <Unknown ISF flags in IRAS90>
IRAS97: LDB T2,[POINTR T1,IS.IXX] ;[1044] COUNT OF LINEFEEDS REMAINING
SUBI T2,1 ;[1044] LESS THE ONE WE'RE ABOUT TO RETURN
DPB T2,[POINTR T1,IS.IXX] ;[1044] IS NEW COUNT OF LINEFEEDS REMAINING
TXNN T1,IS.IXX ;MORE LINEFEEDS COMING?
TXZ T1,IS.INL ;NO, CLEAR THE "N" LINEFEEDS FLAG
MOVEI T2,.CHLFD ;RETURN A <LF> CHARACTER
IRAS99: CAIE T2,.CHCRT ;RETURNING A <CR>?
TXZA T1,IS.IVC ;NO, LAST THING NOT A <CR>
TXO T1,IS.IVC ;YES, LAST THING IS A <CR>
MOVEM T1,.IOISF(IO) ;SAVE NEW EOR FLAGS
MOVEM T2,-T2(P) ;POSITION RETURN DATA
XMOVEI T1,IRAS91 ;SELECT NEW EOR ISR
MOVEM T1,.IOISR(IO) ;AND SET IT FOR CALLER
JRST .POPJ1## ;RETURN WITH ASCII DATA
;HELPERS FOR REMOTE ASCII INPUT
;IRACC -- COBOL CARRIAGE CONTROL
IRACC: STOPCD <COBOL carriage control not implemented>
;IRAFC -- FORTRAN CARRIAGE CONTROL
;CALL IS:
;
; JSP P1,IRAFC
;
;RETURN CPOPJ0 IF ERROR RETURN, CPOPJ1 IF VALID DATA BYTE, OR JRST (P1) IF
;NO DATA BYTE.
IRAFC: PUSHJ P,RDBYC0## ;GET THE FIRST BYTE OF THE RECORD
JRST IRAFE0 ;ERROR, IT MUST EXIST
MOVEI T4,IRAFCT ;THE CONVERSION TABLE
PUSHJ P,.CFIND## ;LOCATE CARRIAGE CONTROL
JRST IRAFE1 ;ERROR, UNKNOWN CARRIAGE CONTROL
MOVE T1,0(T1) ;FETCH CARRIAGE CONTROL SERVICE FLAGS
DPB T1,[POINTR .IOISF(IO),IS.IXX] ;STORE SPECIAL CONTROL (IF ANY)
TRZ T1,777 ;CLEAR OUT SPECIAL CHARACTER (IF ANY)
IORM T1,.IOISF(IO) ;SET NEW SERVICE FLAGS
JRST 0(P1) ;SUCCESSFUL RETURN (WITH NO DATA CHARACTER)
;ERROR - PREMATURE EOR
IRAFE0: JUMPN M0,.POPJ## ;PROPAGATE NETWORK DEATH
PUSHJ P,RDEAT0## ;FLUSH RECORD REMNANTS
JFCL ;HO HUM
MOVEI M0,$EIEOR ;PREMATURE END-OF-RECORD ERROR
POPJ P, ;RETURN ERROR CONDITION
;ERROR - UNKNOWN CARRIAGE CONTROL
IRAFE1: PUSHJ P,RDBYR0## ;RETURN DATA BYTE TO BE RE-READ
JFCL ;HO HUM
MOVEI M0,$EIFCC ;ILLEGAL FORTRAN CARRIAGE CONTROL
POPJ P, ;ERROR RETURN
;THE FORTRAN CARRIAGE CONTROL TRANSLATION TABLE
IRAFCT: XWD [IS.ICR!IS.ILF], " " ;SINGLE-SPACE TEXT LINE
XWD [IS.ICR!IS.INL+2], "0" ;DOUBLE-SPACE TEXT LINE
XWD [IS.ICR!IS.INL+3], "-" ;TRIPLE-SPACE TEXT LINE
XWD [IS.ICR+.CHFFD], "1" ;NORMAL TEXT PAGE
XWD [IS.ICR+.CHDLE], "2" ;1/2 PAGE SKIP
XWD [IS.ICR+.CHVTB], "3" ;1/3 PAGE SKIP
XWD [IS.ICR+.CHDC4], "/" ;1/6 PAGE SKIP
XWD [IS.ICR+.CHDC3], "*" ;1/10 PAGE SKIP
XWD [IS.ICR+.CHDC2], "." ;1/20 PAGE SKIP
XWD [IS.ICR+.CHDC1], "," ;1/30 PAGE SKIP
XWD [IS.ICR], "+" ;OVERPRINT LINE
0
;HERE FOR NETWORK LSN'S
IRALS: SETZB T4,.IOISH(IO) ;CLEAR OUT LSN TEMPLATE
MOVD1 T3,FSZ ;GET SIZE OF LSN "FIXED CONTROL" FIELD
JUMPE T3,(P1) ;IF EMPTY, JUST IGNORE IT
IRALS1: PUSHJ P,RDBYC0## ;GET FIXED-CONTROL CHARACTER
JRST IRAS29 ;ERROR, CAN'T END HERE
CAIE T2,0 ;IF NULL, OR
CAIN T2," " ;IF LEADING SPACE,
SOJG T3,IRALS1 ;JUST EAT IT
JUMPLE T3,(P1) ;IF NULL CONTROL HEADER, JUST IGNORE IT
CAIE T2,.CHFFD ;PAGE MARK?
JRST IRALS5 ;NO
MOVSI T2,(1B0) ;YES, FLAG IT
MOVEM T2,.IOISH(IO) ;AND SET IT FOR LATER
SOJLE T3,(P1) ;QUIT IF ONLY A PAGE MARK
IRALS4: PUSHJ P,RDBYC0## ;NEXT LSN DIGIT
JRST IRAS29 ;CAN'T END HERE
IRALS5: CAIN T2," " ;IF A SPACE
MOVEI T2,"0" ;THEN MAKE IT A ZERO
CAIL T2,"0" ;IF NOT AN ASCII DIGIT
CAILE T2,"9" ;IF NOT AN ASCII DIGIT
JRST [MOVEI M0,$EILLN ;ERROR CODE: LUDICROUS LSN
POPJ P,] ;BOMB THIS RECORD
IMULI T4,^D10 ;NEXT DECADE
ADDI T4,-"0"(T2) ;ACCUMULATE LSN AS AN INTEGER
SOJG T3,IRALS4 ;LOOP FOR REST OF LSN
HRRM T4,.IOISH(IO) ;SET THE ACTUAL LSN
JRST (P1) ;GO PROCESS ASCII DATA
;INITIALIZE FOR REMOTE BINARY DATA READ
IRIB: SETZ P1, ;NO ISR SELECTED YET
MOVE P2,.IOIOC(IO) ;FETCH I/O CONTROL FLAGS
MOVD1 T2,RFM ;RECORD FORMAT
MOVD T3,RAT ;RECORD ATTRIBUTES
TFZ T3,<MCY,NSB> ;MACY11-PACKING DOESN'T AFFECT US
JSP T4,.CDISP## ;DISPATCH ON RECORD FORMAT PROCESSING
IRIB10,,$DVFNR ;"NO FORMAT"
IRIB20,,$DVFFX ;FIXED-LENGTH RECORDS
IRIB20,,$DVFVR ;VARIABLE-LENGTH RECORDS
IRIB20,,$DVFVF ;VARIABLE-WITH-FIXED-HEADER RECORDS
IRIB30,,$DVFST ;ASCII "STREAM"
0 ;THAT'S ALL
STOPCD <Unknown record format in IRIB>
;"NO FORMAT" BINARY DATA (NO RECORD STRUCTURE)
IRIB10: MOVD1 T2,BSZ ;GET LOGICAL DATA BYTESIZE
CAIN T2,^D08 ;8-BIT BYTES?
XMOVEI P1,IRBB ;YES, EASIEST CASE
CAIN T2,^D36 ;36-BIT BYTES?
IRIB12: XMOVEI P1,IRBW ;YES, FAVORITE CASE
TXNE P2,IC.RSI ;TRYING FOR RECORDS?
STOPCD <Record-structured I/O selected in IRIB10>
JUMPN P1,IRIB80 ;GO SETUP DATA STREAM
IRIB13: STOPCD <DAP data bytesize neither 8 nor 36 in IRIB10>
;FIXED, VARIABLE, AND VARIABLE-WITH-FIXED-HEADER RECORDS
IRIB20: LDB T2,[POINTR .IOIOC(IO),IC.RFM] ;GET CONTROLLING /RECFORMAT
CAIN T2,.ICRF3 ;DOING 36PACK SHANANIGANS?
JRST IRIB12 ;YES . . .
MOVD1 T2,BSZ ;LOGICAL DATA BYTESIZE
JUMPN T2,IRIB22 ;VERIFY ITS SIZE
MOVEI T2,^D08 ;SUPPLY A DEFAULT
MOVD1M T2,BSZ ;TELL OTHERS ABOUT IT
IRIB22: CAIE T2,^D08 ;MUST BE 8-BIT BYTES (E.G., VAX ET AL)
STOPCD <DAP data bytesize not 8 in IRIB20>
XMOVEI P1,IRBR ;SELECT RECORD PROCESSOR
TXNN P2,IC.RSI ;IS USER EXPECTING RECORDS?
STOPCD <Record-structured I/O not selected in IRIB20>
JRST IRIB80 ;GO SETUP DATA STREAM
;ASCII STREAM
IRIB30: STOPCD <Binary data with "ASCII STREAM" format records in IRIB30>
;ISR SELECTED, ESTABLISH THE DATA STREAM
IRIB80: JUMPN P1,IRIB82 ;ERROR IF NO ISR SELECTED
STOPCD <No ISR selected in IRIB>
IRIB82: TFZE T3,<FCC,ILC,PRN,EFC,CCC,LSA> ;ASCII-LIKE ATTRIBUTES?
JRST [MOVEI M0,$EIBAI ;ASCII ATTR ILLEGAL FOR BINARY FILE
POPJ P,] ;TELL USER OF ERROR
FJUMPE T3,RAT,IRIB84 ;ERROR IF ANY RECORD ATTRIBUTES LEFT OVER
STOPCD <Unknown or illegal record format/attributes in IRIB>
IRIB84: MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNE T1,IO.NEP ;ACTIVE OR PASSIVE LINK?
JRST IRIB86 ;PASSIVE, NO STARTUP NEEDED
PUSHJ P,DPSII0## ;ACTIVE, NEED CONTROL(CONNECT), CONTROL(GET)
POPJ P, ;NETWORK DIED?
IRIB86: MOVEM P1,.IOISR(IO) ;SET INPUT SERVICE ROUTINE
XMOVEI P1,IRBCL ;SPECIAL CLOSE ROUTINE
MOVEM P1,.IOISS(IO) ;SPECIAL CLOSE PROCESSING REQUIRED
JRST .POPJ1## ;INPUT INITIALIZED
;HERE TO SHUTDOWN THE REMOTE BINARY INPUT DATA STREAM
;
; *** NOTE ***
;
; ENTERED FROM CLOSE AT SACIO LEVEL
IRBCL: SKIPG T1,.IODIM(IO) ;IN A DAP MESSAGE?
JRST .POPJ1## ;NO, ALL SET THEN (CLOSE WILL EAT ANY NEW DATA)
CAIE T1,$DHDAT ;YES, IS IT DATA?
STOPCD <Non-data DAP message outstanding in IRBCL>
PUSHJ P,RDEAT1## ;A DATA MESSAGE, SIMPLY EAT THE REST OF IT
POPJ P, ;FAILED?
JRST .POPJ1## ;READY FOR CLOSE TO DO ITS THING
;REMOTE BINARY 8-BIT BYTE ISR
IRBB: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
IRBB01: XMOVEI T4,IRBB ;NOT-WITHIN-A-RECORD STATE
MOVEM T4,.IOISR(IO) ;SET IN CASE OF ERROR RESTART
SKIPLE .IODIM(IO) ;BETTER NOT BE PROCESSING A DAP MESSAGE
STOPCD <DAP input message in progress in IRBB>
PUSHJ P,RDMSG0## ;START READING NEW MESSAGE
POPJ P, ;NETWORK DIED?
CAIE T2,$DHDAT ;DATA?
JRST IRBB10 ;NO
PUSHJ P,RDDAT0## ;READ TEMPLATED PORTION OF DATA MESSAGE
POPJ P, ;DIED?
XMOVEI T4,IRBB20 ;NOW-WITHIN-A-RECORD STATE
MOVEM T4,.IOISR(IO) ;SET NEW STATE DISPATCH
JRST IRBB21 ;READ FIRST DATA BYTE
;INPUT MESSAGE NOT DATA, SEE IF STATUS
IRBB10: CAIE T2,$DHSTS ;LOOKING AT A STATUS MESSAGE?
JRST IRBB17 ;NO
PUSHJ P,RDSTS0## ;READ AND TRANSLATE THE DAP STATUS
POPJ P, ;ERROR READING A STATUS MESSAGE?
CAIE M0,$EGOIP ;"OPERATION IN PROGRESS"
CAIN M0,$EGAOK ;"A-OK"
JRST IRBB01 ;YES, IGNORE IT
POPJ P, ;RETURN ERROR
IRBB17: MOVE M0,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN M0,IO.NEP ;ACTIVE OR PASSIVE LINK?
STOPCD <Received DAP message neither DATA nor STATUS in IRBB>
PUSHJ P,RDMSR0## ;PASSIVE, RE-EAT THE MESSAGE
POPJ P, ;DUH?
MOVEI M0,$EINMP ;TELL FAL THAT AN INPUT MESSAGE IS PENDING
POPJ P, ;TAKE EXCEPTION RETURN
;HERE TO READ NEXT DATA BYTE (ENTERED AS AN ISR)
IRBB20: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
IRBB21: PUSHJ P,RDBYC0## ;READ IN ANOTHER DATA BYTE
JRST IRBB25 ;MAYBE EOR
MOVEM T2,-T2(P) ;POSITION RETURN DATA BYTE
JRST .POPJ1## ;SUCCESSFUL RETURN
IRBB25: JUMPE M0,IRBB01 ;EOR, START UP A NEW RECORD
POPJ P, ;ERROR
;REMOTE BINARY 36-BIT WORD ISR
IRBW: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
IRBW01: XMOVEI T4,IRBW ;NOT-WITHIN-A-RECORD STATE
MOVEM T4,.IOISR(IO) ;SET IN CASE OF ERROR RESTART
SKIPLE .IODIM(IO) ;STILL IN A DAP MESSAGE?
STOPCD <DAP input message in progress in IRBW>
PUSHJ P,RDMSG0## ;START READING NEXT DAP MESSAGE
POPJ P, ;ERROR
CAIE T2,$DHDAT ;DATA MESSAGE?
JRST IRBW10 ;NO
PUSHJ P,RDDAT0## ;YES, START UP A DATA RECORD
POPJ P, ;DIED?
XMOVEI T4,IRBW20 ;NOW-WITHIN-A-RECORD STATE
MOVEM T4,.IOISR(IO) ;SET NEW STATE
JRST IRBW21 ;AND START READING NEW RECORD
;NOT A DATA MESSAGE, SEE IF STATUS (EOF, ETC.)
IRBW10: CAIE T2,$DHSTS ;STATUS?
JRST IRBW17 ;NO
PUSHJ P,RDSTS0## ;READ AND TRANSLATE THE DAP STATUS
POPJ P, ;DUH?
CAIE M0,$EGOIP ;"OPERATION IN PROGRESS"
CAIN M0,$EGAOK ;"A-OK"
JRST IRBW01 ;IGNORE
POPJ P, ;ERROR, EOF, ETC.
IRBW17: MOVE M0,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN M0,IO.NEP ;ACTIVE OR PASSIVE LINK?
STOPCD <Received DAP message neither DATA nor STATUS in IRBW>
PUSHJ P,RDMSR0## ;PASSIVE, RE-EAT THE MESSAGE
POPJ P, ;DUH?
MOVEI M0,$EINMP ;TELL FAL THAT AN INPUT MESSAGE IS PENDING
POPJ P, ;TAKE EXCEPTION RETURN
;HERE TO READ NEXT 36-BIT DATA WORD - DAP DATA BYTES 1 TO 4.5
;
;ENTERED AS AN ISR
IRBW20: PUSHJ P,.SACIO## ;SET I/O CONTEXT
PUSHJ P,TSAV14## ;AND THE T'S TOO
IRBW21: SKIPE T2,.IODIW(IO) ;GET SAVED PARTIAL WORD (IF ANY)
JRST IRBW31 ;ODD WORD
PUSHJ P,RDBYC0## ;GET FIRST DAP BYTE
JRST IRBW25 ;EOR?
MOVEM T2,-T2(P) ;POSITION AND SET BITS 28 - 35
PUSHJ P,RDBYC0## ;GET SECOND DAP BYTE
JRST IRBW28 ;THIS IS NOT ALLOWED
LSH T2,<1*^D08> ;POSITION
IORM T2,-T2(P) ; AND SET BITS 20 - 27
PUSHJ P,RDBYC0## ;GET THIRD DAP BYTE
JRST IRBW28 ;THIS IS NOT ALLOWED
LSH T2,<2*^D08> ;POSITION
IORM T2,-T2(P) ; AND SET BITS 12 - 19
PUSHJ P,RDBYC0## ;GET FOURTH DAP BYTE
JRST IRBW28 ;THIS IS NOT ALLOWED
LSH T2,<3*^D08> ;POSITION
IORM T2,-T2(P) ; AND SET BITS 04 - 11
PUSHJ P,RDBYC0## ;GET FOURTH AND A HALFTH DAP BYTE
JRST IRBW28 ;THIS IS NOT ALLOWED
LSHC T1,<4*^D08> ;POSITION
IORM T2,-T2(P) ; AND SET BITS 00 - 03
HRROM T1,.IODIW(IO) ;SAVE PARTIAL WORD
JRST .POPJ1## ;RETURN 36-BIT DATA BYTE
IRBW25: JUMPN M0,.POPJ## ;ERROR RETURN IF ERROR
SKIPN .IODIB(IO) ;EOR, SHOULD HAVE USED ALL BITS
JRST IRBW01 ;ALL SET, START UP A NEW RECORD
STOPCD <Unused bitcount non-zero in IRBW20>
IRBW28: JUMPN M0,.POPJ## ;ERROR RETURN IF ERROR
STOPCD <Premature DAP DATA end of message in IRBW20>
;HANDLE THE ODD WORD (DAP BYTES 4.5 TO 9)
IRBW31: HRRZM T2,-T2(P) ;SET PARTIAL WORD (LOW 4 BITS)
SETZM .IODIW(IO) ;CLEAR TRAILING PARTIAL WORD
PUSHJ P,RDBYC0## ;GET SIXTH DAP BYTE
JRST IRBW35 ;MAYBE NONE
LSH T2,<0*^D08>+4 ;POSITION
IORM T2,-T2(P) ; AND SET BITS 24 - 31
PUSHJ P,RDBYC0## ;GET SEVENTH DAP BYTE
JRST IRBW38 ;THIS IS NOT ALLOWED
LSH T2,<1*^D08>+4 ;POSITION
IORM T2,-T2(P) ; AND SET BITS 16 - 23
PUSHJ P,RDBYC0## ;GET EIGHTH DAP BYTE
JRST IRBW38 ;THIS IS NOT ALLOWED
LSH T2,<2*^D08>+4 ;POSITION
IORM T2,-T2(P) ; AND SET BITS 08 - 15
PUSHJ P,RDBYC0## ;GET NINTH (AND LAST) DAP BYTE
JRST IRBW38 ;THIS IS NOT ALLOWED
LSH T2,<3*^D08>+4 ;POSITION
IORM T2,-T2(P) ; AND SET BITS 00 - 07
JRST .POPJ1## ;RETURN WITH 36-BIT WORD
IRBW35: JUMPN M0,.POPJ## ;ERROR RETURN IF ERROR
MOVE T4,.IODIB(IO) ;GET UNUSED BIT COUNT
CAIN T4,4 ;HAD BETTER BE A HALF-BYTE
JRST IRBW01 ;OK, START READING NEXT RECORD
STOPCD <Unused bitcount not 4 in IRBW30>
IRBW38: JUMPN M0,.POPJ## ;ERROR RETURN IF REAL ERROR
STOPCD <Premature DAP DATA end of message in IRBW30>
;REMOTE BINARY 8-BIT BYTE RECORD-FORMATTED ISR
IRBR: PUSHJ P,.SACIO## ;SETUP I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
IRBR01: XMOVEI T4,IRBR ;NOT-WITHIN-A-RECORD STATE
MOVEM T4,.IOISR(IO) ;SET IN CASE OF ERROR RESTART
SKIPLE .IODIM(IO) ;BETTER NOT BE PROCESSING A DAP MESSAGE
STOPCD <DAP input message in progress in IRBR>
PUSHJ P,RDMSG1## ;START READING NEW MESSAGE
POPJ P, ;NETWORK DIED?
CAIE T2,$DHDAT ;DATA?
JRST IRBR70 ;NO
PUSHJ P,RDDAT1## ;READ TEMPLATED PORTION OF DATA MESSAGE
POPJ P, ;DIED?
MOVD T1,RCN ;FETCH "RECORD NUMBER"
MOVEM T2,-T2(P) ;AND RETURN TO CALLER (FOR WHAT IT'S WORTH)
MOVN T3,-T3(P) ;CALLER'S MAX RECORD SIZE
SUBI T3,1 ;ALLOW FOR AOBJN
HRLZ P1,T3 ;MAKE BYTE COUNTER/LOOPER
SKIPA P2,-T4(P) ;FETCH CALLER'S RECORD BUFFER STUFFER
;HERE TO READ NEXT DATA BYTE
IRBR20: IDPB T2,P2 ;STASH ANOTHER RECORD BYTE
IRBR21: PUSHJ P,RDBYC1## ;READ IN ANOTHER DATA BYTE
JRST IRBR25 ;MAYBE EOR
AOBJN P1,IRBR20 ;RETURN DATA TO CALLER
SOJA P1,IRBR21 ;DATA OVERFLEW USER'S BUFFER, DISCARD
IRBR25: HRRZM P1,-T3(P) ;RETURN COUNT OF BYTES STUFFED
JUMPN M0,.POPJ## ;IF ERROR, PROPAGATE IT
JUMPL P1,.POPJ1## ;RETURN DATA RECORD
MOVEI M0,$EIRTB ;OOPS - RECORD WAS TOO BIG, DATA LOST!
POPJ P, ;TOO BAD
;INPUT MESSAGE NOT DATA, SEE IF STATUS
IRBR70: CAIE T2,$DHSTS ;LOOKING AT A STATUS MESSAGE?
JRST IRBR77 ;NO
PUSHJ P,RDSTS1## ;READ AND TRANSLATE THE DAP STATUS
POPJ P, ;ERROR READING A STATUS MESSAGE?
CAIE M0,$EGOIP ;"OPERATION IN PROGRESS"
CAIN M0,$EGAOK ;"A-OK"
JRST IRBR01 ;YES, IGNORE IT
POPJ P, ;RETURN ERROR
IRBR77: MOVE M0,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNN M0,IO.NEP ;ACTIVE OR PASSIVE LINK?
STOPCD <Received DAP message neither DATA nor STATUS in IRBR>
PUSHJ P,RDMSR1## ;PASSIVE, RE-EAT THE MESSAGE
POPJ P, ;DUH?
MOVEI M0,$EINMP ;TELL FAL THAT AN INPUT MESSAGE IS PENDING
POPJ P, ;TAKE EXCEPTION RETURN
SUBTTL OUTPUT SERVICE ROUTINES
;All Output Service Routines are called with the I/O CDB address in
;register T1 and the output data in T2 (and if needed T3, T4).
;
;On the error/exception return M0 has the error/exception code.
;
;On normal return the data is in the output buffer.
;
;In all cases, the T registers are preserved!
ENTRY .IOOIN
.IOOIN: PUSHJ P,IOOIN0 ;DO THE WORK
POPJ P, ;OOPS
PJRST @.IOOSR(T1) ;DISPATCH TO SELECTED OUTPUT SERVICE ROUTINE
IOOIN0: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S TOO
SETZM .IOOSF(IO) ;RESET OUTPUT PROCESSING FLAGS
XMOVEI P1,.POPJ1## ;THE SKIP-RETURNER
MOVEM P1,.IOOSS(IO) ;USUALLY NO SPECIAL CLOSE PROCESSING NEEDED
MOVX P1,IO.IOA ;THE I/O-ACTIVE FLAG
IORB P1,.IOCCF(IO) ;NOTE I/O ACTIVITY
TXNE P1,IO.NET ;LOCAL OR REMOTE (NETWORK) I/O?
JRST ORINI ;REMOTE
;LOCAL, FALL INTO OLINI
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
;OLINI -- OUTPUT, LOCAL, INITIALIZATION
OLINI: TXNE P1,IO.OBA ;OUTPUT BUFFERS ALLOCATED?
JRST OLINI4 ;YES, SELECT OSR AND START I/O
;NO OUTPUT BUFFERS, GENERATE SOME FOR FREE
PUSHJ P,FILBO1## ;SETUP OUTPUT BUFFERS
POPJ P, ;OH WELL
;SEE IF CALLER REALLY WANTS TO APPEND TO THE FILE (I.E., FAL GOT A READ
;FILE REQUEST AND THE POSITION-TO-EOF FLAG WAS LIT, MEANING REMOTE SYSTEM
;REALLY WANTS TO WRITE THE FILE, NOT READ IT...)
TXNN P1,IO.APP ;APPEND MODE?
JRST OLINI4 ;NO -- DON'T SWITCH MODES
MOVEI P2,.FOAPP ;YES -- GET APPEND FUNCTION
HRRM P2,.I1FLP(IO) ;STUFF IN FILOP. BLOCK
MOVEI P2,.I1FLP(IO) ;GET ADDRESS
HRLI P2,.FOMAX ;AND SIZE
FILOP. P2, ;SET UP FOR FILE APPENDING
POPJ P, ;COULDN'T
;SELECT OSR BASED ON FILE MODE AND OPTIONS
OLINI4: MOVE P4,.IOIOC(IO) ;GET I/O CONTROL
LDB P2,[POINTR P4,IC.MOD] ;GET FILE MODE
XMOVEI P3,. ;GET OUR SECTION IN LH
HRR P3,MOOSTB(P2) ;SELECT OSR BASED ON FILE MODE ALONE
TXNE P4,IC.RSI ;USER WANT RECORD-STRUCTURED I/O?
HRRI P3,OLREC ;YES, TOO BAD
TXNE P4,IC.BLK ;USER WANT BLOCK MODE BUFFERS
HRRI P3,OLBLK ;YES, LET HIM DO HIS OWN STUFF THEN
TXNE P4,IC.MCY!IC.MEY;MACY11-FORMATTED OUTPUT?
HRRI P3,OLMCI ;YES, SELECT MACY11 OUTPUT SERVICE THEN
MOVEM P3,.IOOSR(IO) ;SET OSR IN THE CDB
;INITIALIZE COUNTERS
SETOM .IOOUC(IO) ;NO BUFFERS OUTPUT YET
JRST .POPJ1## ;OUTPUT INITIALIZED
;OLASC -- OUTPUT, LOCAL, ASCII CHARACTERS
OLASB: PUSHJ P,OLBUF ;ASK MONITOR FOR ANOTHER BUFFER
POPJ P, ;ERROR
OLASC: SKIPE .IOOS0(T1) ;GOT AN LSN PENDING?
JRST OLASC8 ;YES, GO PROCESS IT FIRST
OLASC2: SOSGE .IOOBC(T1) ;ANY ROOM LEFT?
JRST OLASB ;NO, GET AN EMPTY BUFFER
IDPB T2,.IOOBP(T1) ;YES, STUFF AWAY THIS CHARACTER THEN
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;HERE TO OUTPUT LINE SEQUENCE NUMBER PENDING (SET BY IFLSN)
;
;.IOOS0 CONTAINS THE LSN AS A INTEGER (NOT ASCII CHARACTERS) WHICH
;IF 1B0 THEN OUTPUT A "PAGE-MARK"
OLASC8: PUSHJ P,OLLSN ;ISSUE LSN
POPJ P, ;I/O ERROR
JRST OLASC2 ;GO ISSUE THE CHARACTER
;HERE TO ISSUE LSN FOR LOCAL FILE SERVICE
OLLSN: PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;AND THE T'S
;FIRST, MOVE UP TO A WORD BOUNDRY
OLLSN2: LDB T2,[POINT 6,.IOOBP(T1),5] ;GET OUTPUT POINTER "P" FIELD
CAIE T2,1 ;ON A WORD BOUNDRY?
CAIN T2,44 ;(ALTERNATE FORM)?
JRST OLLSN4 ;YES
JUMPE T2,OLLSN4 ;NULL MEANS UNINITIALIZED, NEED TO CALL OLBUF
OLLSN3: SETZ T2, ;GET A NULL AS A FILLER CHARACTER
PUSHJ P,OLBYT ;PAD THE PARTIAL WORD TO A WORD BOUNDRY
POPJ P, ;BLETCH
JRST OLLSN2 ;CHECK AGAIN
;SECOND, MAKE SURE THE SOS-STYLE <TAB> WILL FIT IMMEDIATELY AFTER THE
;THE LINE-SEQUENCE-NUMBER (THIS IS SO STUPID PROGRAMS CAN SIMPLY LOOK
;AT THE WORD IMMEDIATELY FOLLOWING THE LSN FOR THE SOS-STYLE <TAB>.
OLLSN4: SKIPLE T2,.IOOBC(T1) ;GET OUTPUT COUNT
JRST OLLSN5 ;AND SEE IF ANY ROOM LEFT
PUSHJ P,OLBUF ;CURRENT BUFFER EMPTY, GET A NEW BUFFER
POPJ P, ;I/O ERROR?
JRST OLLSN4 ;TRY AGAIN
OLLSN5: CAIGE T2,6 ;ROOM IN THIS BUFFER FOR LSN AND <TAB>?
JRST OLLSN3 ;NO
;NOW THE TRADITIONAL "DECOUT" ROUTINE, KINDA TURNED SIDEWAYS
MOVE P1,.IOOS0(T1) ;RETRIEVE THE INPUT LSN
IBP .IOOBP(T1) ;POINT BYTE POINTER AT THE RIGHT WORD
JUMPL P1,[DMOVE T2,[EXP <<ASCII/ />!1>,<BYTE (7) 15,14,00,00,00>]
DMOVEM T2,@.IOOBP(T1) ;SET SOS-STYLE "PAGE MARK"
AOS .IOOBP(T1) ;BUMP POINTER PAST FIRST WORD
MOVNI T2,^D10 ;JUST USED UP 10 CHARACTERS
HRRZM P1,.IOOS0(T1) ;SET FUTHER PROCESSING
JRST OLLSN7] ;CAP OFF LSN
SETZ T2, ;INITIALIZE LSN
MOVEI P3,5 ;WILL WANT EXACTLY 5 DIGITS
OLLSN6: IDIVI P1,^D10 ;GET LOWEST DIGIT LEFT
IORI T2,"0"(P2) ;TACK ON THE ASCIIZED DIGIT
ROT T2,-^D7 ;POSITION DIGIT WITHIN WORD
SOJG P3,OLLSN6 ;MAKE FIVE-DIGIT LSN
IORI T2,1 ;TURN ON THE LSN BIT
MOVEM T2,@.IOOBP(T1) ;STASH AWAY LSN WORD
SETZM .IOOS0(T1) ;THE LSN HAS BEEN PROCESSED!
MOVNI T2,5 ;ACCOUNT FOR THE 5 CHARACTERS
OLLSN7: ADDM T2,.IOOBC(T1) ;WHICH WERE JUST USED
MOVSI T2,(POINT 7,,34);ALSO DIDDLE THE BYTE POINTER
HLLM T2,.IOOBP(T1) ;TO LOOK "RIGHT"
SKIPE .IOOS0(T1) ;DID WE FINISH?
JRST OLLSN2 ;NO, STILL HAVE MORE TO DO
MOVEI T2,.CHTAB ;NOW GET A <TAB> CHARACTER
PJRST OLBYT ;AND OUTPUT IT TOO
;OLBYT -- OUTPUT, LOCAL, BYTE STREAM
OLBYB: PUSHJ P,OLBUF ;ASK FOR ANOTHER BUFFER
POPJ P, ;ERROR
OLBYT: SOSGE .IOOBC(T1) ;ANY ROOM LEFT IN CURRENT BUFFER?
JRST OLBYB ;NO, ASK FOR AN EMPTY BUFFER
IDPB T2,.IOOBP(T1) ;STASH AWAY THIS DATA BYTE
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;OLREC -- OUTPUT, LOCAL, RECORD-STRUCTURED I/O
OLREC: STOPCD <Record-structured local I/O illegal>
;OLBLK -- OUTPUT, LOCAL, BLOCK MODE
OLBLK: JRST OLBLK2 ;NEED A BUFFER
MOVEM T3,.IOOBC(T1) ;SET USER'S RETURNED BYTE COUNT
MOVEM T4,.IOOBP(T1) ;AND BYTE POINTER
SOS .IOOSR(T1) ;MARK NEED-A-BUFFER STATE
OLBLK2: PUSHJ P,OLBUF ;ASK FOR A NEW [EMPTY] BUFFER
JRST OLBLK4 ;NO BUFFER AVAILABLE
AOS .IOOSR(T1) ;WE HAVE A NEW [PRESUMABLY EMPTY] BUFFER
MOVE T3,.IOOBC(T1) ;RETURN USER THE NEW BYTE COUNT
MOVE T4,.IOOBP(T1) ;AND BYTE POINTER
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
;HERE WHEN CAN'T GET A BUFFER, RETURN -1 BYTE COUNT TO USER TO FORCE
;HIM TO IMMEDIATELY CALL OLBLK AGAIN SINCE THERE IS NO GUARANTEE THAT
;THERE IS A BUFFER AVAILABLE UNTIL HE FORCES ANOTHER OUTPUT ATTEMPT.
;WE MUST ALSO BE SURE NOT TO TOUCH THE RING HEADER COUNTER/POINTER
;SINCE THE MONITOR USES IT AS A STATE FLAG.
OLBLK4: SETOB T2,T3 ;RETURN NO BYTES
POPJ P, ;PASS ERROR STATUS TO USER
;OLMCY -- OUTPUT, LOCAL, MACY11 PACKED
;MACY11 packing involves writing 8-bit bytes packed four to a 36-bit word,
;but not in an obvious manner. The four bytes are layed out as follows:
;
; 2 9 10 17 20 27 28 35
; +--+--------+--------+--+--------+--------+
; | | two | one | | four | three |
; +--+--------+--------+--+--------+--------+
;
;This format can be thought of as aligning one -11 16-bit word per -10
;halfword (although it should be emphasized that the packing is in
;terms of bytes, so that the "16-bit words" might be (and often are)
;split across "18-bit halfwords"!).
;
;The record structure imposed is:
;
; 000001 ;record header
; length ;count of bytes (includes MACY11 header - 6 bytes)
; address ;for .LDA files, address to load record
; ; ignored for pure data records
; -data- ;length-6 data bytes
; ...cks ;one-byte checksum (not included in count)
;
;The output variables (in the CDB) are used as follows:
;
; .IOOS0 ;not used
; .IOOS1 ;record byte count
; .IOOS2 ;OLMCB (byte-stuffing) state
; .IOOS3 ;OLMCR (record-header) state
; .IOOS4 ;OLMCB 36-bit word address
; .IOOS5 ;MACY11 checksum value
;The ISR call is:
;
; MOVX T2,<ADR>
; MOVX T3,<CNT>
; MOVX T4,<PTR>
; PUSHJ P,@.IOISR
; error return
; normal return
;
;Where <ADR> is the record/.LDA "load" address (if any); <CNT> is
;the count of data bytes; and <PTR> is the byte pointer to the data bytes.
;
;On error return an error code is in M0
;
;On normal return the record as specified has been output suitably
;"encased" in MACY11 format.
;HERE TO INITIALIZE FOR MACY11 DATA PACKING (FROM OLINI)
OLMCI: SETZM .IOOS3(T1) ;CURRENTLY NOT IN A RECORD
MOVEI M0,4 ;WORD-PACKING STATE
MOVEM M0,.IOOS2(T1) ;SET FOUR BYTES LEFT
SETZM .IOOS4(T1) ;INITIALIZE BYTE-PACKING WORD
XMOVEI M0,OLMCC ;SPECIAL CLOSE PROCESSING REQUIRED
MOVEM M0,.IOOSS(T1) ;SET FOR .IOCLO TO FIND
XMOVEI M0,OLMCY ;NORMAL OSR
MOVEM M0,.IOOSR(T1) ;SET FOR SUBSEQUENT CALLS
;AND FALL INTO OLMCY
;HERE TO OUTPUT ONE MACY11 LOGICAL DATA RECORD (CALLED AS AN OSR)
OLMCY: PUSHJ P,.SAVE2## ;NEED A COUPLA EXTRA ACS
PUSHJ P,TSAV14## ;PRESERVE THE T'S
PUSHJ P,OLMCR ;FIRE UP AN OUTPUT RECORD
POPJ P, ;CAN'T
MOVE P2,-T4(P) ;GET OUTPUT RECORD POINTER
SKIPG P1,-T3(P) ;AND OUTPUT BYTE COUNT
JRST OLMCY6 ;NULL RECORD, DONE BEFORE WE START!
;LOOP WRITING THE DATA BYTES
OLMCY3: ILDB T2,P2 ;FETCH ANOTHER DATA BYTE
PUSHJ P,OLMCB ;OUTPUT THIS 8-BIT BYTE
POPJ P, ;DIED
ADDM T2,.IOOS5(T1) ;ACCUMUMLATE MACY11 CHECKSUM
SOJG P1,OLMCY3 ;LOOP FOR REST OF RECORD
OLMCY6: SETZM .IOOS3(T1) ;CLEAR RECORD STATE
MOVX M0,IS.MCF!IS.MCK;FLAG FILLER AND CHECKSUM BYTE NEEDED
IORM M0,.IOOSF(T1) ; BUT NOT YET OUTPUT
SETZ T2, ;*** CALCULATE CHECKSUM
PUSHJ P,OLMCB ;OUTPUT 8-BIT CHECKSUM BYTE
POPJ P, ;DIED
MOVX M0,IS.MCK ;FLAG THE CHECKSUM BYTE
ANDCAM M0,.IOOSF(T1) ; IS NO LONGER NEEDED
JRST .POPJ1## ;SUCCESSFUL RETURN FOR THIS RECORD
;OLMCR - MACY11 RECORD STARTUP
;
;On error return, the record header could not be written completely.
;If error recovery is attempted, the retry call must specify exactly
;the same record information as the original call which failed, as there
;is no way to determine (or unwind) the progress of the original call!
OLMCR: MOVEM T2,.IOOS0(T1) ;SAVE RECORD "ADDRESS"
MOVEM T3,.IOOS1(T1) ;AND RECORD LENGTH
SKIPLE T4,.IOOS3(T1) ;ERROR RECOVERY CALL?
JRST @OLMCTA(T4) ;YES, RESUME FROM WHENCE ABORTED
MOVX T3,IS.MCK ;THE CHECKSUM BYTE NEEDED FLAG
TDNE T3,.IOOSF(T1) ;HAVE A DANGLING CHECKSUM?
JRST [MOVE T2,.IOOS5(T1) ;GET CHECKSUM BYTE
PUSHJ P,OLMCB ;OUTPUT MACY11 BYTE
POPJ P, ;STILL HAVEN'T OUTPUT THE CHECKSUM
ANDCAM T3,.IOOSF(T1) ;THE CHECKSUM IS NOW OUTPUT
JRST .+1] ;BACK TO MAIN-LINE CODE
MOVX T3,IS.MCF ;THE INTER-RECORD FILLER FLAG
TDNN T3,.IOOSF(T1) ;SET IN THE OUTPUT SERVICE FLAGS?
JRST [MOVEI T3,2 ;NO - PROBABLY FIRST RECORD IN FILE
MOVEM T3,.IOOS3(T1) ;SKIP FIRST STAGE
JRST OLMCR2] ;AND START WITH STAGE TWO
ANDCAM T3,.IOOSF(T1) ;YES, CLEAR IT
MOVEI T4,6 ;MACY11 PUTS 6-NULLS 'TWEEN RECORDS
MOVE T3,.IOIOC(T1) ;IO MODE CONTROL
TXNN T3,IC.MEY ;/MECY11 STRUCTURING?
JRST OLMCR0 ;NO
;HERE TO TRY TO KEEP "-11 16-BIT WORDS" ALIGNED IN -10 HALFWORDS, FURTHER
;ENSURING THAT THE RECORD HEADER NEVER SPLITS ACROSS A BLOCK/BUFFER BOUNDRY.
;THE RESULTANT FORMAT YIELDS A ZERO [INTER-RECORD GAP] WORD, THEN
;1,,CNT, THEN ADR,,DATA, FOLLOWED BY (CNT-6-2)/2 MORE DATA HALFWORDS,
;AND FINALLY THE CHECKSUM. THIS MAKES LOOKING AT THE "MACY11" FILE
;MUCH EASIER VIA FILDDT/ET AL.
SKIPGE T3,.IOOBC(T1) ;YES, GET OUTPUT WORD COUNT IN BUFFER
MOVEI T3,1 ;NONE LEFT, FORCE ONE WORD OF ZEROS
LSH T3,2 ;NUMBER OF BYTES LEFT
MOVEI T4,4 ;MINIMUM ONE ZERO WORD 'TWEEN RECORDS
CAIGE T3,^D12 ;ENOUGH ROOM LEFT?
MOVE T4,T3 ;NO, FLUSH OUT THIS BUFFER FIRST
SETZM .IOOS2(T1) ;RESET OLMCB TO START OF NEW WORD
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
OLMCR0: MOVEM T4,.IOOS5(T1) ;COUNT OF NULL BYTES NEEDED
AOS .IOOS3(T1) ;STAGE ONE
OLMCR1: SETZ T2, ;NULL BYTE
PUSHJ P,OLMCB ;WRITE ONE EIGHT-BIT BYTE
POPJ P, ;OUTPUT ERROR
SOSLE .IOOS5(T1) ;COUNT DOWN FILLER
JRST OLMCR1 ;STILL NEED MORE
AOS .IOOS3(T1) ;STAGE TWO
OLMCR2: MOVEI T2,1 ;THE 000001 TO START A NEW RECORD
PUSHJ P,OLMCB ;WRITE LOW-ORDER BYTE
POPJ P, ;OUTPUT ERROR
AOS .IOOS3(T1) ;STAGE THREE
OLMCR3: MOVEI T2,0 ;THE 000001 (HIGH BYTE)
PUSHJ P,OLMCB ;WRITE HIGH-ORDER BYTE
POPJ P, ;OUTPUT ERROR
AOS .IOOS3(T1) ;STAGE FOUR
OLMCR4: MOVE T2,.IOOS1(T1) ;RETRIEVE RECORD LENGTH
ADDI T2,6 ;ALLOW FOR MACY11 HEADER INFO
PUSHJ P,OLMCB ;WRITE LOW-ORDER BYTE
POPJ P, ;OUTPUT ERROR
AOS .IOOS3(T1) ;STAGE FIVE
OLMCR5: MOVE T2,.IOOS1(T1) ;RETRIEVE RECORD LENGTH
ADDI T2,6 ;ALLOW FOR MACY11 HEADER INFO
LSH T2,-^D08 ;POSITION FOR HIGH BYTE
PUSHJ P,OLMCB ;WRITE HIGH-ORDER LENGTH BYTE
POPJ P, ;OUTPUT ERROR
AOS .IOOS3(T1) ;STAGE SIX
OLMCR6: MOVE T2,.IOOS0(T1) ;RETRIEVE RECORD ADDRESS (IF ANY)
PUSHJ P,OLMCB ;WRITE LOW-ORDER BYTE
POPJ P, ;OUTPUT ERROR
AOSA .IOOS3(T1) ;STAGE SEVEN
OLMCR7: MOVE T2,.IOOS0(T1) ;RETRIEVE RECORD ADDRESS (IF ANY)
LSH T2,-^D08 ;POSITION HIGH-ORDER BYTE
PUSHJ P,OLMCB ;WRITE HIGH-ORDER BYTE
POPJ P, ;OUTPUT ERROR
AOS .IOOS3(T1) ;STAGE EIGHT (IN A RECORD)
SETZM .IOOS5(T1) ;INITIALIZE CHECKSUM FOR THIS RECORD
JRST .POPJ1## ;SUCCESSFUL RETURN, READY TO WRITE DATA
;HERE TO OUTPUT ONE PHYSICAL 8-BIT MACY11-PACKED BYTE
;
;THIS IS NOT CALLED AS AN OSR!
OLMCB: EXCH M0,T4 ;NEED A SCRATCH USEABLE AS AN INDEX
SOSGE T4,.IOOS2(T1) ;ADVANCE PACKING STATE
JRST OLMCB2 ;NEED A NEW WORD
DPB T2,OLMCTB(T4) ;STASH AWAY THIS DATA BYTE
EXCH T4,M0 ;RESTORE T4
AOS (P) ;SUCCESSFUL
POPJ P, ; RETURN
OLMCB2: EXCH T4,M0 ;RESTORE T4
EXCH T2,.IOOS4(T1) ;SAVE CURRENT BYTE, GET FULLY-PACKED WORD
PUSHJ P,OLBYT ;ADVANCE TO ANOTHER -10 WORD
POPJ P, ;ERROR
MOVEI T2,4 ;"VIRGIN" PACKING SO FAR THIS WORD
MOVEM T2,.IOOS2(T1) ;SET NEW PACKING STATE
SETZ T2, ;CLEAR NEW WORD TO BE PACKED
EXCH T2,.IOOS4(T1) ;RETRIEVE NEXT BYTE TO BE OUTPUT
JRST OLMCB ;GO OUTPUT THIS BYTE
;SPECIAL CLOSE PROCESSOR (CALLED AT SACIO LEVEL!)
OLMCC: SKIPE .IOOS3(IO) ;THE FINAL RECORD MUST HAVE BEEN FINISHED
JRST [MOVEI M0,$EIRSO ;ERROR - RECORD STILL OUTSTANDING
POPJ P,] ;PROPAGATE ERROR
MOVE T2,.IOOSF(IO) ;GET PROCESSING FLAGS
TXNN T2,IS.MCF ;WANT A FILLER?
JRST .POPJ1## ;NO (THEN NO DATA WAS EVER WRITTEN)
TXNN T2,IS.MCK ;HAVE A DANGLING CHECKSUM BYTE TO OUTPUT?
JRST OLMCC2 ;NO
MOVE T2,.IOOS5(IO) ;YES, GET CHECKSUM BYTE
MOVE T1,IO ;POSITION ISR-LEVEL CDB ADDRESS
PUSHJ P,OLMCB ;STASH FINAL CHECKSUM BYTE
POPJ P, ;POOR FORM!
;FLUSH FINAL WORD BEING ASSEMBLED
OLMCC2: MOVE T2,.IOOS4(IO) ;GET WORD AS PARTIALLY BUILT
MOVE T1,IO ;POSITION ISR-LEVEL CDB ADDRESS
PUSHJ P,OLBYT ;OUTPUT FINAL 36-BIT WORD
POPJ P, ;SIGH
JRST .POPJ1## ;NOW CAN CLOSE THE FILE
;MACY11 TABLES
;RECORD STARTUP STATE DISPATCH TABLE (USED IN ERROR RETRY)
OLMCTA: IFIW [STOPCD] ;STAGE 0 - CAN'T HAPPEN
IFIW OLMCR1 ;STAGE 1
IFIW OLMCR2 ;STAGE 2
IFIW OLMCR3 ;STAGE 3
IFIW OLMCR4 ;STAGE 4
IFIW OLMCR5 ;STAGE 5
IFIW OLMCR6 ;STAGE 6
IFIW OLMCR7 ;STAGE 7
;BYTE-PACKING
OLMCTB: POINT 8,.IOOS4(T1),27 ;BYTE 4
POINT 8,.IOOS4(T1),35 ;BYTE 3
POINT 8,.IOOS4(T1),9 ;BYTE 2
POINT 8,.IOOS4(T1),17 ;BYTE 1
;OLBUF -- OUTPUT, LOCAL, GET EMPTY BUFFER FROM MONITOR
OLBUF: PUSHJ P,.SACIO## ;SET IO
OLBUF0: PUSHJ P,TSAV14## ;PRESERVE THE USER'S T'S
;ASK FOR A NEW BUFFER
OLBUF1: HRLZ T2,.IOCHN(IO) ;I/O CHANNEL NUMBER
HRRI T2,.FOOUT ;"OUTPUT" FUNCTION
MOVE T1,[1,,T2] ;FILOP. ARG POINTER TO
FILOP. T1, ;READ NEW BUFFER
JRST OLBUF4 ;HMMM, CHECK OUT POSSIBLE ERROR
SKIPG .IOOBC(IO) ;ENSURE THAT THE MONITOR GAVE US SOMETHING
STOPCD <FILOP OUT returned successfully with 0-length buffer in OLBUF>
AOS .IOOUC(IO) ;INCREMENT OUT UUO COUNT
JRST .POPJ1## ;SUCCESSFUL RETURN
;CHECK OUT OUTPUT EXCEPTION CONDITION
OLBUF4: TXNE T1,IO.EOF!IO.ERR;ERROR AND/OR END OF FILE?
JRST OLBUF6 ;YES, GO HANDLE
MOVE T3,.IOIOM(IO) ;GET I/O MODE
TXNN T3,IM.AIO ;FILE OPEN FOR NON-BLOCKING I/O?
STOPCD <FILOP OUT failed with no error/EOF bits in OLBUF>
MOVX T1,$SCNBO ;SCHEDULER - NON-BLOCKING OUTPUT
PUSHJ P,@.IOSCH(IO) ;CALL THE SCHEDULER
POPJ P, ;DUH?
JRST OLBUF1 ;TRY OUTPUTTING AGAIN
;ERROR OR END OF FILE
OLBUF6: MOVEM T1,.I1IOS(IO) ;SAVE TOPS-10 I/O STATUS WORD
TXC T1,IO.ERR ;FLIP ALL THE BITS
TXCN T1,IO.ERR ;WERE ALL BITS SET?
JRST OLBUE3 ;YES, EXTENDED I/O ERROR STATUS
LDB T2,[POINTR TY.DEV,.I1DTY(IO)] ;GET DEVICE TYPE
CAIN T2,.TYDSK ;IS IT A DISK?
JRST OLBUD1 ;YES, MORE GUESSWORK INVOLVED
;RANDOM I/O ERROR ENCODED INTO IO.ERR, TRANSLATE DIRECTLY AND RETURN
OLBUE1: TXNE T1,IO.BKT ;"BLOCK TOO LARGE" ?
MOVEI M0,$EIBKT ;YES
TXNE T1,IO.DTE ;"DATA CHECKSUM/PARITY ERROR" ?
MOVEI M0,$EIDAT ;YES
TXNE T1,IO.DER ;"DEVICE ERROR"
MOVEI M0,$EIDEV ;YES
TXNE T1,IO.IMP ;"IMPROPER MODE"
MOVEI M0,$EIIMP ;YES
POPJ P, ;RETURN I/O ERROR
;EXTENDED I/O ERROR, NEED TO RETRIEVE EXTENDED ERROR CODE
OLBUE3: PUSHJ P,IOERX1 ;RETRIEVE AND TRANSLATE EXTENDED I/O ERROR CODE
MOVEI M0,$EIXXX ;UNKNOWN ERROR
HRRZ M0,M0 ;POSITION OUTPUT TRANSLATION
POPJ P, ;RETURN I/O ERROR
;DISK ERROR, SNIFF AROUND A BIT
OLBUD1: MOVE T2,.IOCHN(IO) ;I/O CHANNEL
MOVEM T2,.I1NSP+.DCNAM(IO) ;SET IN DSKCHR BLOCK
MOVSI T2,.I1NSL ;LENGTH AND
HRRI T2,.I1NSP(IO) ;ADDRESS OF DSKCHR BLOCK
DSKCHR T2, ;READ ALL ABOUT THAT UNIT/STRUCTURE
JRST ILBUE1 ;FORGET IT
MOVEI M0,$EIQTA ;USER QUOTA EXHAUSTED
SKIPG .I1NSP+.DCUFT(IO) ;ANY USER QUOTA LEFT?
POPJ P, ;NO, ERROR
MOVEI M0,$EIFUL ;FILE STRUCTURE STORAGE EXHAUSTED
SKIPG .I1NSP+.DCUNT(IO) ;ANY ROOM LEFT ON DISK?
POPJ P, ;NO, ERROR
MOVEI M0,$EIHWL ;WRITE-LOCKED
TXNE T2,DC.HWP ;HARDWARE WRITE-LOCKED?
POPJ P, ;YES, ERROR
MOVEI M0,$EISWL ;WRITE-LOCKED BY SOFTWARE
TXNE T2,DC.SWP ;SOFTWARE WRITE-LOCKED?
POPJ P, ;YES, ERROR
MOVEI M0,$EIOFL ;DEVICE OFFLINE
TXNE T2,DC.OFL ;IS DISK UNIT OFFLINE?
POPJ P, ;YES, ERROR
JRST OLBUE1 ;OH WELL, JUST CATCH-ALL THE ERROR
;IOOIE -- OUTPUT, ERROR, OUTPUT-NOT-OPEN
ENTRY .IOOIE
.IOOIE: MOVX M0,$EIONO ;OUTPUT-NOT-OPEN STATUS
POPJ P, ;ERROR RETURN
;OENIR -- OUTPUT ERROR, NOT IN A RECORD
OENIR: MOVEI M0,$EINIR ;NOT-IN-A-RECORD ERROR
POPJ P, ;EXCEPTION RETURN
;ORINI -- OUTPUT, REMOTE, INITIALIZATION
ORINI: MOVD1 T1,ORG ;GET FILE ORGANIZATION
CAIE T1,$DVOSQ ;IS IT SEQUENTIAL?
STOPCD <DAP file organization not "sequential" in ORINI>
MOVE T1,.IOIOC(IO) ;GET I/O CONTROL
TXNE T1,IC.BLK!IC.DMP;FUNNY MODE SET?
STOPCD <Block/Dump mode selected in ORINI>
;ENSURE FRESH START, NETWORK BUFFER-WISE
PUSHJ P,XDFLS0## ;FLUSH OUT ANYTHING ACCUMULATED
POPJ P, ;NETWORK DIED
;INITIALIZE BASIC VARIABLES
MOVEI T1,177777 ;CRC POLYNOMIAL SEED
MOVEM T1,.IODOK(IO) ;SET FOR FILE DATA CRC COMPUTATION
; INITIALIZATION DISPATCH BASED ON DATA TYPE
MOVD T1,DTY ;DATA TYPE ATTRIBUTE FIELD
TFNE T1,ASC ;ASCII CHARACTER DATA?
JRST ORIA ;YES, INIT FOR ASCII
TFNE T1,IMG ;IMAGE (BINARY) DATA?
JRST ORIB ;YES, INIT FOR BINARY
STOPCD <DAP data type neither ASCII nor binary in ORINI>
;REMOTE ASCII OUTPUT INITIALIZATION
ORIA: SETZ P1, ;INITIAL OSR SELECTION
MOVE P2,.IOIOC(IO) ;GET I/O CONTROL FLAGS
TXNE P2,IC.RSI ;WANTING BYTE MODE I PRESUME
STOPCD <Record-structured I/O selected in ORIA>
MOVD1 T2,RFM ;GET RECORD FORMAT CONTROL
MOVD T3,RAT ;GET RECORD ATTRIBUTES
TFZ T3,MCY ;MACY11-PACKING DOESN'T AFFECT US
JSP T4,.CDISP## ;DISPATCH ON RECORD FORMAT REQUIRED
ORIA20,,$DVFNR ;NO FORMAT
ORIA30,,$DVFST ;STREAM FORMAT RECORDS
ORIA40,,$DVFSL ;STREAM-LF FORMAT RECORDS
ORIA40,,$DVFSC ;STREAM-CR FORMAT RECORDS
ORIA50,,$DVFFX ;FIXED-LENGTH RECORDS
ORIA50,,$DVFVR ;VARIABLE-LENGTH RECORDS
ORIA50,,$DVFVF ;VARIABLE WITH FIXED-LENGTH HEADER
0 ;NONE OTHERS KNOWN
STOPCD <Unknown record format in ORIA>
;"NO FORMAT" ASCII
ORIA20: XMOVEI P1,ORAU ;UNFORMATTED ASCII OSR
TFZN T3,LSA ;WANT LINE SEQUENCE NUMBERS
JRST ORIA80 ;NO, STARTUP DATA STREAM
;YES, TREAT AS STREAM ASCII THEN
;"STREAM" ASCII
ORIA30: XMOVEI P1,ORAS ;STREAM ASCII OSR
TFZ T3,<EFC,LSA> ;CAN HANDLE LSN'S
JRST ORIA80 ;STARTUP DATA STREAM
;"STREAM-LF" AND "STREAM-CR" ASCII
ORIA40: XMOVEI P1,ORAS ;STREAM ASCII OSR
TFZ T3,<ILC,LSA> ;CAN HANDLE LSN'S
JRST ORIA80 ;STARTUP DATA STREAM
;"VARIABLE", ET AL, AS NEEDED FOR RSX, VAX, AND SO FORTH
ORIA50: XMOVEI P1,ORAV ;VAX (ET AL) ASCII OSR
TFZ T3,<ILC,LSA> ;CAN HANDLE LSN'S
JRST ORIA80 ;STARTUP DATA STREAM
;STARTUP A DATA STREAM
ORIA80: JUMPN P1,ORIA82 ;MAKE SURE AN OSR WAS SELECTED
STOPCD <No OSR selected in ORIA>
ORIA82: FJUMPE T3,RAT,ORIA84 ;ANY RECORD ATTRIBUTES LEFT OVER?
STOPCD <Unknown or illegal record format/attributes in ORIA>
ORIA84: MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNE T1,IO.NEP ;ACTIVE OR PASSIVE LINK?
JRST ORIA86 ;PASSIVE, NO STARTUP NEEDED
PUSHJ P,DPSOI0## ;ACTIVE, NEED CONTROL(CONNECT), CONTROL(PUT)
POPJ P, ;DIED
ORIA86: MOVEM P1,.IOOSR(IO) ;SET NEW STATE DISPATCH
XMOVEI T1,ORACL ;ASCII OUTPUT SHUTDOWN
MOVEM T1,.IOOSS(IO) ;SET FINAL STATE DISPATCH
JRST .POPJ1## ;OUTPUT INITIALIZED
;HERE TO CLOSE DOWN THE OUTPUT ASCII STREAM
;
; *** NOTE ***
;
; ENTERED FROM CLOSE AT SACIO LEVEL
ORACL: SKIPG T1,.IODOM(IO) ;IN A MESSAGE?
JRST .POPJ1## ;NO, ALL DONE
CAIE T1,$DHDAT ;DATA MESSAGE?
STOPCD <Non-data DAP message outstanding in ORACL>
MOVE T1,.IOOSF(IO) ;GET OUTPUT PROCESSING FLAGS
TXZN T1,IS.ICR ;GOT AN IMPLICIT <CR> HIDING IN THE BUSHES?
JRST ORACL3 ;NO
MOVEI T2,.CHCRT ;YES, A <CR> CHARACTER
PUSHJ P,XDBYC0## ;SEND LONELY <CR> AS EMBEDDED CARRIAGE CONTROL
POPJ P, ;BUTTS
ORACL3: PUSHJ P,XDEOM0## ;CLOSE OFF THIS MESSAGE
POPJ P, ;OOPS
JRST .POPJ1## ;SUCCESSFUL
;REMOTE ASCII STREAM OUTPUT SERVICE ROUTINE
ORAS: PUSHJ P,TSAV14## ;NEED SOME ACS HERE!
SKIPE .IONIA(T1) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,.ORNIA ;YES, GO CHECK IT OUT
ORAS02: SETZB T2,T3 ;JUNK RECORD NUMBER
PUSHJ P,.XDDAT## ;STARTUP A DATA MESSAGE
POPJ P, ;BUMMER
XMOVEI T2,ORAS20 ;NOW-WITHIN-A-RECORD STATE SERVICE
MOVEM T2,.IOOSR(T1) ;SET NEW STATE SERVICE DISPATCH
MOVD T2,RAT,.IDRAT(T1) ;GET RECORD ATTRIBUTES OF OUTPUT STREAM
TFNE T2,LSA ;WAS FILE OPENED FOR LSN'S?
JRST ORAS10 ;NO, JUST OUTPUT ASCII DATA BYTES
ORAS09: MOVE T2,-T2(P) ;RESTORE ASCII CHARACTER
JRST ORAS20 ;AND OUTPUT ASCII DATA
;HERE TO SHIP A NETWORK LSN
ORAS10: MOVEI T2," " ;ASSUME NOT A PAGE MARK
SKIPGE T3,.IOOS0(T1) ;1B0 SET? (SOS PAGE MARK)
MOVEI T2,.CHFFD ;YES, SWITCH TO PAGE MARK
PUSHJ P,.XDBYC## ;OUTPUT PAGE MARK FLAG
POPJ P, ;HO HUM
MOVEI T2,5 ;NOW WANT 5 DIGITS
HRRZ T3,.IOOS0(T1) ;GET THE ACTUAL LSN
SETZM .IOOS0(T1) ;WHATEVER HAPPENS, NO MORE LSN
ORAS12: IDIVI T3,^D10 ;EXTRACT NEXT DIGIT
PUSH P,T4 ;SAVE IT MOMENTARILY
SOJG T2,ORAS12 ;LOOP FOR ALL FIVE DIGITS
SETZ T3, ;CLEAR ACCUMULATOR
MOVEI T2,5 ;MUST NOW RETRIEVE 5 DIGITS
ORAS14: POP P,T4 ;RETRIEVE AN ASCIIZABLE DIGIT
LSH T3,^D07 ;MAKE ROOM AND
IORI T3,"0"(T4) ;BLEND IT IN
SOJG T2,ORAS14 ;LOOP FOR ALL FIVE DIGITS
LSH T3,1 ;LEFT-JUSTIFY THE FIVE ASCII DIGITS
MOVEI T4,5 ;NOW WE CAN OUTPUT THE 5 DIGITS
ORAS16: LSHC T2,7 ;NEXT DIGIT
ANDI T2,177 ;AND ONLY THE NEXT DIGIT
PUSHJ P,.XDBYC## ;OUTPUT ONE CHECKSUMMED DATA CHARACTER
POPJ P, ;BUMMER, SO MUCH FOR THAT LSN
SOJG T4,ORAS16 ;LOOP FOR ALL FIVE DIGITS
JRST ORAS09 ;NOW CAN START UP USER DATA
;HERE TO OUTPUT ONE ASCII CHARACTER (CDB ADDRESS IN T1, CHAR IN T2)
ORAS20: EXCH T1,IO ;SET I/O CDB INDEX
PUSHJ P,XDBYC0## ;SHIP ONE DAP DATA MESSAGE BYTE
JRST ORAS24 ;ERROR
CAIGE T2," " ;PRINTING ASCII GRAPHIC?
JRST ORAS60 ;NO, CONTROL, MAYBE EOR
ORAS23: AOS (P) ;YES, TAKE SUCCESSFUL RETURN
ORAS24: EXCH IO,T1 ;RESTORE T1 AND IO
POPJ P, ;RETURN AS APPROPRIATE
;CHECK FOR END OF RECORD CHARACTER
ORAS60: CAIN T2,.CHTAB ;IF A TAB
JRST ORAS23 ;THEN NOT EOR
CAIL T2,.CHLFD ;IF <LF>, <VT>, OR <FF>
CAILE T2,.CHFFD ; . . .
CAIL T2,.CHDLE ;IF <DLE>, <DC1>, <DC2>, <DC3>, OR <DC4>
CAILE T2,.CHDC4 ; . . .
CAIL T2,.CHCNZ ;OR A <SUB>, OR <ESC>
CAILE T2,.CHESC ; . . .
JRST ORAS23 ;RANDOM CONTROL, NOT EOR
; JRST ORAS70 ;DAP ASCII EOR CHARACTER
;END OF RECORD CHARACTER (BUT BYTE *ALREADY* OUTPUT)
ORAS70: EXCH IO,T1 ;PUT THE ACS BACK
PUSHJ P,TSAV14## ;PROTECT THE T'S
XMOVEI T2,ORAS77 ;BYTE-ALREADY-OUTPUT STATE
MOVEM T2,.IOOSR(T1) ;SET IN CASE XDEOM FAILS
PUSHJ P,.XDEOM## ;CAP OFF THIS DATA MESSAGE
POPJ P, ;ERROR (BUT BYTE ALREADY "OUTPUT")
ORAS77: XMOVEI T2,ORAS ;NOT-IN-A-RECORD STATE
MOVEM T2,.IOOSR(T1) ;SET FOR NEXT DATA BYTE
JRST .POPJ1## ;THIS BYTE OUTPUT SUCCESSFULLY
;REMOTE ASCII UNFORMATTED OUTPUT SERVICE ROUTINE
ORAU: PUSHJ P,TSAV14## ;SAVE THE T'S
ORAU02: SKIPE .IONIA(T1) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,.ORNIA ;YES, GO CHECK IT OUT
SETZB T2,T3 ;SELECT RECORD NUMBER
PUSHJ P,.XDDAT## ;STARTUP A NEW DATA MESSAGE
POPJ P, ;BUMMER
XMOVEI T2,ORAU20 ;MESSAGE-IN-PROGRESS STATE
MOVEM T2,.IOOSR(T1) ;SET NEW STATE DISPATCH
MOVE T2,-T2(P) ;RESTORE ASCII CHARACTER
;HERE TO OUTPUT ONE ASCII CHARACTER (CDB IN T1, CHAR IN T2)
ORAU20: SKIPG .IODOC(T1) ;ANY ROOM LEFT IN CURRENT DATA MESSAGE?
JRST ORAU60 ;NO, STARTUP A NEW RECORD
EXCH T1,IO ;SETUP I/O CDB INDEX
PUSHJ P,XDBYC0## ;STASH THIS BYTE
CAIA ;FAILED (CAN'T HAPPEN)
AOS (P) ;INDICATE SUCCESS
EXCH IO,T1 ;RESTORE T1 AND IO
POPJ P, ;RETURN AS INDICATED
;CLOSE CURRENT RECORD, START A NEW ONE (BYTE NOT YET OUTPUT)
ORAU60: PUSHJ P,TSAV14## ;SAVE THE T'S
PUSHJ P,.XDEOM## ;CAP OFF THIS MESSAGE
POPJ P, ;ERROR (BYTE NOT YET OUTPUT)
XMOVEI T2,ORAU ;NEED-A-NEW-MESSAGE STATE
MOVEM T2,.IOOSR(T1) ;SET NEW STATE DISPATCHER
JRST ORAU02 ;AND START UP A NEW DATA MESSAGE
;REMOTE ASCII VAX ET AL OUTPUT SERVICE ROUTINE
ORAV: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S
ORAV02: SKIPE .IONIA(IO) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,ORNIA0 ;YES, GO CHECK IT OUT
SETZB T2,T3 ;ZERO RECORD NUMBER
PUSHJ P,XDDAT0## ;START UP A FRESH DATA RECORD
POPJ P, ;CAN'T
XMOVEI T3,ORAV20 ;THE IN-A-RECORD OSR
MOVEM T3,.IOOSR(IO) ;SET NEW OSR
MOVX T3,IS.ICR ;THE <CR> SEEN FLAG
ANDCAM T3,.IOOSF(IO) ;RESET IT SINCE NEW RECORD
MOVE T2,-T2(P) ;RESTORE OUTPUT DATA BYTE
JRST ORAV22 ;GO OUTPUT DATA BYTE
;HERE TO OUTPUT ONE ASCII CHARACTER (ENTERED AS OSR)
ORAV20: PUSHJ P,.SACIO ;SWITCH TO I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S
ORAV22: CAIGE T2," " ;CONTROL OR PRINTING GRAPHIC?
JRST ORAV40 ;CONTROL, CHECK FOR EOR CONDITION
ORAV23: PUSHJ P,XDBYC0## ;OUTPUT DATA BYTE
POPJ P, ;ERROR
JRST .POPJ1## ;SUCCESSFUL
;HERE ON CONTROL, END OF RECORD IF A BREAK CHARACTER
ORAV40: CAIN T2,.CHTAB ;IF A <TAB>
JRST ORAV23 ;THEN TREAT AS NORMAL ASCII GRAPHIC
CAIN T2,.CHCRT ;IF A <CR>
JRST ORAV50 ;TREAT SPECIAL (FOR <CR><LF> CONVERSION)
CAIL T2,.CHLFD ;IF A <LF>, <VT>, OR <FF>
CAILE T2,.CHFFD ; . . .
CAIL T2,.CHDLE ;OR A <DLE>, <DC1>, <DC2>, <DC3>, OR <DC4>
CAILE T2,.CHDC4 ; . . .
CAIL T2,.CHCNZ ;OR A <SUB>, OR <ESC>
CAILE T2,.CHESC ; . . .
JRST ORAV23 ;NO, RANDOM DATA CHARACTER
ORAV43: PUSHJ P,XDBYC0## ;OUTPUT EMBEDDED CARRIAGE-CONTROL CHARACTER
POPJ P, ;NET DIED?
ORAV45: XMOVEI T3,ORAV47 ;THE BYTE-ALREADY-OUTPUT STATE
MOVEM T3,.IOOSR(IO) ;SET NEW STATE DISPATCH
MOVX T3,IS.ICR ;THE <CR> FLAG
ANDCAM T3,.IOOSF(IO) ;RESET THAT TOO
PUSHJ P,XDEOM0## ;END OF RECORD
POPJ P, ;ERROR
ORAV47: XMOVEI T3,ORAV ;NOT-IN-A-RECORD STATE
MOVEM T3,.IOOSR(IO) ;SET FOR NEXT OUTPUT DATA BYTE
JRST .POPJ1## ;SUCCESSFUL
;HERE ON <CR>, CHECK FOR <CR><LF> AND TREAT IT SPECIAL
ORAV50: MOVX T3,IS.ICR ;A <CR>, GET THE <CR> FLAG
IORM T3,.IOOSF(IO) ;AND NOTE ONE PENDING IN CASE OF CLOSE
XMOVEI T3,ORAV54 ;SPECIAL CHECK OSR
MOVEM T3,.IOOSR(IO) ;FOR <CR><LF> FOR IMPLIED <LF><CR> SERVICE
JRST .POPJ1## ;SUCCESFUL RETURN
;HERE ON CHARACTER AFTER <CR> - ENTERED AS AN OSR
ORAV54: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S
MOVD T3,RAT ;GET RECORD ATTRIBUTES
TFNE T3,ILC ;DOING IMPLIED <LF><CR> ENVELOPE?
CAIE T2,.CHLFD ;YES, IS THIS A <CR><LF>?
CAIA ;OUTPUT CHARACTERS AS EMBEDDED CARRIAGE CONTROL
JRST ORAV45 ;A <CR><LF> TO IMPLIED <LF><CR> ENVELOPE
;HERE WHEN MUST OUTPUT THE <CR> AS EMBEDDED CARRIAGE CONTROL
MOVEI T2,.CHCRT ;THE <CR> CHARACTER
PUSHJ P,XDBYC0## ;OUTPUT IT
POPJ P, ;BUMMER
MOVX T2,IS.ICR ;THE <CR>-PENDING FLAG
ANDCAM T2,.IOOSF(IO) ;CLEAR THAT OUT SINCE <CR> IS NOW PROCESSED
XMOVEI T2,ORAV20 ;OTHERWISE EMBEDDED <CR>, NOTHING FANCY,
MOVEM T2,.IOOSR(IO) ;SO BACK TO NORMAL ASCII OSR
MOVE T2,-T2(P) ;RETRIEVE CHARACTER AFTER THE <CR>
JRST ORAV22 ;OUTPUT FIRST OVERPRINT CHARACTER
;REMOTE BINARY OUTPUT INITIALIZATION
ORIB: SETZ P1, ;NO OSR YET
MOVE P2,.IOIOC(IO) ;I/O CONTROL FLAGS
MOVD1 T2,RFM ;RECORD FORMAT
MOVD T3,RAT ;AND RECORD ATTRIBUTES
TFZ T3,MCY ;MACY11 DOESN'T AFFECT US HERE
JSP T4,.CDISP## ;DISPATCH ON RECORD FORMAT
ORIB10,,$DVFNR ;"NO FORMAT"
ORIB20,,$DVFFX ;FIXED LENGTH
ORIB20,,$DVFVR ;VARIABLE LENGTH
ORIB20,,$DVFVF ;VARIABLE WITH FIXED HEADER
0 ;THAT'S IT
STOPCD <Unknown/Illegal record format in ORIB>
;HERE FOR "NO FORMAT" RECORDS (I.E., NO "RECORDS" AT ALL)
ORIB10: MOVD1 T2,BSZ ;GET DATA BYTE SIZE
CAIN T2,^D08 ;8-BIT BYTES?
XMOVEI P1,ORBB ;YES, EASY BYTE BINARY ROUTINE
CAIN T2,^D36 ;NO, 36-BIT BYTES?
ORIB12: XMOVEI P1,ORBW ;YES, BINARY WORD, SPECIAL-CASE IT
TXNE P2,IC.RSI ;TRYING FOR RECORDS?
STOPCD <Record-structured I/O selected in ORIB10>
JUMPN P1,ORIB80 ;GO IF OSR SELECTED
STOPCD <DAP data byte size neither 8 nor 36 in ORIB10>
;HERE FOR BINARY RECORD FORMATTING
ORIB20: LDB T1,[POINTR P2,IC.RFM] ;GET I/O CONTROL RECORD FORMAT
CAIN T1,.ICRF3 ;36PACK'ED PDP-10 WORDS?
JRST ORIB12 ;YES, SPECIAL SERVICE
XMOVEI P1,ORBR ;BINARY RECORD OSR
TXNN P2,IC.RSI ;USER EXPECTING RECORDS?
STOPCD <Record-structured I/O not selected in ORIB20>
MOVD1 T2,BSZ ;GET DAP DATA BYTESIZE
CAIE T2,0 ;IGNORE IF NULL
CAIN T2,^D08 ;MUST BE 8
JRST ORIB80 ;GO TO IT
STOPCD <DAP data byte size not 8 in ORIB20>
;HERE WITH OSR SELECTED, SETUP AND START I/O
ORIB80: JUMPN P1,ORIB82 ;OK IF WE HAVE AN OSR
STOPCD <No OSR selected in ORIB80>
ORIB82: MOVE T1,.IOCCF(IO) ;CHANNEL CONTROL FLAGS
TXNE T1,IO.NEP ;ACTIVE OR PASSIVE LINK?
JRST ORIB86 ;PASSIVE, NO STARTUP NEEDED
PUSHJ P,DPSOI0## ;ACTIVE, NEED CONTROL(CONNECT), CONTROL(PUT)
POPJ P, ;DIED
ORIB86: MOVEM P1,.IOOSR(IO) ;SET NEW STATE DISPATCH
XMOVEI P1,ORBCL ;BINARY OUTPUT SHUTDOWN
MOVEM P1,.IOOSS(IO) ;SET FINAL STATE DISPATCH
JRST .POPJ1## ;OUTPUT INITIALIZED
;HERE TO CLOSE DOWN THE OUTPUT BINARY STREAM
;
; *** NOTE ***
;
; ENTERED FROM CLOSE AT SACIO LEVEL
ORBCL: SKIPG T1,.IODOM(IO) ;IN A MESSAGE?
JRST .POPJ1## ;NO, ALL DONE
CAIE T1,$DHDAT ;DATA MESSAGE?
STOPCD <Non-data DAP message outstanding in ORBCL>
PUSHJ P,XDEOM0## ;CLOSE OFF THIS MESSAGE
POPJ P, ;OOPS
JRST .POPJ1## ;SUCCESSFUL
;REMOTE 8-BIT BYTE BINARY OUTPUT SERVICE ROUTINE
ORBB: PUSHJ P,TSAV14## ;SAVE THE T'S
ORBB02: SKIPE .IONIA(T1) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,.ORNIA ;YES, CHECK IT OUT
SETZB T2,T3 ;CLEAR DATA RECORD NUMBER
PUSHJ P,.XDDAT## ;START UP A NEW DATA MESSAGE
POPJ P, ;BUTTS
XMOVEI T2,ORBB20 ;NOW-WITHIN-A-RECORD STATE
MOVEM T2,.IOOSR(T1) ;SET NEW STATE DISPATCH
MOVE T2,-T2(P) ;RESTORE ACTUAL DATA BYTE
;AND FALL INTO BYTE OUTPUTTER
;HERE TO OUTPUT ONE 8-BIT BINARY DATA BYTE (CDB IN T1, BYTE IN T2)
ORBB20: SKIPG .IODOC(T1) ;ANY ROOM LEFT IN CURRENT MESSAGE?
JRST ORBB60 ;NO, ALLOCATE A NEW MESSAGE
EXCH T1,IO ;YES, SET UP I/O CDB INDEX
PUSHJ P,XDBYC0## ;STASH THIS 8-BIT CHARACTER
CAIA ;FAILED???
AOS (P) ;SKIP RETURN
EXCH IO,T1 ;RESTORE T1
POPJ P, ;RETURN AS APPROPRIATE
;END OF RECORD, CLOSE OFF DAP MESSAGE AND START UP A NEW ONE
ORBB60: PUSHJ P,TSAV14## ;SAVE THE T'S
XMOVEI T2,ORBB ;NEW STATE WILL BE NOT-IN-A-MESSAGE
MOVEM T2,.IOOSR(T1) ;SET WHAT WILL BE NEW STATE
PUSHJ P,.XDEOM## ;CLOSE OFF CURRENT DAP MESSAGE
POPJ P, ;ERROR (DATA BYTE NOT OUTPUT)
JRST ORBB02 ;NOW GO START UP A NEW RECORD
;REMOTE 36-BIT BINARY WORD OUTPUT SERVICE ROUTINE
ORBW: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,TSAV14## ;SAVE THE T'S
ORBW02: SKIPE .IONIA(IO) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,ORNIA0 ;YES, CHECK IT OUT
LDB T2,[POINTR .IOIOC(IO),IC.RFM] ;GET RECORD FORMAT CONTROL
CAIN T2,.ICRF3 ;36PACK'ED PDP-10 WORDS?
SKIPA T2,.IORSZ(IO) ;YES, GET BYTE-COUNTED RECORD SIZE
MOVEI T2,123 ;NO, RANDOM BIT PATTERN
ADDI T2,10 ;ALLOW FOR DAP HEADER
CAMG T2,.IONOC(IO) ;ROOM FOR ANOTHER "RECORD"
JRST ORBW04 ;YES
PUSHJ P,XDFLS0## ;NO, FLUSH OUT DATA RECORDS SO FAR
POPJ P, ;NET DIED?
ORBW04: SETZB T2,T3 ;OUTPUT RECORD NUMBER
PUSHJ P,XDDAT0## ;STARTUP A NEW OUTPUT DATA MESSAGE
POPJ P, ;BUTTS
LDB T2,[POINTR .IOIOC(IO),IC.RFM] ;GET RECORD FORMAT CONTROL
CAIN T2,.ICRF3 ;36PACK'ED PDP-10 WORDS?
SKIPA T2,.IORSZ(IO) ;YES, GET RECORD-SIZE
MOVE T2,.IODOC(IO) ;NO, LIMIT BASED ON DAP MESSAGE SIZE THEN
MOVEM T2,.IOOS0(IO) ;SET BYTE COUNTER FOR THIS "RECORD"
XMOVEI T2,ORBW20 ;NOW-IN-A-MESSAGE STATE
MOVEM T2,.IOOSR(IO) ;SET NEW DISPATCH
MOVE T2,-T2(P) ;RESTORE OUTPUT WORD (36-BITS)
JRST ORBW22 ;FALL INTO OUTPUT SERVICE
;HERE FOR ONE 36-BIT BINARY BYTE - DAP DATA BYTES 1 - 4.5
;
;ENTERED AS AN OSR
ORBW20: PUSHJ P,.SACIO## ;RUN IN I/O CONTEXT HERE
ORBW22: SKIPE T1,.IODOB(IO) ;ANY UNUSED BITS FROM LAST TIME?
JRST ORBW30 ;YES, THEN "ODD" WORD CALL
MOVNI T1,^D09 ;ACCOUNT FOR A FULL 2*4.5 DAP BYTES
ADDB T1,.IOOS0(IO) ;TO BE USED FOR THE NEXT WORD PAIR
JUMPL T1,ORBW60 ;IF OUT OF ROOM, START A NEW RECORD
PUSHJ P,XDBYC0## ;BYTE 1 = BITS 28 - 35
STOPCD <XDBYC (1) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 2 = BITS 20 - 27
STOPCD <XDBYC (2) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 3 = BITS 12 - 19
STOPCD <XDBYC (3) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 4 = BITS 04 - 11
STOPCD <XDBYC (4) failed in ORBW>
MOVE M0,.IODOK(IO) ;PRE-4.5TH BYTE CRC
MOVEM M0,.IODOK+1(IO) ;SAVE FOR ORBW30 (UGLY!!!)
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 4.5 = BITS 0 - 3
STOPCD <XDBYC (4.5) failed in ORBW>
ROT T2,-^D04 ;RESTORE T2
MOVEI M0,^D04 ;4 BITS UNUSED IN LAST DAP DATA BYTE
MOVEM M0,.IODOB(IO) ;SET BITCNT FIELD
JRST .POPJ1## ;THIS WORD SUCCESSFULLY OUTPUT
;HANDLE THE ODD WORD - DAP DATA BYTES 4.5 - 9
ORBW30: CAIE T1,4 ;HAD BETTER HAVE BEEN 4!
STOPCD <Unused bit count not 4 in ORBW30>
SETZM .IODOB(IO) ;CLEAR UNUSED BIT COUNTER
MOVE T1,T2 ;POSITION "HIGH ORDER" WORD
LDB T2,.IONOP(IO) ;FETCH BACK LAST DAP DATA BYTE
LSH T2,+<4 * ^D08> ;ABUT IT UP TO THE HIGH-ORDER WORD
LSHC T1,-<4 * ^D08> ;POSITION FULL FIFTH BYTE
DPB T2,.IONOP(IO) ;AND RE-WRITE THE FIFTH DATA BYTE
MOVE M0,.IODOK+1(IO) ;NOW FETCH PRE-4.5TH BYTE CRC "SEED"
MOVEM M0,.IODOK(IO) ;AND RESTORE CRC
PUSHJ P,XDCRC1## ;CALCULATE NEW CRC BASED ON FULL 8 BITS
STOPCD ;CAN'T HAPPEN
LSHC T1,-^D04 ;RESTORE T2
ROT T2,-^D04 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 6 = BITS 24 - 31
STOPCD <XDBYC (6) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 7 = BITS 16 - 23
STOPCD <XDBYC (7) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 8 = BITS 08 - 15
STOPCD <XDBYC (8) failed in ORBW>
ROT T2,-^D08 ;POSITION NEXT BYTE
PUSHJ P,XDBYC0## ;BYTE 9 = BITS 00 - 07
STOPCD <XDBYC (9) failed in ORBW>
ROT T2,-^D08 ;RESTORE T2
JRST .POPJ1## ;36-BIT BYTE SUCCESSFULLY OUTPUT
;NEED A NEW DATA MESSAGE
ORBW60: PUSHJ P,TSAV14## ;SAVE THE T'S MODULO ORBW02
XMOVEI T1,ORBW ;SET NEW NOT-IN-A-RECORD STATE
MOVEM T1,.IOOSR(IO) ;SET IN THE CDB
PUSHJ P,XDEOM0## ;TERMINATE THIS MESSAGE
POPJ P, ;ERROR (BYTE NOT "OUTPUT")
JRST ORBW02 ;START UP A NEW MESSAGE
;REMOTE RECORD-FORMATTED BINARY OUTPUT (ENTERED AS OSR)
ORBR: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
PUSHJ P,.SAVE4## ;SAVE THE P'S
PUSHJ P,TSAV14## ;SAVE THE T'S
ORBR02: ADDI T3,10 ;ALLOW FOR DAP OVERHEAD (USUALLY 5, BUT...)
CAMG T3,.IONOC(IO) ;WILL THIS RECORD FIT?
JRST ORBR05 ;YEAH
PUSHJ P,XDFLS1## ;NO, FLUSH OUT DAP SO FAR
POPJ P, ;SOMETHING DIED
ORBR05: SKIPE .IONIA(IO) ;GOT AN INPUT MESSAGE LURKING ABOUT?
PUSHJ P,ORNIA0 ;YES, CHECK IT OUT
SETZ T2, ;CLEAR DATA RECORD NUMBER
MOVE T3,-T2(P) ;GET USER'S DATA RECORD NUMBER
PUSHJ P,XDDAT1## ;START UP A NEW DATA MESSAGE
POPJ P, ;BUTTS
MOVE P1,-T3(P) ;GET RECORD LENGTH
CAMLE P1,.IONOC(IO) ;ROOM FOR IT LEFT?
JRST [MOVEI M0,$EIRTB ;RECORD TOO BIG
POPJ P,] ;TELL USER OF WOES
MOVE P2,-T4(P) ;GET POINTER TO RECORD DATA
;LOOP OUTPUTTING RECORD DATA BYTES
ORBR20: ILDB T2,P2 ;FETCH NEXT RECORD DATA BYTE
PUSHJ P,XDBYC0## ;STASH THIS 8-BIT BYTE
POPJ P, ;PROPAGATE ERROR RETURN
SOJG P1,ORBR20 ;LOOP FOR REST OF RECORD
;HERE AT END OF RECORD
PJRST XDEOM1## ;CLOSE OFF THIS DAP DATA RECORD
;OUTPUT HELPER TO CHECK OUT PENDING INPUT MESSAGE (STATUS, ETC.)
.ORNIA: EXCH T1,IO ;SETUP I/O CONTEXT
PUSHJ P,ORNIX0 ;CHECK OUT THE INPUT DATA
POP P,0(P) ;TAKE CALLER'S ERROR RETURN
EXCH IO,T1 ;RESTORE RANDOM ACS
POPJ P, ;RETURN AS APPROPRIATE
ORNIA0: PUSHJ P,ORNIX0 ;CHECK OUT THE INPUT DATA
POP P,0(P) ;TAKE CALLER'S ERROR RETURN
POPJ P, ;RETURN AS APPROPRIATE
;THE ACTUAL WORK IS DONE HERE
ORNIX0: PUSHJ P,.SAVE4## ;WANT LOTS OF ACS
PUSHJ P,TSAV14## ;WANT LOTS OF REGISTERS TOO
MOVX M0,IO.NBT ;BUT ESPECIALLY,
IORM M0,.IOCCF(IO) ; WE DON'T WANT TO BLOCK HERE!
PUSHJ P,RDMSG1## ;SEE WHAT THE NETWORK HAS FOR US
JRST [MOVX T1,IO.NBT ;THAT FUNNY LITTLE BIT
ANDCAM T1,.IOCCF(IO) ;GET IT OUT OF THE WAY
CAIE M0,$EINTI ;NON-BLOCKING NETWORK INPUT?
POPJ P, ;NO, BAD NEWS
WARNCD <Network input set, but no data available>
JRST .POPJ1##] ;HMMM CONTINUE WITH OUTPUT
MOVX T1,IO.NBT ;THAT FUNNY WITTLE BIT
ANDCAB T1,.IOCCF(IO) ;GET IT OUT OF THE WAY
CAIE T2,$DHSTS ;LOOKING AT A STATUS MESSAGE?
JRST ORNIX5 ;NO - LOOKS BAD, BUT THERE IS STILL HOPE
TXNE T1,IO.NEP ;BETTER BE AN ACTIVE DAPPER
STOPCD <FAL received a DAP STATUS message on output>
PUSHJ P,RDSTS1## ;GO SLURP UP THE STATUS MESSAGE
POPJ P, ;BAD MESSAGE?
POPJ P, ;PROPAGATE EXCEPTION RETURN
;HERE FOR A NON-STATUS MESSAGE, BETTER BE RUNNING FAL!
ORNIX5: TXNN T1,IO.NEP ;[1040] BETTER BE A PASSIVE DAPPER
STOPCD <Received DAP message not STATUS on data output>
PUSHJ P,RDMSR1## ;FAL, RE-EAT THE MESSAGE
POPJ P, ;HO HUM
MOVEI M0,$EINMP ;EXCEPTION RETURN:INPUT MESSAGE PENDING
POPJ P, ;TELL FAL TO DO SOMETHING ABOUT IT
;FILE MODE TO INPUT SERVICE ROUTINE
MOISTB: XWD 0, ILASC ;.ICDEF -- DEFAULT (7-BIT ASCII)
XWD 0, ILASC ;.ICASC -- ASCII (7-BIT)
XWD 0, ILASC ;.ICAS8 -- ASCII (8-BIT)
XWD 0, ILBYT ;.ICEBC -- EBCDIC (RESERVED)
XWD 0, ILBYT ;.ICPIM -- PACKED IMAGE
XWD 0, ILBYT ;.ICIMG -- IMAGE
XWD 0, ILBYT ;.ICBYT -- BINARY 8-BIT BYTES
XWD 0, ILBYT ;.ICBIN -- BINARY 36-BIT BYTES
;FILE MODE TO OUTPUT SERVICE ROUTINE
MOOSTB: XWD 0, OLASC ;.ICDEF -- DEFAULT (7-BIT ASCII)
XWD 0, OLASC ;.ICASC -- ASCII (7-BIT)
XWD 0, OLASC ;.ICAS8 -- ASCII (8-BIT)
XWD 0, OLBYT ;.ICEBC -- EBCDIC (RESERVED)
XWD 0, OLBYT ;.ICPIM -- PACKED IMAGE
XWD 0, OLBYT ;.ICIMG -- IMAGE
XWD 0, OLBYT ;.ICBYT -- BINARY 8-BIT BYTES
XWD 0, OLBYT ;.ICBIN -- BINARY 36-BIT BYTES
SUBTTL IOFUN - Random I/O functions
;IOFUN -- RANDOM I/O FUNCTIONS
;Call is:
;
; MOVX T1,<CDB>
; MOVX T2,<FUN>
; MOVX T3,<ARG>
; MOVX T4,<ETC>
; ERROR RETURN
; NORMAL RETURN
;
;Where <CDB> is the address of the controlling I/O CDB; <FUN> is
;the function to be performed (.FUxxx); <ARG> is the first argument
;(if any) to be passed (or perhaps returned depending on the func-
;tion being performed); <ETC> is any other argument needed.
;
;On error return the requested function could not be performed (or
;possibly the function itself was illegal), an error code is in M0.
;
;On normal return the function completed successfully (see the in-
;dividual functions for more details).
;
;Uses T1 - T4.
ENTRY .IOFUN
INTERN IOFUN0, IOFUN1
.IOFUN: PUSHJ P,.SACIO## ;SWITCH TO I/O CONTEXT
IOFUN0: PUSHJ P,.SAVE4## ;SAVE THE P'S
IOFUN1: PUSHJ P,TSAV14## ;AND THE T'S AS WELL
CAIL T2,1 ;IS FUNCTION IN RANGE?
CAILE T2,.FUMAX ; . . .
JRST [MOVEI M0,$EIILF ;ILLEGAL FUNCTION
POPJ P,] ;ERROR RETURN
MOVE P1,.IOCCF(IO) ;CALL WITH P1 HOLDING CHANNEL CONTROL FLAGS
MOVE P2,.IOIOC(IO) ;AND P2 WITH THE I/O CONTROL FLAGS
PJRST @IOFUNT-1(T2) ;DISPATCH TO FUNCTION-SPECIFIC PROCESSOR
; (FUNCTIONS START AT 1 . . .)
;THE FUNCTION DISPATCH TABLE
IOFUNT: IFIW IFBOR ;01 - WRITE BEGINING OF RECORD
IFIW IFLSN ;02 - WRITE ASCII LINE SEQUENCE NUMBER
IFIW IFIEC ;03 - ATTEMPT I/O ERROR RECOVERY CONTINUATION
.FUMAX==.-IOFUNT ;MAXIMUM FUNCTION
SUBTTL IOFUN - IFBOR -- Write begining of record
;IFBOR - WRITE BEGINING OF RECORD
;Call is:
;
; MOVX T3,<LEN>
; MOVX T4,<ETC>
; PUSHJ P,IFBOR
; error return
; normal return
;
;Where <LEN> is the length of the record about to be written (via calls
;to the I/O service routine operating in byte mode); <ETC> is the record
;"address" for MACY11-packed files.
;
;On error return an I/O error occurred, or the length is invalid (e.g.,
;too big, too small).
;
;On normal return the OSR is set to accept data bytes.
;
;Uses T1 - T4.
IFBOR: TXNE P1,IO.NET ;LOCAL OR REMOTE?
JRST RFBOR ;REMOTE
; JRST LFBOR ;LOCAL
;CONTINUED ON NEXT PAGE
;HERE ON LOCAL FILE SERVICE BEGINING OF RECORD
LFBOR: TXNE P2,IC.MCY!IC.MEY;MACY11-PACKING?
JRST LFMCY ;YES
MOVEI M0,$EINRS ;NO, NOT A RECORD-STRUCTURED FILE
POPJ P, ;PROPAGATE ERROR
;HERE TO START UP A MACY11-PACKED RECORD
LFMCY: SKIPE .IOOS3(IO) ;STILL IN A RECORD?
JRST [MOVEI M0,$EIRSO ;YES, RECORD STILL OUTSTANDING
POPJ P,] ;RETURN ERROR
CAIL T3,0 ;NOT IN A RECORD, RANGE-CHECK SIZE
CAILE T3,177777-6 ;WILL IT FIT?
JRST [MOVEI M0,$EIRTB ;NO, RECORD TOO BIG
POPJ P,] ;RETURN ERROR
CAIL T4,0 ;RANGE-CHECK ADDRESS TOO
CAILE T4,177777 ;WILL IT FIT?
JRST [MOVEI M0,$EIRAI ;NO, RECORD ADDRESS ILLEGAL
POPJ P,] ;RETURN ERROR
ADDI T3,6 ;ADD IN MACY11 OVERHEAD
HRL T3,T4 ;POSITION ADDRESS
MOVEM T3,.IOOS0(IO) ;SET ADDRESS,,COUNT FLAG FOR OLMCY
JRST .POPJ1## ;SUCCESSFUL RETURN
;HERE FOR REMOTE BEGINING OF RECORD
RFBOR: CAIG T3,0 ;*** CAN'T DO 0-LENGTH RECORDS
STOPCD <Zero/Negative length record in RFBOR>
MOVEM T3,.IOOS1(IO) ;JUST LEAVE IT FOR ORBR/ETC.
JRST .POPJ1## ;RETURN HAPPILY NOW
SUBTTL IOFUN - IFLSN -- Write ASCII line-sequence-number
;IFLSN - WRITE ASCII LINE-SEQUENCE-NUMBER
;Call is:
;
; MOVX T3,<LSN>
; PUSHJ P,IFLSN
; error return
; normal return
;
;Where <LSN> is the binary line sequence number (maximum 99,999) to
;be written to the output file. If the <LSN> is 1B0 or -1 then the
;LSN is interpreted to mean only an SOS page mark. If the LSN is
;negative, then it is interpreted as being an SOS page mark followed
;by a normal LSN.
;
;On error return an I/O error occurred, or the LSN is illegal.
;
;On normal return the LSN has been set, the OSR is ready to accept
;output characters.
;
;It is the caller's responsibility to ensure that the output file is
;at the "begining" of a text line.
;
;Uses T1 - T4.
IFLSN: JUMPGE T3,IFLSN2 ;IF POSITIVE, THEN NORMAL LSN
MOVSI T2,(1B0) ;1B0 TO FLAG PAGE MARK
MOVEM T2,.IOOS0(IO) ;REMEMBER THAT MUCH
ANDI T3,777777 ;REDUCE TO JUST LSN FIELD
CAIE T3,0 ;IF 0
CAIN T3,777777 ;OR -1
JRST .POPJ1## ;THEN ALL DONE (ONLY A PAGE MARK)
IFLSN2: CAIE T3,0 ;0 IS ILLEGAL
CAILE T3,^D99999 ;WILL LSN FIT IN 5 DIGITS?
JRST [MOVX M0,$EILTB ;LSN TOO BIG
POPJ P,] ;ERROR RETURN
SKIPGE .IOOS0(IO) ;STILL HAVE AN LSN OUTSTANDING?
HRLI T3,400000 ;SET .LT. 0 TO INDICATE PAGE MARK
IFLSN5: MOVEM T3,.IOOS0(IO) ;SAVE LSN FOR OUTPUT SERVICE ROUTINE
; (THIS IS DONE SINCE OUTPUT MAY NOT HAVE
; BEEN INITIALIZED YET SO WE CAN'T DIDDLE
; WITH .IOOBP/ETC HERE)
JRST .POPJ1## ;SUCCESSFUL RETURN
SUBTTL IOFUN - IFIEC -- I/O error recovery and continuation
;IFIEC - I/O ERROR CONTINUATION
;Call is:
;
; PUSHJ P,IFIEC
; error return
; normal return
;
;On error return the I/O service routine cannot be continued (e.g., the
;network link is down, the disk was dismounted, etc.), an error code is
;in M0.
;
;On normal return the I/O service routine is ready to accept data again
;(for input, simply call the service routine again; for output the failed
;call must be re-executed since the data from the failed call was not
;accepted).
;
;Uses T1 - T4.
IFIEC: STOPCD <I/O error recovery not yet written (IFIEC)>
;IOERX - READ AND TRANSLATE EXTENDED I/O ERROR STATUS
IOERX1: MOVE T4,.IOCHN(IO) ;I/O CHANNEL IN QUESTION
MOVEI T3,.DFRES ;FUNCTION: RETURN ERROR STATUS
MOVE T2,[2,,T3] ;DEVOP. ARG POINTER TO
DEVOP. T2, ;READ EXTENDED I/O ERROR STATUS
POPJ P, ;DUH?
CAILE T2,IOERXL ;WITHIN KNOWN RANGE?
SETO T2, ;NO
MOVE M0,IOERXT(T2) ;GET INPUT,,OUTPUT ERROR STATUS
JRST .POPJ1## ;RETURN WITH ERROR CODE IN M0
;THE EXTENDED ERROR STATUS TRANSLATION TABLE
XWD $EIXXX,$EIXXX ;(--) UNKNOWN ERROR STATUS
IOERXT: XWD $EIXXX,$EIXXX ;(00) UNKNOWN ERROR STATUS
XWD $EIXXX,$EILLE ;(01) PAGE LIMIT EXCEEDED
XWD $EIXXX,$EIVFE ;(02) VFU FORMAT ERROR
XWD $EILBL,$EILBL ;(03) LABEL TYPE ERROR
XWD $EILBL,$EILBL ;(04) HEADER LABEL ERROR
XWD $EILBL,$EILBL ;(05) TRAILER LABEL ERROR
XWD $EILBL,$EILBL ;(06) VOLUME LABEL ERROR
XWD $EIDEV,$EIDEV ;(07) HARD DEVICE ERROR
XWD $EIDAT,$EIDAT ;(10) DATA PARITY ERROR
XWD $EIHWL,$EIHWL ;(11) WRITE-LOCK ERROR
XWD $EILBL,$EILBL ;(12) ILLEGAL POSITIONING (MTA)
XWD $EILBL,$EILBL ;(13) BEGINING OF TAPE (MTA)
XWD $EILBL,$EILBL ;(14) ILLEGAL OPERATION (MTA)
XWD $EILBL,$EILBL ;(15) FILE NOT FOUND (MTA)
XWD $EILBL,$EILBL ;(16) OPR CANCELLED VOL SWITCH REQUEST (MTA)
XWD $EILBL,$EILBL ;(17) TOO MANY VOLUMES (MTA)
XWD $EINLA,$EINLA ;(20) NETWORK LINK DOWN
XWD $EIXXX,$EILUC ;(21) LP20 - UNDEFINED CHAR INTERRUPT
XWD $EIXXX,$EIVRP ;(22) LP20 - RAM PARITY ERROR
XWD $EILBL,$EILBL ;(23) LABELER REQUEST ABORTED BY RESET
XWD $EILBL,$EILBL ;(24) VOLUME PROTECTION FAILURE
XWD $EILBL,$EILBL ;(25) FILE PROTECTION FAILURE
XWD $EILBL,$EILBL ;(26) UNEXPIRED FILE
IOERXL==.-IOERXT ;LENGTH OF EXTENDED ERROR TRANSLATION TABLE
END