         TITLE     DIO V17 -- DISK INPUT OUTPUT PROGRAM
         PROGRAM   DIO   17
*
         DEF       FCBINIT         FILE CONTROL BLOCK INITIALIZE
*=    SUBROUTINE FCBINIT (LFC, PBLK, FUNC, RECLEN, *ERR, *NOWAIT)
*          INTEGER    LFC          logical file code
*          INTEGER    PBLK(4)      parameter block to be filled
*          INTEGER    FUNC         function code for FCB
*          INTEGER    RECLEN       length of record for blocking
*          ADDRESS    ERR          error return address
*          ADDRESS    NOWAIT       no wait normal return address
*= Initialize the parameter block for future reads and writes
           SPACE   3
         DEF       DPWRITE         NO-WAIT I/O COMPLETE SECTOR WRITE
*=    SUBROUTINE DPWRITE (PBLK, BUFFER, COUNT, RECORD, *ERR, *NOWAIT)
*          INTEGER    PBLK(4)      parameter block
*          *          BUFFER       buffer to write (int *1,2,4,char)
*          INTEGER    COUNT        count of bytes to write
*          INTEGER    RECORD       record number to write to
*= Write unblocked to device/file defined by PBLK
         SPACE     3
         DEF       DPREAD          NO-WAIT I/O COMPLETE SECTOR READ
*          INTEGER    PBLK(4)      parameter block to be filled
*=    SUBROUTINE DPREAD (PBLK, BUFFER, COUNT, RECORD, *ERR, *NOWAIT)
*= Read unblocked from device/file defined by PBLK
         DEF       DWRITE          WAIT I/O PARTIAL SECTOR WRITE
*          INTEGER    PBLK(4)      parameter block to be filled
*=    SUBROUTINE DWRITE (PBLK, BUFFER, COUNT, RECORD, *ERR, *NOWAIT)
*= Write blocked to a file defined by PBLK
         DEF       DREAD           WAIT I/O PARTIAL SECTOR READ
*=    SUBROUTINE DREAD (PBLK, BUFFER, COUNT, RECORD, *ERR, *NOWAIT)
*          INTEGER    PBLK(4)      parameter block to be filled
*= Read blocked from a file defined by PBLK
         DEF       DERROR          RETURN ERROR CODES
*=    INTEGER FUNCTION DERROR (PBLK)
*= Return status of last io on the PBLK
         DEF       DPCOUNT         COUNT OF BYTES TRANSFERED
*=    INTEGER FUNCTION DPCOUNT (PBLK)
*= Return byte count of last io transfer on the PBLK
         PAGE
*
* AUTHOR: A D PATEL               DATE: 1982
* REVISIONS:
*     X14          L. TATE (4/29/84)
*                  -NO WAIT IO DOES NOT CHECK ERROR OF PREVIOUS ATTEMPT
*                  -ENTRY DERROR ADDED TO RETURN ERROR CODE (REENTRANT)
*     X15          L. TATE (7/5/84)
*                  -DATA BUFFER MAY BE IN EXTENDED MEMORY.
*     X15.1        L. TATE (9/5/84)
*                  -THE FORMAT BIT IS NOW CLEARED ON BYTE BUFFERS
*     X16          L. TATE (1/7/85)
*                  -ALLOW LOCAL ERROR/END ACTION RETURNS
*     X16.1        LTATE (4/15/85)
*                  -REARRANGED ERROR TESTING SO EOF WILL BE DETECTED.
*     X16.2        LTATE (5/13/85)
*                  -ENSURED EXTENDED ADDRESSING WAS CANCELED WHEN SET.
*     X17          LTATE (5/27/85)
*                  -RETURN TRANSFER COUNT AS FUNCTION VALUE
*
*
*        TO USE THESE FUNCTIONS INCLUDE  $OBJECT
*                                        $SELECTF ^(SEMS)O.DIO15
*
*        THIS SET OF PROGRAMS CAN BE CALLED
*        FROM FORTRAN BY THE FOLLOWING CSQ'S
*
*        CALL FCBINIT (LU   ,PBLK  ,FUNC   ,RECLN,$NN,$NN1)
*        CALL DREAD   (PBLK ,BUFFER,BYTECNT,RECNO,$NN,$NN1)!WAIT I/O
*        CALL DPREAD  (PBLK ,BUFFER,BYTECNT,RECNO,$NN,$NN1)!NO_WAIT I/O
*        CALL DWRITE  (PBLK ,BUFFER,BYTECNT,RECNO,$NN,$NN1)!WAIT I/O
*        CALL DPWRITE (PBLK ,BUFFER,BYTECNT,RECNO,$NN,$NN1)!NO_WAIT I/O
*        ERROR = DERROR(PBLK)                              !ERROR CHECK
*        COUNT = DPCOUNT(PBLK)                             !BYTE COUNT
*
*        BYTECNT= INTEGER*4; # OF BYTES FOR THIS I/O
*
*        LU     = INTEGER*4; NO-CHARACTER ARGUMENTS ALLOWED
*                            PLEASE DEFINE LU AS A PARAMETER SUCH THAT
*                            IT CAN BE REASSIGNED TO DIFFRNT DEVICE EASE
*        PBLK   = INTEGER*4; PBLK(4); PBLK FOR FCB ADDRS STOR & ERR STAT
*
*                            PBLK(1); FCB ADDRESS STORAGE LOCATION
*                            PBLK(2); NOT USED (SPARE)
*                            PBLK(3); NOT USED (SPARE)
*                            PBLK(4); ERROR STATUS AS SPECIFIED BELOW
*
*        PBLK(4)= ERROR STATUS; FOLLOWING CODES ARE IMPLEMENTED
*
*        0      = I/O COMPLETE WITHOUT ERROR
*        1      = REC # .LE. 0
*        2      = BYTECNT .LE. 0
*        3      = EOF
*        4      = EOM
*        5      = RECORD LENGTH .LT. 0
*
*        BUFFER = DATA BUFFER IN INTEGER OR CHARACTER FORMAT
*                 MAY BE IN EXTENDED MEMORY
*
*        BYTECNT  # OF BYTES FOR THIS TRANSFER
*
*        RECNO    RECORD # FOR THIS I/O
*
*        FUNC      INTEGER*4  ; FUNC DATA/8Z0A000000/
*                               REFER TO TABLE 7_4 OF MPX2.1 VOL 1,
*                               PAGE 7-33 FOR DETAILS ON THESE BITS
*        BIT ASSIGNMENT:        NO_WAIT I/O SPECIFICATION    BIT 0
*                               NO ERROR RETURN PROCESSING   BIT 1
*                               BINARY TRANSFER DFI          BIT 2
*                               NO STATUS CHECK BY HANDLER   BIT 3
*                               RANDOM ACCESS                BIT 4
*                               BLOCKED I/O (DISC & TAPE)    BIT 5
*                               EXPANDED FCB (MUST BE ON)    BIT 6
*                               TASK WILL NOT ABORT          BIT 7
*                               DEVICE FORMAT DEFINATION     BIT 8
*
*        $NN    = FATAL ERROR RETURN CHECK ENTIRE WORD & REFER TO
*                 MPX2.1 VOLM 1.; FIG: 7-3; TABLE 7-4; FCB BIT INTERP
*                 *NOTE* CAN BE SPECIFIED AT READ/WRITE CALL, BUT
*                 FUTURE CALLS USE LAST SUPPLIED VALUE.
*
*        $NN1   = NO_WAIT I/O NORMAL RETURN STATEMENT LABEL; AFTER THIS
*                 LABLE YOU MUST HAVE ( CALL X:XNWIO) TO  TERMINATE
*                 NO_WAIT I/O.
*                 *NOTE* CAN BE SPECIFIED AT READ/WRITE CALL, BUT
*                 FUTURE CALLS USE LAST SUPPLIED VALUE.
*
*
*
*        The DREAD & DRITE routines can be used to perform I/O to disk
*        files where record length are such that  FORTRAN random
*        access routines cannot be used; (e.g. record length > 248
*        bytes). These routines perform BLOCKING of data within the
*        physical sector and has minimum overhead for the operation.
*
*
*        The DPREAD & DPWRITE routines are general purpose I/O
*        functions to perform I/O operations to any device. The FUNC
*        word defines the type of operation that the routine will
*        accomplish. It is totaly dependent on the functions implemented
*        by the specific device driver. User can perform I/O in wait
*        mode or no-wait mode. If the user wants to perform no-wait I/O
*        he has to have $NN1; end action receiver established. The
*        example of no-wait I/O is as follows:
*
*        CALL FCBINIT (LFC,PBLK,FUNC,RECLN,$NN,$NN1)
*
*        10        CONTINUE
*
*        CALL DPWRITE (PBLK,BUF,BYTECNT, irec ) ! irec option for random
*                                                 access disk files only
*
*
*        any FORTRAN or ASSEMBLY code
*
*        nn1       CONTINUE
*
*                  Any code including I/O to same LFC or any other
*                  device. The I/O to the same LFC shold be before
*                  the following X:XNWIO  function.
*
*                  CALL X:XNWIO
*
*
*
*
*        REV 1.1   BY A. PATEL IMPELMET CHECKING OF NO WAIT BIT
*                  TO BYPASS ERROR CHECKING FOR LAST I/O
*                  ALSO ADD CODE TO CHECK ERR AT THE COMLETION OF I/O
*                  IF THE WAIT BIT IS SET
*
*        REV 14.0  BY L.TATE IMPLEMENT DERROR ROUTINE
*
*                        ERROR = DERROR(PBLK)
*
*                  REENTRANT.... CAN BE CALLED FROM THE
*                  ERROR AND END ACTION HANDLERS.
*
*            ERROR CODES:
*
*                  0  - NO ERROR
*                  1  - REC # .LE. 0
*                  2  - BYTECNT .LE. 0
*                  3  - EOF
*                  4  - EOM
*                  5  - RECORD LENGTH .LT. 0
*                  6  - INVALID BLOCKING BUFFER
*                  7  - WRITE PROTECT
*                  8  - INOPERABLE DEVICE
*                  9  - BEGINNING OF MEDIUM
*
*        REV 15.0  BY L.TATE EXTENDED MEMORY BUFFER CAPABILITY
*        REV 15.1  BY L.TATE CORRECTED CHARACTER ADDRESS MASKING
*        REV 16    BY L.TATE ADDED LOCAL ERROR/END ACTION RETURNS.
*
*
         PAGE
*
* EXTERNAL REFERENCES
*
         EXT       R.EF            POINTER TO # PARMS IN BL
         EXT       E.RR            ERROR PROCESSOR
         EXT       I.IO15          GET FCB + CHECKS
         EXT       N.X             USER'S RETURN ADDRESS
         EXT       R.X             ALTERNATE RETURN ADDRESS
         EXT       F.F             FLAGS FOR I/O INITIALIZATION
         EXT       N.CL            USER'S CALL ADDRESS
         EXT       F.C             CURRENT FCB ADDRESS
         EXT       REQ.PARM        REQUIRED PARAMETER PROCESSOR
         EXT       OPT.ADDR        OPTIONAL ADDRESS PROCESSOR
         EXT       REQ.ADDR        REQUIRED ADDRESS PROCESSOR
         EXT       P_BLOCK         192W TEMPARARY WORK BUFFER
         PAGE
*
* EQUATES
*
         M.EQUS                    GENERAL EQUATES
         M.TBLS                    EQUATES FOR ALL TABLES
         SPACE     3
*
*
RANACCRL EQU       1W              RANDOM ACCESS RECOD LENGTH STORED IN
PBK.SFLG EQU       3W              PARAMETER BLOCK ERROR STATUS
BUFADDR  EQU       2W              BUFERR ADDRES POINTER  IN ARG
PBKADDR  EQU       1W              PARAMETER BLOCK POINTER IN ARG
FTN.I    EQU       0               INDIRECT BIT OF FORTRAN PARAMETER
FTN.X    EQU       1               INDICATES ADDRESS IS 24 BITS LONG
*
*        ERROR CODES
*
NOERR    EQU       0               NO  ERROR
RECNERR  EQU       1               RECORD #.LT. 0
BCNTERR  EQU       2               TRANSFER COUNT .LT. 0
EOFERR   EQU       3               EOF
EOMERR   EQU       4               EOM
RECLERR  EQU       5               RECORD LENGTH .LT. 0
BB.ERR   EQU       6               INVALID BLOCKING BUFFER
PRO.ERR  EQU       7               WRITE PROTECT VIOLATION
INOP.ERR EQU       8               DEVICE IS INOPERABLE
BOM.ERR  EQU       9               BEGINNING OF MEDIUM
         PAGE
*
* LOCAL MEMORY
*
         BOUND     1W
BLKSIZE  DATAW     768             BYTES IN A SECTOR
X1SAVE   DATAW     0               SAVE OF PARAMETER POINTER
         ACW       A(LFC)          NEEDED FOR I.IO15
LFC      DATAW     0
XMASK    DATAW     X'FFFFFF'       24 BIT ADDRESS MASK
WMASK    DATAW     X'0007FFFF'     DATA BUFFER MASK; NO EXTENDED ADDRESS
UBA      DATAW     0               USER BUFFER ADDRESS STORAGE
TC       DATAW     0               USER REQUESTED TRANSFER COUNT IN BYTE
RN       DATAW     0               USER REQUESTED RECORD #
BSA      DATAW     0               SECTOR # FORM ORIGIN OF THE DISC FILE
SWN      DATAW     0               RELATIVE WIDTH OF PARTIAL SECTOR I/O
PBLKA    DATAW     0               TEMP STORAGE FOR PBLK ADDRESS
FLAG     DATAH     0
B0.FLAG  EQU       0               FLAG
B1.FLAG  EQU       1               DIRECT PROCEED I/O READ/WRITE FLAG
X.FLAG   EQU       2               THE BUFFER IS IN EXTENDED MEMORY
COUNT    RES       1W              COUNT OF BYTES TRANSFERED
         PAGE
         BOUND     1W
FCBINIT  EQU       $
         TRR       R0,X1           SAVE R0 FOR ARG POINTER
         LW        R7,0W,X1        GET # PARMS
         ABR       R7,29           BUMP BY 4 FOR RETURN LOCATION
         ADR       R7,R0           FIND RETURN LOCATION
         STD       R0,N.X          *   ERROR EXITS
         STW       X1,X1SAVE       SAVE X1 FOR LATER  USE
         BL        REQ.PARM        GET LFC
         STW       R7,LFC          SAVE LFC
         LA        X1,X1SAVE       PUT ADDRESS # OF PARAMETERS IN X1
         LI        R7,1
         STB       R7,F.F
         BL        I.IO15          FIND FCB ADDRESS
         LW        X1,X1SAVE       RESTORE ARG POINTER IN X1
         STW       X3,*2W,X1       SAVE FCB ADDRESS FOR LATER USE
         LA        R5,*5W,X1       ERROR SUB ADDR TO R5
         ANMW      R5,WMASK        STRIP HIGH BITS
         STW       R5,FCB.ERRT,X3  PUT ERR ADDR AT FCB(6)
         LW        R6,*3W,X1       GET EFUNCTION CODE & PUT IT IN FCB(2)
         STW       R6,FCB.CBRA,X3  STORE AT GENERAL CONTROL SPEC
         TBR       R6,4            IS THIS RAN ACCESS RECORD
         BNS       FCB.1           NO RECL-LENGTH FOR THIS I/O
         LW        R7,*4W,X1       GET RECORD LENGHT
         BCT       LE,RELRTRN      RECORD LENGTH .LT. 0
         STW       R7,RANACCRL,X3  STORE RANDOM ACCESS RECL-LENGTH IN 1W
         BU        FCB.2
*
FCB.1    EQU       $
         ZMW       RANACCRL,X3     CLEAR THE RANDOM ACCESS STORAGE
*
FCB.2    EQU       $
         TBR       R6,0            IS IT A NO WAIT I/O
         BNS       FCB.3           BY PASS STUFFING NO WAIT DATA
         STW       R5,FCB.NWER,X3  PUT NO_WAIT ERROR RETURN ADDRESS IN F
         LA        R5,*6W,X1       GET THE NORMAL RETURN ADDRESS
         ANMW      R5,WMASK        MASK OUT HI LOW BITS
         STW       R5,FCB.NWOK,X3  PUT NO_WAIT NORMAL RETURN ADDRESS
*
FCB.3    EQU       $
         BU        *N.X
         PAGE
*
*        DPWRITE   ENTRY POINT
*
         BOUND     1W
DPWRITE  EQU       $
         SBM       B1.FLAG,FLAG    SET WRITE IND
         BU        DP.01           COMMON ROUTINE
         SPACE     3
*
*        DPREAD    ENTRY POINT
*
DPREAD   EQU       $
         ZBM       B1.FLAG,FLAG    CLEAR WRITE IND
         SPACE     3
DP.01    EQU       $
         TRR       R0,X2           PUT LIST POINTER INTO X2
         ABR       R0,29           +1W FOR ARG CNT
         ADMW      R0,0W,X2        ADD # OF LIST BYTES
         STD       R0,N.X          SAVE RETURN ADDRESS
         BL        SETUP           SETUP ARGUMENTS FOR THIS CALL
         LW        R5,UBA          GET USER BUFFER ADDRESS
         STW       R5,FCB.ERWA,X1  STORE BUFFER ADDRESS IN FCB
         LW        R6,TC           LOAD TRANSFER COUNT
         STW       R6,FCB.EQTY,X1  STORE BYT CNT IN FCB(9)
         TBM       4,FCB.GCFG,X1   IS IT A RANDOM ACCESS I/O
         BNS       $+3W            BYPASS STORING OF RANDOM ACCESS ADR.
         LW        R7,BSA          GET SECTOR #
         STW       R7,FCB.ERAA,X1  STORE IT IN RANDOM ACESS ADDRESS
         TBM       B1.FLAG,FLAG    TEST R/W FLAG
         BCT       SET,WRIT        BR IF WRITE
         SVC       1,X'31'         READ RECORD SVC
         BU        DP.1            RETURN TO CALLER
WRIT     SVC       1,X'32'         WRITE RECORD SVC
*
DP.1     EQU       $
         TBM       0,FCB.GCFG,X1   IS IT A NO_WAIT I/O ?
         BS        $+2W            BYPASS ERROR CHECKING & RTRN TO CALLE
         BL        CHKERR          CHECK IF ANY ERROR DURING PREVIOUS I/
         BU        *N.X            RETURN TO CALLER
         PAGE
*
*        DREAD     ENTRY POINT
*
         BOUND     1W
DREAD    EQU       $
         TRR       R0,X2           PUT LIST POINTER INTO X2
         ABR       R0,29           +1W FOR ARG CNT
         ADMW      R0,0W,X2        ADD # OF LIST BYTES
         STD       R0,N.X          SAVE RETURN ADDRESS
         BL        SETUP           SETUP WORK AREA
DREAD.1  LW        R6,TC           GET TRANSFER COUNT
         BCT       LE,*N.X         EXIT IF NEG OR ZERO
         LW        R5,SWN          GET STARTING WD NUMBER
         BCF       ZR,DREAD.2      BR IF NOT START OF SECT
         LW        R5,UBA          START OF SECT, GET BUFFER ADDR
         STW       R6,FCB.EQTY,X1  PUT BYTE COUNT IN FCB(9)
         STW       R5,FCB.ERWA,X1  STORE ADDRESS IN FCB(8)
         LW        R5,BSA          GET STARTING SECT NO
         STW       R5,FCB.ERAA,X1  PUT IN FCB(10)
         SVC       1,X'31'         READ FILE
         BL        DWAIT           WAIT FOR I/O COMP
         BU        *N.X            RETURN
DREAD.2  LA        R5,P_BLOCK      GET TEMP WORK BUF ADDRESS
         STW       R5,FCB.ERWA,X1  PUT IN FCB
         LW        R6,BLKSIZE      GET BLKSIZE IN BYTES
         STW       R6,FCB.EQTY,X1  PUT IT IN FCB(9)
         LW        R5,BSA          GET SECT ADDR
         STW       R5,FCB.ERAA,X1  PUT SECT ADDRESS IN FCB(10)
         ABM       31,BSA          BUMP SECTOR ADDR
         SVC       1,X'31'         READ A SECT
         BL        DWAIT           WAIT FOR I/O COMP
         LNW       R5,BLKSIZE      GET MAX BYT CNT
         ADMW      R5,SWN          ONLY REST OF BUFFER FOR TRANSFER
         LA        X3,P_BLOCK      GET BUFFER ADDR
         ADMW      X3,SWN          POINT TO START WD
         LW        X2,UBA          GET USER BUFFER ADDR
         LW        R4,TC           GET TRANSFER COUNT
         ZMW       SWN             ZERO START WD NO
         TBM       X.FLAG,FLAG     TEST FOR EXTENDED MEMORY
         BNS       DREAD.3         SKIP OVER EXTENDED ADDRESSING
         SEA                       SET EXTENDED ADDRESSING
DREAD.3  LB        R6,0B,X3        GET BYTE
         STB       R6,0B,X2        PUT BYTE
         SUI       R4,1            REDUCE TC
         BZ        DREAD.4         RETURN IF COMPLETE
         STW       R4,TC           UPDATE LOCN
         ABR       X3,31           BUMP ADDR
         ABR       X2,31           BUMP ADDRE
         ABM       31,UBA          BUMP USER BUFFER ADDR
         BIB       R5,DREAD.3      LOOP UNTIL TRANSFER COMP
         CEA                       CANCEL WHEN MOVE DONE, SET OR NOT
         BU        DREAD.1         GO GET REST OF DATA
DREAD.4  EQU       $
         CEA                      CANCEL EXTENDED ADDRESSING ON EXIT
         BU        *N.X            RETURN
         PAGE
*
* DERROR
*
         BOUND     1W
DERROR   EQU       $
         LW        X2,0,X1         GET FCB ADDRESS
         LW        R5,FCB.SFLG,X2  GET FCB STATUS
         TBR       R5,2            BLOCKING BUFFER
         BS        DERR.2
         TBR       R5,3            WRITE PROTECT
         BS        DERR.3
         TBR       R5,4            DEVICE INOPERABLE
         BS        DERR.4
         TBR       R5,5            BEGINNING OF MEDIUM
         BS        DERR.5
         TBR       R5,6            EOF
         BS        DERR.6
         TBR       R5,7            EOM
         BS        DERR.7
         TBR       R5,1            ERROR
         BNS       DERR.1          NO ERROR FOUND
         SLL       R5,10           STRIP OUT PRE
         SRL       R5,10           PUT BACK
         TRN       R5,R7           RETURN IT
         BU        DERR.99         RETURN
DERR.1   EQU       $
         LW        R7,PBK.SFLG,X1  GET ANY PBLK ERRORS
         BU        DERR.99
DERR.2   EQU       $
         LI        R7,BB.ERR       BLOCKING ERROR
         BU        DERR.99
DERR.3   EQU       $
         LI        R7,PRO.ERR      PROTECT ERROR
         BU        DERR.99
DERR.4   EQU       $
         LI        R7,INOP.ERR     INOPERABLE
         BU        DERR.99
DERR.5   EQU       $
         LI        R7,BOM.ERR      BEGINNING OF MEDIUM
         BU        DERR.99
DERR.6   EQU       $
         LI        R7,EOFERR       EOF
         BU        DERR.99
DERR.7   EQU       $
         LI        R7,EOMERR
         BU        DERR.99
DERR.99  EQU       $
         TRSW      R0              RETURN
         PAGE
*
* DPCOUNT          RETURN COUNT OF BYTES TRANSFERED IN LAST READ
*
         BOUND     1W
DPCOUNT  EQU       $
         LW        X2,0,X1         GET FCB ADDRESS
         BZ        DPCNT.Z         NOT A PROPER PBLK YET
         TBM       0,3W,X2         TEST FOR OPERATION IN PROGRESS
         BS        DPCNT.Z         NOT VALID COUNT YET
         LW        R7,4W,X2        GET BYTE COUNT
         TRSW      R0
DPCNT.Z  EQU       $
         ZR        R7              NOTHING TO RETURN
         TRSW      R0
         PAGE
*
*
*                                  GET ARGUMENTS AND FIND SECTOR #
*
*
         BOUND     1W
SETUP    EQU       $
         LW        X1,*PBKADDR,X2  GET FCB ADDR
         LA        X3,*PBKADDR,X2  GET ADDRESS OF PARAMETERS BLOCK
         STW       X3,PBLKA        STORE PBLK ADDRESS FOR ERR REPORTING
         ZMW       PBK.SFLG,X3     ZERO PREVIOUS ERRORS
         ZMW       FCB.SFLG,X1     ZERO PREVIOUS ERRORS
         SPACE     3
*
* BUFFER MAY BE IN EXTENDED MEMORY, MUST MANUALLY GO DOWN
* INDIRECT CHAIN TILL REACHED.
*
         TBM       FTN.I,BUFADDR,X2   TEST FOR PARAMETER WORD
         BNS       SETUP.3         NORMAL PARAMETER
         SPACE     3
*
* EXTENDED ADDRESS TYPE
*
         SBM       X.FLAG,FLAG     NOTE EXTENDED BUFFER
         LW        X3,BUFADDR,X2   PARAMETER WORD
         LW        X3,0,X3         GET FIRST ADDRESS
SETUP.1  EQU       $
         TBR       X3,FTN.I        TEST FOR PSEUDO-INDIRECT
         BNS       SETUP.2         END OF LOOK
         LW        X3,0,X3         NEXT WORD IN CHAIN
         BU        SETUP.1         LOOP
SETUP.2  EQU       $
         TRR       X3,R6           PUT LIKE REST
         ANMW      R6,XMASK        MASK OUT NON-ADDRESS DATA
         ANMW      X3,=X'0F000000' CLEAR OUT REST
         SRL       X3,24           ISOLATE BYTE
         TRR       X3,R5           PUT IN 5 FOR TESTING
         LW        X3,PBLKA        GET BACK THE PBLK ADDRESS
         BU        SETUP.4         CONTINUE
         SPACE     3
*
* NORMAL BUFFER ADDRESS FETCH
*
SETUP.3  EQU       $               NORMAL ARGUMENT PROCESSING
         ZBM       X.FLAG,FLAG     NOTE NON-EXTENDED BUFFER
         LA        R6,*BUFADDR,X2  GET CONTENT OF BUF ADDRESS LOCATION
         ANMW      R6,WMASK        MASK OUT UNWANTED DATA
         LB        R5,BUFADDR,X2   GET DATA TYPE OF BUFFER
         SPACE     3
*
* TEST FOR TYPING NOW
*
SETUP.4  EQU       $
         CI        R5,X'B'         IS IT CHARCTER TYPE
         BNE       SETUP.5         NO, IT IS NOT CHARCTER
         ADI       X2,4            ADJUST ARG PTR FOR DBL WRD ARG
SETUP.5  EQU       $
         CI        R5,X'01'        IS IT INTEGER*2 ARG
         BNE       SETUP.6         NO, IT IS NOT INTEGRE*2
         ZBR       R6,31           CLEAR C BIT
SETUP.6  EQU       $
         STW       R6,UBA          STORE IT
         LW        R6,*3W,X2       GET BYTE COUNT
         BCT       LE,TCERR        IF ZERO, RETURN
         STW       R6,TC           SAVE
         TBM       4,FCB.GCFG,X1   IS THIS A RANDOM ACCESS I/O
         BNS       SETUP.7         NO NEED TO CALCULATE
         LW        R7,*4W,X2       GET REL REC NO
         BCT       LE,RNERR        IF ZERO, RETURN
         STW       R7,RN           SAVE RECORD NUMBER
         SUI       R7,1            CALCULATE
         MPMW      R6,RANACCRL,X1  GET RECL-LN & MPMW TO GET POSITION
         DVMW      R6,BLKSIZE      PHYSICAL
         STW       R7,BSA          SECTOR NUM,
         STW       R6,SWN          REL WD WITH SECTOR
         SPACE     3
*
* GET OPTIONAL ERROR RETURN AND END ACTION ADDRESSES               X16
*
SETUP.7  EQU       $
         ADI       X2,5W           BUMP PARAMETER POINTER TO ERROR RET
         CAMW      X2,N.X          IS THERE AN ERROR RETURN?
         BGE       SETUP.8         NO, USE PREVIOUS
         LA        R7,*0,X2        GET ADDRESS
         STW       R7,FCB.ERRT,X1  PUT IN WAIT ERROR RETURN
         TBM       0,FCB.GCFG,X1   NO WAIT I/O
         BNS       SETUP.8         DO NOT SETUP NO WAIT RETURN
         STW       R7,FCB.NWER,X1  PUT IN NO-WAIT ERROR RETURN
SETUP.8  EQU       $
         ADI       X2,1W           BUMP PARAMETER POINTER TO NORMAL RET
         CAMW      X2,N.X          IS THERE A NORMAL RETURN?
         BGE       SETUP.9         NO, USE PREVIOUS
         LA        R7,*0,X2        GET ADDRESS
         STW       R7,FCB.NWOK,X1  PUT IN NO-WAIT END ACTION RETURN
SETUP.9  EQU       $
         TRSW      R0
         PAGE
*
*        DWRITE    ENTRY POINT
*
         BOUND     1W
DWRITE   EQU       $               WRITE ENTRY
         TRR       R0,X2           PUT LIST POINTER INTO X2
         ABR       R0,29           +1W FOR ARG CNT
         ADMW      R0,0W,X2        ADD # OF LIST BYTES
         STD       R0,N.X          SAVE RETURN ADDRESS
         BL        SETUP           SETUP WORD AREA
DWRITE.1 LW        R6,TC           GET WC
         BCT       LE,*N.X         EXIT IF NEG OR ZERO
         LW        R5,SWN          GET START WD NO
         BCF       ZR,DWRITE.2     BR IF NOT FIRST
         CAMW      R6,BLKSIZE      SEE IF OVER 192
         BCT       LT,DWRITE.2     BR IF ONLY PART OF SECTOR
         LW        R5,UBA          GET USER ADDR
         LW        R6,BLKSIZE      GET SECT BYTE COUNT
         STW       R5,FCB.ERWA,X1  PUT IN FCB
         STW       R6,FCB.EQTY,X1  PUT BYTE COUNT IN FCB(9)
         LW        R5,BSA          GET REL SECT NO
         STW       R5,FCB.ERAA,X1  PUT SECTOR # IN FCB(10)
         SVC       1,X'32'         WRITE THE WHOLE SECTOR
         BL        DWAIT           WAIT FOR I/O COMPLETE
         ABM       31,BSA          BUMP SECT ADDR
         LW        R5,UBA          GET USER ADDR
         ADMW      R5,BLKSIZE      UPDATE BY 192 WORDS
         STW       R5,UBA          RESTORE IT
         LW        R5,TC           GET TC
         SUMW      R5,BLKSIZE      REDUCE BY 192
         STW       R5,TC           UPDATE TRANSFER COUNT
         BU        DWRITE.1        GO AGAIN
DWRITE.2 LA        R5,P_BLOCK      PARTIAL SECT WRITE, GET WORK BUF ADDR
         STW       R5,FCB.ERWA,X1  STO IN FCB
         LW        R6,BLKSIZE      SECTOR SIZE
         STW       R6,FCB.EQTY,X1  PUT IT IN BYTE COUNT FCB(9)
         LW        R5,BSA          GET REL SECTNO
         STW       R5,FCB.ERAA,X1  PUT SECTOR # IN FCB(10)
         SVC       1,X'31'         READ SECTOR
         BL        DWAIT           WAIT FORI/O COMPLETE
         LNW       R5,BLKSIZE      SET MAX TRANSFER CNT
         ADMW      R5,SWN          ONLY REST OF BUFFER FOR TRANSFER
         LA        X3,P_BLOCK      GET WORK BUFFER ADDR
         ADMW      X3,SWN          POINT TO STARTING WORD
         LW        X2,UBA          GET USERT BUFFER ADDR
         LW        R4,TC           GET TC
         ZMW       SWN             RESET START WORD NO
         TBM       X.FLAG,FLAG     EXTENDED ADDRESSING?
         BNS       DWRITE.4        SKIP SET
         SEA
         NOP                       FORCE BOUNDING
DWRITE.4 EQU       $
         LB        R6,0B,X2        GET ONE BYTE
         STB       R6,0B,X3        PUT ONE BYTE
         SUI       R4,1            REDUCE TC
         STW       R4,TC           STORE IT
         TRR       R4,R4
         BCT       ZR,DWRITE.3     CONTINUE
         ABR       X3,31           BUMP ADDR
         ABR       X2,31           BUMP ADDR
         ABM       31,UBA          BUMP USER BUFFER POINTER
         BIB       R5,DWRITE.4     LOOP TIL DONE
DWRITE.3 EQU       $
         CEA
         LA        R5,P_BLOCK      GET WORK BUF ADDRESS
         STW       R5,FCB.ERWA,X1  PUT IN WORK BUF ADDRESS IN FCB(8)
         LW        R5,BSA          GET SA
         STW       R5,FCB.ERAA,X1  PUT SECTOR # IN FCB(10)
         ABM       31,BSA          BUMP SA
         SVC       1,X'32'         WRITE TO DISK UPDATE SECT
         BL        DWAIT           WAIT FOR I/O COMP
         BU        DWRITE.1        CONTINUE PROCESSING
         SPACE     3
*
DWAIT    EQU       $
         TBM       0,FCB.GCFG,X1   IS IT A NO_WAIT I/O ?
         BNS       $+2W            BYPASS I/O WAIT SVC
         SVC       1,X'3C'         I/O   WAIT SVC
         LW        X3,PBLKA        GET PBLK ADDRESS FOR ERROR REPORTING
         SPACE     3
CHKERR   EQU       $
         TBM       1,FCB.SFLG,X1   TEST FOR I03 ERROR BIT
         BCF       SET,NERROR      SKIP TO NERROR IF BIT NO SET
         TBM       6,FCB.SFLG,X1   EOF CHECK
         BS        EOFRTRN
         TBM       7,FCB.SFLG,X1   EOM CHECK
         BS        EOMRTRN
         LW        R6,FCB.SFLG,X1  GET ENTIRE STATUS WORD
         BU        RETURN
         PAGE
*
*        ERROR RETURNS
*
NERROR   EQU       $
         ZMW       3W,X3           SET  NO ERROR DATA
         TRSW      R0              PROCESS ADDITIONAL DATA
         SPACE     1
EOFRTRN  EQU       $
         LI        R6,EOFERR       LOAD EOF ERROR DATA
         BU        RETURN
         SPACE     1
EOMRTRN  EQU       $
         LI        R6,EOMERR       LOAD EOM ERROR DATA
         BU        RETURN
         SPACE     1
TCERR    EQU       $
         LI        R6,BCNTERR      LOAD INCORRECT BYTE CNT ERROR
         BU        RETURN
         SPACE     1
RNERR    EQU       $
         LI        R6,RECNERR      LOAD REC # ERROR DATA
         BU        RETURN
         SPACE     1
RELRTRN  EQU       $
         LI        R6,RECLERR      GET ERROR CODE & PUT IN R6
         LA        X3,*2W,X1       GET ADDRESS OF PBLK
*
RETURN   EQU       $
         STW       R6,PBK.SFLG,X3  PUT DATA IN PBLK(3)
         BU        *N.X            RETURN TO CALLING PROGRAM
*
         END
         PROGRAM   MSEC
         DEF       MSEC
*=    SUBROUTINE MSEC (TIME)
*          INTEGER   TIME         !time in milliseconds
*= Time in milliseconds since midnight
*
*        CALL MSEC(I)
*
*        I = INTEGER*4
*        I = TIME IN M-SEC
*
*
         M.EQUS
*
*
         BOUND     1W
MSEC     EQU       $
         LW        R5,C.BTIME      GET TIME IN 100 MICRO SECOND UNIT
         ZR        R4
         DVI       R4,10           CONVERT TO MILI SECOND
         STW       R5,0W,R1        STORE CURRENT VALUE OF TIME
         TRSW      R0              RETURN TO CALLING PROGRAM
*
*
         END
         PROGRAM   TLINE           0.0
         DEF       TLINE
*
*=       SUBROUTINE TLINE (S)
*             CHARACTER*(*) S      !STRING FROM TERMINAL LINE BUFFER
*
*= Extracts the current terminal line buffer
*
         M.EQUS
CR       EQU       X'0D'
NULL     EQU       0
BLANK    EQU       C' '
S        EQU       1W
SLEN     EQU       2W
*
* DATA
*
         BOUND     1W
RETURN   RES       1W
*
* TLINE
*
         BOUND     1W
TLINE    EQU       $
         TRR       R0,X1           INDEX ARGUMENTS
         ABR       R0,29
         ADMW      R0,0,X1         BUMP OVER ARGUEMENT COUNT
         STW       R0,RETURN       SAVE FOR RETURN
         SPACE     3
*
* LOOP AND COPY LINE BUF
*
         LA        X3,*S,X1        GET S ADDRESS
         LW        R5,*SLEN,X1     GET LENGTH OF S
         LW        X2,C.TSAD       TSA ADDRESS
         LW        X2,T.LINBUF,X2  LINE BUFFER ADDRESS
         BZ        TLINE.3         NO LINE BUFFER, DO NOT READ
         LB        R6,4W,X2        TSM BUFFER SIZE
         SLA       R6,2            CONVERT WORD TO BYTE COUNT
         CAR       R5,R6           WHICH IS GREATER FOR XFER LIMIT
         BLE       TLINE.1         TSM BUFFER IS SMALLER
         TRR       R5,R6           STRING TO XFER TO IS SMALLER
TLINE.1  EQU       $
         ADI       X2,5W           TSM LINE BUFFER ADDRESS
         TRN       R6,R6           NEGATIVE FOR LOOP
TLINE.2  EQU       $               TOP OF LOOP
         LB        R7,0,X2         GET FIRST BYTE
         CI        R7,CR           END OF INPUT?
         BEQ       TLINE.3
         CI        R7,NULL         GUARD AGAINST OVER RUN
         BEQ       TLINE.3
         STB       R7,0,X3         PUT IN STRING
         ADI       X2,1B           NEXT CHARACTER
         ADI       X3,1B           NEXT SLOT IN S
         SUI       R5,1B           DECREMENT S LENGTH LEFT
         BIB       R6,TLINE.2
TLINE.3  EQU       $
         SPACE     3
*
* NOW BLANK FILL IF NECESSARY
*
         TRN       R5,R5           TEST FOR ANY LEFT
         BNN       TLINE.5         FILLED UP
         LI        R7,BLANK
TLINE.4  EQU       $
         STB       R7,0,X3         BLANK FILL
         ADI       X3,1B           NEXT BYTE
         BIB       R5,TLINE.4      CONTINUE
TLINE.5  EQU       $
         BU        *RETURN         RETURN
         END
        PROGRAM M_UPRIV
        DEF         M_PRIV
*
*=    SUBROUTINE M_PRIV
*
*= converts the calling task to privileged.
* Note that the task must have been cataloged privileged for this
* to work.
*
*
        DEF        M_UPRIV
*=    SUBROUTINE M_UPRIV
*
*= converts the calling task to unprivileged.
*
* Privilege
* By: L. Tate
* On: May 17, 1983
* Purpose: Call these two routines to change from a privileged
*          state to an unprivileged.
*
* Inputs: none
* Outputs: none
*
* Notes: Must be cataloged privileged to call these routines.
******************************************************************
         M.EQUS                        !system equates
*
* M_PRIV
*
M_PRIV   EQU       $
         M.PRIV                        !ref. mpx 32 2.1 vol I: 8.2.36
         TRSW      R0                  !done and home
*
* M_UPRIV
*
M_UPRIV  EQU       $
         M.UPRIV                       !ref mpx 32 2.1 vol I: 8.2.54
         TRSW      R0                  !done and home
         END
         PROGRAM HIO         2.0
         DEF       HIO
*=      LOGICAL FUNCTION HIO (LFC)
*          INTEGER     LFC      logical file to halt io on
*          LOGICAL     HIO      success = T, failure = F
*
*= Halts the io over the specified lfc.
* This is a privileged instrucion and results will be unpredicable
* if you halt something other than a terminal.  Be careful.
* 1.0 LHT automatically attempts to make user privileged if unprivileged
* 2.0 LHT fault in determining if integer or not and error test
         M.EQUS
         M.TBLS
PARMAREA REZ       8W              parameter area for inquiry
LFCINQ   REZ       1D              local lfc as parameter
RETURN   REZ       1W              return address
SRL      SRL       R6,0            dummy shift right logical
SLLD     SLLD      R6,0            dummy shift left logical double
SLL      SLL       R6,0
         BOUND     1W
HIO      EQU       $
         STW       R0,RETURN       save return address
*
* lfc is either integer or character, determine which and handle
*
         LW        R7,0,X1        get LFC
         SRL       R7,24           isolate first byte
         TRR       R7,R7           test first byte
         BZ        HIO.INT        integer
*
* character in integer format
*
         LW        R6,0W,X1        get lfc
         SRL       R6,8            right justify lfc
         ZR        R7              clear 7
         BU        HIO.LFC         now set up inquiry
*
* integer version
*
HIO.INT  EQU       $
         LW        R5,0W,X1        get lfc
         SVC       1,X'2A'         convert to decimal
         LI        R5,-3           loop three times
         TRR       R7,R3           store in 3 for destructive test
         SLL       R7,8            left justify
         ZR        R4              zero counter
         ZBR       R0,0            reset flag
HIO.SHF  EQU       $
         ZR        R6
         SLLD      R6,8            get first byte
         CI        R6,X'30'        zero
         BNE       HIO.SH1         donot count
         TBR       R0,0            test for leading
         BS        HIO.SH2         no count
         ADI       R4,1            increment
         BU        HIO.SH2         skip
HIO.SH1  EQU       $
         SBR       R0,0            set non zero flag
HIO.SH2  EQU       $
         BIB       R5,HIO.SHF
         SLL       R4,3            *8
         TRR       R3,R6           retrieve lfc
         ADI       R4,8            8 bit shift plus
         LH        R1,SLL          going to strip leading zeros
         BL        SHIFTER
         LH        R1,SRL          right bound
         BL        SHIFTER
         SUI       R4,8            back to original count
         LW        R7,=C'    '     blank mask
         LH        R1,SLLD         get slld instruction
         BL        SHIFTER         shift
         ZR        R7
         BU        HIO.LFC         rejoin mainstream
HIO.LFC  EQU       $
         STD       R6,LFCINQ       set up inquiry
         M.INQUIRY PARMAREA,LFCINQ inquiry for udt table
         BS        ERROR           branch if inquire error
         LW        R1,2W+PARMAREA  udt address
         BZ        ERROR           not a device
         TBM       UDT.IOUT,UDT.FLGS,X1 test for outstanding io
         BNS       ERROR           no io to halt
         LW        R6,1W,X1        get logical address
         SLL       R6,8            strip status
         SRLD      R6,24           strip logical address
         SRL       R7,16           right justify logical address
         CI        R6,X'0C'        test for TY type
         BEQ       HIO.TY
         CI        R6,X'11'        test for u0
         BLT       ERROR
         CI        R6,X'1A'        test for u9
         BGT       ERROR
HIO.TY   EQU       $
         LW        R6,3W,X1        get physical address
         SRL       R6,16           right justified
         TRR       R6,R6           test for zero
         BZ        HIO.1           use logical address
         TRR       R6,R7           use physical address
HIO.1    EQU       $
         TBM       0,RETURN        test for priv
         BS        HIO.5
         M.PRIV                    make priv
HIO.5    EQU       $
         HIO       R7,0            halt io
         BCT       6,ERROR         error on cc3 or cc4
         BCT       2,ERROR         error on cc2 set
         LI        R7,-1           fortran true
         BU        HIO.10
ERROR    EQU       $
         ZR        R7              fortran false
         BU        HIO.10
HIO.10   EQU       $
         TBM       0,RETURN
         BS        HIO.15          leave in entrance state
         M.UPRIV
HIO.15   EQU       $
         BU        *RETURN         home
*
* SHIFTER merges N and instruction and perfroms shift
*
*   R1  - instruction
*   R4  - count
*   R1 is destroyed
*
SHIFTER EQU $
         ORR       R4,R1          or in count
         EXRR       R1              perform shift
         TRSW       R0              return
         END
         PROGRAM   TTYF                0.0
         DEF       TTYCURF
*=    LOGICAL FUNCTION TTYCURF (PBLK, SENSE)
*          INTEGER    PBLK(4)         !dio parameter block
*          INTEGER*8  SENSE           !returns the result of sense test
*
*= TTYCUR tests the port for current configuration.
*
         DEF       TTYINIF
*=    SUBROUTINE TTYINIF (PBLK, INIT)
*          INTEGER    PBLK(4)         dio parameter block
*          INTEGER    INIT            initialization word
*
*= Inits the port to the specified initialization.
*
* TTYCURR returns the current initialization of a terminal on an
* asynchronus eight line.  This version is compatable with with the
* magical FCBINIT/DPREAD/DPWRITE/DREAD/DWRITE routines.  Since the
* address of the fcb is the first word of the parameter block, just
* specify the parameter block as the first parameter.
*   EX:
*         CALL TTYCURF(PBLK, SENSE)
*   OR:
*         CALL TTYINIF(PBLK, INIT)
* major problem with previous version was the internal open involved.
*
* definitions
*
         M.EQUS
ARGS     EQU       0               offset to find argument count
FCB      EQU       1W              offset to find lfc
SENSE    EQU       2W              offset to place initialization
INIT     EQU       2W              initialization command
ERROR    EQU       1               bit 1 of word 3 is error flag
*
* local variables
*
         BOUND     1D
OLDCOM   DATAW     1W
FCBADDR  DATAW     0
RETURN   DATAW     0
C.SENSE  DATAW     X'02000000'     expanded format
C.SPCHR  DATAW     X'02000000'     expanded format
C.INIT   DATAW     X'22400000'     expanded format
WORDMASK DATAW     X'0007FFFC'     ensure word address
         BOUND     1W
INITPARM EQU       $
ACE      DATAB     0,0,0           ace parameters to use
SPECHAR  DATAB     0               special character
INITBUF  DATAW     0
SPCHRBUF DATAW     0
SPCHRAD  ACW       SPCHRBUF        byte address of special character
ACEADDR  ACW       INITBUF         byte address of ace parameters
ENTRY    DATAW     0
*
* ttycurr
*
TTYCURF  EQU       $
         LA        R7,TTY.10       sense program
         STW       R7,ENTRY        set up future
         BU        TTY.5           set up return
*
* ttyinit
*
TTYINIF  EQU       $
         LA        R7,TTY.20
         STW       R7,ENTRY        save for future
         BU        TTY.5
*
* set up return
*
TTY.5    EQU       $
         TRR       R0,R1           save arguement pointer
         ABR       R0,29           bump over arguement counter
         ADMW      R0,ARGS,X1      add number of arguements
         STW       R0,RETURN       save returen address
         BU        *ENTRY          perform task
*
* set up fcb and open
*
         BOUND     1W
TTY.10   EQU       $
         LW        R4,WORDMASK     address mask
         LW        R2,*FCB,X1      get lfc
         LW        R7,2W,X2        save old command
         STW       R7,OLDCOM
         LA        R7,*SENSE,X1
         STMW      R7,8W,X2        use SENSE for buffer
         LW        R7,C.SENSE      place commands in fcb
         STW       R7,2W,X2
         LI        R7,8B           byte count for sense
         STW       R7,9W,X2
         STW       R2,FCBADDR      save fcb address
*
* sense terminal
*
         TRR       R2,R1           set up sense
         SVC       1,X'37'         stat
         LW        R2,FCBADDR      retrieve fcb address
         LW        R7,OLDCOM       retrieve
         STW       R7,2W,X2
         TBM       ERROR,3W,X2     check error bit
         BS        TTY.19          error
*
* return true
*
         LI        R7,-1           return true
         BU        *RETURN
*
* error
*
TTY.19   EQU       $
         ZR        R7
         BU        *RETURN
*
* initialize terminal
*
         BOUND     1W
TTY.20   EQU       $
         LW        R7,*INIT,X1     initialize to perform
         STW       R7,INITPARM     isolate for commands
         STW       R7,INITBUF
         LB        R7,SPECHAR      special character
         STB       R7,SPCHRBUF
*
* open
*
         LW        R2,*FCB,X1      get fcb address
         LW        R7,2W,X2        get old command
         STW       R7,OLDCOM
*
* initialize ace parameters
*
         LW        R7,C.INIT       init ace command
         STW       R7,2W,X2
         LW        R7,ACEADDR      address of ace
         STW       R7,8W,X2        command buffer
         LI        R7,3B           transfer 3 bytes
         STW       R7,9W,X2        byte count
         STW       R2,FCBADDR      save address
         TRR       R2,R1           set up write
         SVC       1,X'32'
         LW        R2,FCBADDR      retrieve fcb address
         TBM       ERROR,3W,X2     error bit
         BS        TTY.29          error return
*
* special character
*
         LW        R7,C.SPCHR      special character command
         STW       R7,2W,X2        new command
         LW        R7,SPCHRAD      special character address
         STW       R7,8W,X2
         LI        R7,1B           transfer 1 byte
         STW       R7,9W,X2
         TRR       R2,R1           set up special char init
         SVC       1,X'0D'         set special char
         LW        R2,FCBADDR      retrieve fcb address
         TBM       ERROR,3W,X2     test for error
         BS        TTY.29          error return
*
* return good news
*
         LW        R7,OLDCOM
         STW       R7,2W,X2        replace
         LI        R7,-1           fortran true
         BU        *RETURN
*
* error address
*
TTY.29   EQU       $
         LW        R7,OLDCOM
         STW       R7,2W,X2        replace
         ZR        R7              fortran false
         BU        *RETURN
         END
         PROGRAM   L.UDT               1.1
         DEF       SUDT
*=    SUBROUTINE SUDT(PBLK, MODE)
*         INTEGER    PBLK         dio parameter block attached to ty
*         CHARACTER*4 MODE        mode to set
*
*= Sets the terminal to the specified operating mode.
         DEF       TUDT
*
*=    LOGICAL FUNCTION TUDT(PBLK, MODE)
*
*        INTEGER*4  PBLK(4)     !dio parameter block attached to ty
*        CHARACTER*4 MODE       !mode to test or set
*
*  Result is returned as a logical function
*
*= Tests for a particular mode.
*
         M.EQUS
         M.TBLS
*
* data
*
         BOUND     1D
LFCB     RES       8W                 LOCAL FCB FOR SVC'S
RETURN   RES       1W
UDTA     RES       1W                  ADDRESS OF TERMINAL
LMODE    RES       1W                  LOCAL MODE FOR COMPARE
FLAGS    RES       1W
TEST     EQU       0                   FIRST BIT IS TEST MODE FLAG
MODES    DATAW     C'ONLI'
         DATAW     C'TSM '
         DATAW     C'LOGO'             USER LOGGED ON
         DATAW     C'FULL'
         DATAW     C'HALF'
         DATAW     C'ECHO'
         DATAW     C'NOEC'             NO ECHO
         DATAW     C'DEAD'
         DATAW     C'USE '             IN USE
         DATAW     C'ALIV'             ALIVE
         DATAW     C'DUAL'             DUAL CHANNEL MODE
         DATAW     C'SING'             SINGLE CHANNEL MODE
NMODES   EQU       $-MODES
TESTBITS EQU       $
         TBM       UDT.ONLI,UDT.STAT,X3  TEST FOR ONLINE
         TBM       UDT.TSM,UDT.STAT,X3   TEST FOR TSM
         TBM       UDT.LOGO,UDT.FLGS,X3  TEST FOR LOGON
         TBM       UDT.FDUX,UDT.BIT2,X3  FULL DUPLEX
         TBM       UDT.FDUX,UDT.BIT2,X3  HALF DUPLEX
         TBM       UDT.ECHO,UDT.BIT2,X3  ECHO
         TBM       UDT.ECHO,UDT.BIT2,X3  NO ECHO
         TBM       UDT.DEAD,UDT.BIT2,X3  DEAD
         TBM       UDT.USE,UDT.BIT2,X3   IN USE
         NOP                           DUAL
         NOP
         NOP                           SINGLE
         NOP
SETBITS  EQU       $
         TBM       UDT.ONLI,UDT.STAT,X3  TEST FOR ONLINE
         TBM       UDT.TSM,UDT.STAT,X3   TEST FOR TSM
         TBM       UDT.LOGO,UDT.FLGS,X3  TEST FOR LOGON
         SBM       UDT.FDUX,UDT.BIT2,X3  FULL DUPLEX
         ZBM       UDT.FDUX,UDT.BIT2,X3  HALF DUPLEX
         SBM       UDT.ECHO,UDT.BIT2,X3  ECHO
         ZBM       UDT.ECHO,UDT.BIT2,X3  NO ECHO
         SBM       UDT.DEAD,UDT.BIT2,X3  DEAD
         TBM       UDT.USE,UDT.BIT2,X3   IN USE
         ZBM       UDT.DEAD,UDT.BIT2,X3  ALIVE
         SVC       1,X'27'             DUAL
         SVC       1,X'26'             SINGLE
MODTEST  EQU       $                   MODIFY THE RESULT OF TEST
         DATAB     0                   ONLINE
         DATAB     0                   TSM
         DATAB     0                   LOGON
         DATAB     0                   FULL
         DATAB     255                 NOT FULL
         DATAB     0                   ECHO
         DATAB     255                 NOT ECHO
         DATAB     0                   DEAD
         DATAB     0                   IN USE
         DATAB     0                   NOT ALIVE
         DATAB     0                   DUAL
         DATAB     0                   SINGLE
*
SUDT     EQU       $
         ZBM       TEST,FLAGS          SHOW ENTRANCE
         BU        UDT.1
TUDT     EQU       $
         SBM       TEST,FLAGS          SHOW ENTRANCE
         BU        UDT.1
UDT.1    EQU       $                   COMMON CODE
         TRR       R0,X1               INDEX REGISTER
         ABR       R0,29               BUMP OVER COUNT
         ADMW      R0,0,X1             ADD COUNT
         STW       R0,RETURN           RETURN ADDRESS
         LW        X2,*1W,X1           GET FCB ADDRESS
         BZ        FALSE               NO FCB ADDRESS
         LW        R7,0,X2             GET LFC
         LW        X2,C.TSAD           START OF TSA
         LW        X3,T.FPTA,X2        FILE POINT TABLE ADDRESS
         LNB       R5,T.FILES,X2       NUMBER OF FPT'S
         LW        R4,=X'00FFFFFF'     LFC MASK
UDT.2    EQU       $
         CMMW      R7,0,X3             IS THIS THE LFC
         BEQ       UDT.3
         ADI       X3,3W               BUMP FPT POINTER
         BIB       R5,UDT.2            LOOP
         BU        FALSE               NOT HERE
UDT.3    EQU       $                   FOUND
         TBM       4,4B,X3             ENTRY IN USE?
         BS        FALSE               NO
         LW        X3,2W,X3            FAT ADDRESS
         LH        X3,3H,X3            UDT INDEX
         BZ        FALSE               NO UDT INDEX
         SLA       X3,6                * WORD SIZE * UDT SIZE
         ADMW      X3,C.UDTA           MAKE A UDT ADDRESS
         LB        R7,UDT.DTC,X3       GET TYPE
         CI        R7,X'C'             MUST BE TY TYPE
         BNE       FALSE               NOT GOOD
         STW       X3,UDTA             STORE IN UDT ADDRESS
*
* NOW DETERMINE WHICH FLAG I WANT TO SET
*
         LNW       R5,*3W,X1           GET STRING SIZE
         LI        R4,-4               SIZE OF LMODE
         LA        X2,*2W,X1           MODE STRING POINTER
         LA        X3,LMODE            LOCAL COPY OF MODE
         LW        R7,=C'    '         BLANK OUT LOCAL COPY
         STW       R7,LMODE
UDT.4    EQU       $
         LB        R7,0,X2             GET FIRST BYTE
         STB       R7,0,X3             PUT AWAY
         ABR       X2,31               BUMP POINTERS
         ABR       X3,31               BUMP POINTERS
         ADI       R4,1                INCREMENT LOCAL COUNTER
         BZ        UDT.5               ENOUGH
         BIB       R5,UDT.4            MORE TO COME
UDT.5    EQU       $
         LI        R4,-NMODES          GET NUMBER OF MODES
         LW        R7,LMODE            GET MODE SELECTED
         ZR        X2                  OFFSET OF FIRST MODE
UDT.6    EQU       $
         CAMW      R7,MODES,X2         IS THIS THE MODE
         BEQ       UDT.7               FOUND
         ADI       X2,1W               BUMP INDEX
         BIW       R4,UDT.6            CONTINUE SEARCH
         BU        FALSE               NOT FOUND IN LIST
UDT.7    EQU       $                   FOUND
*
* LETS DO IT!
*
         ZMD       LFCB               MUST ZERO LOCAL FCB
         ZMD       LFCB+2W
         ZMD       LFCB+4W
         ZMD       LFCB+6W
         LW        X1,*1W,X1           GET FCB ADDRESS
         LW        R7,0,X1             GET LFC
         STW       R7,LFCB             STORE LOCALY
         LA        X1,LFCB             USE LOCAL FCB
         LW        X3,UDTA             RETREIVE UDT ADDRESS
         TBM       TEST,FLAGS          TEST ONLY?
         BS        UDT.TST
         TBR       R0,0                ARE WE PRIVILEGED?
         BS        UDT.8               YEP
         M.PRIV
UDT.8    EQU       $
         LW        R7,SETBITS,X2       GET COMMAND
         EXR       R7                  DO IT
         TBR       R0,0                WHERE WE PRIVILEGED
         BS        UDT.9               YEP
         M.UPRIV                       EXIT WAY CAME
UDT.9    EQU       $
         LI        R7,-1
         BU        *RETURN             GO HOME
*
* TEST LOGIC
*
UDT.TST  EQU       $
         ZR        R7                  ASSUME FALSE
         LW        R6,TESTBITS,X2      GET TEST INSTRUCTION
         EXR       R6                  TEST BIT
         BNS       UDT.10              NOT SET
         LI        R7,255              SET
UDT.10   EQU       $
         SRA       X2,2                BYTE BOUND INDEX
         EOMB      R7,MODTEST,X2       SOME ARE NOT'S
         BU        *RETURN             HOME
*
* ERROR RETURN
*
FALSE    EQU       $
         ZR        R7
         BU        *RETURN             HOME
         END
         PROGRAM   INKEY           0.0
         DEF       INKEY
*=    LOGICAL FUNCTION INKEY(LFC, FCB, CHR)
*          INTEGER    LFC          lfc to read from
*          INTEGER    FCB(9)       fcb to use (zero'd initially)
*          INTEGER*1,*2,*4 CHR     character read in nowait form
*
*          returns .true. if character input
*
*= Returns a single character typed to lfc.  User must echo.
*
         M.EQUS
         M.TBLS
LFC      EQU       1W
FCB      EQU       2W
CHR      EQU       3W
*
* inkey
*        R0        return
*        X1        fcb address
*        X2        arguement list pointer
*        R4        mask to extract leading byte
*        R5        numeric lfc
*        R7        alpha lfc and transient register
*
         BOUND     1W
INKEY    EQU       $
         TRR       R0,X2           arg pointer
         ABR       R0,29           bump over arg count
         ADMW      R0,0W,X2        bump over args
*
* check for initialization
*
         LA        X1,*FCB,X2      get fcb address
         LW        R7,FCB.LFC,X1   get first word of fcb
         BNZ       INKEY.10        already initialized
*
* initialize
*
         LW        R7,*LFC,X2      get lfc
         LW        R4,=X'FF000000' lfc mask
         TRRM      R7,R5           test for numeric or alpha
         BNZ       INKEY.5         alpha
         TRR       R7,R5           set up conversion
         SVC       1,X'2A'         convert binary to decimal
         CI        R5,100          less than 100?
         BGE       INKEY.2         no shift since uses 3 digits
         SLC       R7,8            move leading blank to end
         CI        R5,10           only one byte long?
         BGE       INKEY.2         no
         SLC       R7,8            move leading blank to end
INKEY.2  EQU       $
         SLL       R7,8            make like alpha
INKEY.5  EQU       $
         SRL       R7,8            right justify 3 chr lfc
         STW       R7,FCB.LFC,X1   store lfc in fcb
         LW        R7,=X'E0600000' nowait,noerror,dfi,noecho,noconv
         STW       R7,FCB.GCFG,X1  store in control flags
         TRR       X1,R7           fcb address
         ADI       R7,8W           buffer to use is end of fcb
         SBR       R7,12           make byte address
         SBR       R7,11           count of one
         STW       R7,FCB.TCW,X1   store tcw
*
* do normal processing
*
INKEY.10 EQU       $
         TBM       0,FCB.SFLG,X1   test for io completion
         BS        INKEY.20        still processing
         LB        R7,8W,X1        get character received
         STW       R7,*CHR,X2      return character input
         LNW       R7,FCB.RECL,X1  transfer count of -1 is T, 0 is F
         SVC       1,X'31'         read
         BU        INKEY.30        read processing done
INKEY.20 EQU       $               read not complete
         ZMW       *CHR,X2         zero out character input
         LI        R7,0            false
INKEY.30 EQU       $               exit
         TRSW      R0              return
         END
         PROGRAM   HIOALL          0.0
         DEF       HIOALL
*=    SUBROUTINE HIOALL
*
*= Kills all pending io for this task.
*  Must be privileged to do this
*
         M.EQUS
*
         BOUND     1W
HIOALL   EQU       $
         TBR       R0,0            privileged?
         BS        ALL.1           yes
         M.PRIV
ALL.1    EQU       $
         M.CALL    H.IOCS,38       do it
         TBR       R0,0            privileged?
         BS        ALL.2           yes
         M.PRIV
ALL.2    EQU       $
         TRSW      R0              return
         END
