.TITLE VDV - VIRTUAL DEVICE FRONT END .IDENT /V01.04/ ; ; COPYRIGHT (C) 1979,1980 BY ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS. ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ON A ; SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY 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 EXCEPT FOR USE ON SUCH ; SYSTEM AND TO ONE WHO AGREES TO THESE LICENSE TERMS. TITLE ; TO AND OWNERSHIP OF THE SOFTWARE SHALL AT ALL TIMES REMAIN ; IN DEC. ; ; THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO CHANGE WITHOUT ; NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL ; EQUIPMENT CORPORATION. ; ; DEC ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ; ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DEC. ; ; ; MODULE DESCRIPTION ; ; VIRTUAL DEVICE FRONT END ; ; DISTRIBUTED SYSTEMS SOFTWARE ENGINEERING ; ; IDENT HISTORY: ; ; 1.00 30-JAN-79 ; J. A. SCHRIESHEIM ; ; 1.01 5-JUN-80 J. A. SCHRIESHEIM ; SEPARATED INTO READ-ONLY AND READ-WRITE PSECTS ; ; 1.02 30-AUG-80 J. A. SCHRIESHEM ; ADDED I/O KILL SUPPORT ; ; 1.03 2-SEP-80 J. A. SCHRIESHEIM ; ADDED MAG-TAPE SPECIFIC FUNCTIONS ; ; 1.04 4-MAY-81 J. A. SCHRIESHEIM ; ADDED EXTRA WORD TO PEM FOR IAS SUPPORT ; .SBTTL MACRO CALLS AND LOCAL DEFINITIONS ; ; MACRO LIBRARY CALLS ; .MCALL EXIT$S,DIR$,ASTX$S,ALUN$S,CLEF$,GTSK$S .MCALL SETF$,QIOW$,CALLR,USTP$S,PEMW$,WSIG$S,SREA$ .MCALL OPNW$,CONW$,CONB$$,DSCW$,CLSW$,REC$,SND$,XMIW$ .MCALL SNDW$,RECW$,GNDW$,REJW$,CON$,SPAW$,NETDF$ .MCALL HDRDF$,LCBDF$ NETDF$ ; DEFINE NETWORK SYMBOLS HDRDF$ ; DEFINE TASK HEADER OFFSETS LCBDF$ ; DEFINE LOGICAL NAME BLOCK OFFSETS ; ; LOCAL MACROS ; .MACRO XDIR$ DPB ; EXECUTE A DIRECTIVE MOV DPB,-(SP) CALL .XDIR .ENDM XDIR$ .MACRO CODE$ ; GENERATE CODE PSECT .PSECT CODE$ I,RO .ENDM CODE$ .MACRO DATA$ P1 ; GENERATE DATA PSECTS .IF IDN .PSECT DATA$P D,RO .IFF .PSECT DATA$I D,RW .ENDC .ENDM DATA$ .MACRO FUNC$ FUNCTN,ROUTIN ; GENERATE I/O FUNCTION DISPATCH ENTRY .WORD FUNCTN/256. .WORD ROUTIN .ENDM FUNC$ ; ; LUN AND EVENT FLAG DEFINITIONS ; .TTLUN=1 ; TERMINAL LUN .MBXLU=2 ; MAILBOX LUN .LLLUN=3 ; LOGICAL LINK LUN .EXEFN=1 ; TASK EXIT EVENT FLAG .TTEFN=2 ; TERMINAL EVENT FLAG .NTEFN=3 ; NETWORK I/O EVENT FLAG .SDEFN=4 ; SNDW$ EVENT FLAG .RCEFN=5 ; RECW$ EVENT FLAG .SBTTL MESSAGE FORMAT DEFINITIONS ; ; CONFIGURATION MESSAGE ; .ASECT .=0 TY.CON=0 ; CONFIGURATION MESSAGE TYPE C.TYPE: .BLKB 1 ; TYPE FIELD ( = TY.CON ) C.OST: .BLKB 1 ; OPERATING SYSTEM TYPE C.BUFL: .BLKB 2 ; MAXIMUM BUFFER LENGTH C.VER: .BLKB 2 ; VERSION NUMBER C.LGTH: ; LENGTH ; ; REQUEST MESSAGE ; .=0 TY.REQ=2 ; REQUEST MESSAGE TYPE R.TYPE: .BLKB 1 ; TYPE FIELD ( = TY.REQ) R.FLAG: .BLKB 1 ; REQUEST FLAGS R.FUNC: .BLKW 1 ; REQUESTED FUNCTION R.PARM: .BLKW 6 ; PARAMETERS R.SEQN: .BLKW 1 ; REQUEST SEQUENCE NUMBER RF.NST=1 ; NO STATUS MESSAGE REQUESTED FLAG RF.LAB=2 ; REQUEST IS ON A LABELED MAG-TAPE R.LGTH: ; LENGTH ; ; STATUS MESSAGE ; .=0 TY.STA=4 ; STATUS MESSAGE TYPE S.TYPE: .BLKB 1 ; TYPE FIELD ( = TY.STA) .BLKB 1 ; UNUSED S.STAT: .BLKB 2 ; STATUS S.LEN: .BLKB 2 ; LENGTH OF I/O TRANSFERRED S.LGTH: ; LENGTH ; ; I/O KILL INTERRUPT MESSAGE ; .=0 TY.KIL=5 ; I/O KILL MESSAGE TYPE K.TYPE: .BLKB 1 ; TYPE FIELD ( = TY.KIL) .BLKB 1 ; UNUSED K.SEQN: .BLKW 1 ; SEQUENCE OF REQUEST TO KILL K.LGTH: ; LENGTH ; ; PEM CONNECT MESSAGE ; .=0 P.NAME: .BLKW 2 ; ISSUING TASK'S NAME IN RAD50 P.TI: .BLKW 1 ; ISSUING TASK'T TI: IDENTIFIER P.FUNC: .BLKW 1 ; FUNCTION (IO.ATT) P.USER: .BLKW 1 ; USER'S TI: UCB ADDRESS P.OWNR: .BLKW 1 ; OWNER OF DEVICE (UCB ADDRESS OR 0) P.NODE: .BLKB 6 ; TARGET NODE NAME P.FILE: .BLKW 1 ; TARGET DEVICE OR FILE NAME LENGTH .BLKB 40. ; ... AND NAME P.LOGN: .BLKW 2 ; LOGICAL DEVICE NAME TO BE ASSIGNED P.ACC: .BLKB 2+16.+2+8.+2+16. ; ACCESS CONTROL INFO P.LGTH: ; LENGTH OF MESSAGE .PSECT .SBTTL BUFFERS AND IMPURE STORAGE ; ; BUFFERS ; DATA$ IMPURE ; INPURE DATA RCVSIZ=20. ; SIZE OF RECEIVE BUFFER RCVBUF: .BLKB RCVSIZ ; RECEIVE BUFFER GNDSIZ=P.LGTH ; SIZE OF GND BUFFER (ENOUGH FOR PEM) GNDBUF: .BLKB GNDSIZ ; GND BUFFER ; ; STATUS BLOCKS ; TTSTAT: .BLKW 2 ; TERMINAL I/O STATUS NSSTAT: .BLKW 2 ; NETWORK I/O STATUS SNDSTT: .BLKW 2 ; SEND STATUS RCVSTT: .BLKW 2 ; RECEIVE STATUS GNDSTT: .BLKW 2 ; GET NETWORK DATA STATUS ; ; MISC. STORAGE ; CURIOP: .WORD 0 ; CURRENT I/O PACKET ADDRESS KILFLG: .WORD 0 ; CURRENT REQUEST IS BEING KILLED FILE: .BLKB 40. ; NAME OF REMOTE DEVICE/FILE FILEL: .BLKW 1 ; LENGTH OF FILENAME STRING MAXBUF: .BLKW 1 ; REMOTE SERVER MAXIMUM BUFFER SIZE MAX64: .BLKW 1 ; MAX BUFFER SIZE IN 64 BYTE BLOCKS CURAPR: .BLKW 1 ; APR BIAS OF USER BUFFER CURLEN: .BLKW 1 ; LENGTH OF REMAINING DATA TO BE XFERRED TEXT: .WORD 0 ; TEXT STRING POINTER USER: .WORD 0 ; USER'S TI: UCB ADDRESS OWNER: .BLKW 1 ; OWNER OF VIRTUAL DEVICE LOGNAM: .BLKW 2 ; LOGICAL NAME TO BE ASSIGNED VDUCB: .WORD 0 ; UCB ADDRESS OF OUR VD: DEVTYP: .WORD 0 ; REMOTE DEVICE TYPE .SBTTL NETWORK DIRECTIVE DPB'S ; ; NETWORK DPB'S ; DATA$ IMPURE OPN: OPNW$ .MBXLU,.NTEFN,NSSTAT,,<1> CON: CONW$ .LLLUN,.NTEFN,NSSTAT,, REC: REC$ .LLLUN,,RCVSTT DSC: DSCW$ .LLLUN,.NTEFN CLS: CLSW$ .MBXLU,.NTEFN GND: GNDW$ .MBXLU,.NTEFN,GNDSTT,, PEM: PEMW$ .MBXLU,.NTEFN,,, REJ: REJW$ .MBXLU,.NTEFN,,, SPA: SPAW$ .MBXLU,.NTEFN,,, SND: SND$ .LLLUN,,SNDSTT SNDW: SNDW$ .LLLUN,.SDEFN,SNDSTT RECW: RECW$ .LLLUN,.RCEFN,RCVSTT RECMSG: RECW$ .LLLUN,.RCEFN,RCVSTT,, XMIKIL: XMIW$ .LLLUN,.NTEFN,,, ; ; CONNECT BLOCK ; CONB: CONB$$ ,NO.VDV ; ; CONFIGURATION MESSAGE ; CONMSG: .BYTE TY.CON ; CONFIGURATION MESSAGE OSTYPE: .BYTE 1 ; OS TYPE (DEFAULT = RSX-11M) .BYTE 0,0 ; DYNAMIC BUFFERING .BYTE 1,1 ; VERSION 1.1 CONSIZ=.-CONMSG ; ; REQUEST MESSAGE ; REQMSG: .BYTE TY.REQ ; REQUEST MESSAGE RFLAGS: .BLKB 1 ; REQUEST FLAGS FUNC: .BLKW 1 ; FUNCTION PARAM: .BLKW 6 ; PARAMETERS CURSEQ: .WORD 0 ; CURRENT REQUEST SEQUENCE NUMBER REQSIZ=.-REQMSG ; ; STATUS RETURN PEM ; PEMMSG: .WORD 0,0 ; INITIATING TASK NAME .WORD 0 ; ... AND TI: IDENTIFIER EXSTAT: .WORD EX$ERR ; EXIT STATUS (ASSUME ERROR) PEMSIZ=.-PEMMSG ; ; KILL I/O MESSAGE ; KILMSG: .BYTE TY.KIL ; I/O KILL MESSAGE .BYTE 0 ; UNUSED KILSEQ: .BLKW 1 ; REQUEST SEQUENCE NUMBER TO KILL KILSIZ=.-KILMSG .SBTTL RSX DIRECTIVE DPB'S ; ; RSX DPB'S ; DATA$ IMPURE CLEF: CLEF$ .EXEFN ; CLEAR EXIT FLAG SETF: SETF$ .EXEFN ; SET EXIT FLAG TIQIO: QIOW$ IO.WBT,.TTLUN,.TTEFN,,,,<,,40> ; TI MESSAGE OUTPUT SREA: SREA$ ABOAST ; TASK ABORT REQUEST AST .SBTTL MESSAGES STRINGS ; ; TEXT STRINGS ; .ENABL LC .NLIST BEX DATA$ PURE NSERR: .ASCIZ <15>/VDV -- Network not loaded/ OPNERR: .ASCIZ <15>/VDV -- Unable to open network/ CONERR: .ASCIZ <15>/VDV -- Unable to connect to remote server/ PROERR: .ASCIZ <15>/VDV -- Server synchronization error/ ABTERR: .ASCIZ <15>/VDV -- Link to server aborted/ ABOERR: .ASCIZ <15>/VDV -- Task aborted by directive or MCR request/ ASNERR: .ASCIZ <15>/VDV -- *Warning* -- Unable to assign logical name/ .EVEN DATA$ IMPURE ATTMSG: .ASCII <15>/VDV -- Connected through / ATTBUF: .BLKB 7 DETMSG: .ASCII <15>/VDV -- Disconnected from / DETBUF: .BLKB 7 NVDERR: .ASCII <15>/VDV -- Unable to allocate a virtual device of type "/ NVDBUF: .ASCIZ /??:"/ DEVERR: .ASCII <15>/VDV -- Unable to access remote device or file (/ DEVBUF: .BLKB 6 .EVEN .LIST BEX .SBTTL VDV MAIN LINE CODE ;+ ; **-VDV-VIRTUAL DEVICE MAIN LINE CODE ; ; VDV IS INITIATED BY A USER REQUEST PEM. THE REQUEST BLOCK CONTAINS ; A TARGET NODE NAME AND DEVICE/FILE SPECIFICATION. THE REMOTE DEVICE/FILE ; IS ACCESSED, AND THE USER IS ALLOCATED A PSEUDO DEVICE OF THE PROPER ; TYPE AS A CHANNEL TO DIRECT I/O TO THE REMOTE DEVICE. ALL I/O PACKETS ; ARE PROCESSED UNTIL THE EXIT FLAG IS SET, THEN THE DEVICE IS DEALLOCATED, ; MARKED AS OFFLINE, AND THE TASK EXITS. ; ;- CODE$ VDV:: ; ; INITIALIZE AND CONNECT ; CALL OPEN ; OPEN THE NETWORK, AND PERFORM PREAMBLE BCS EXIT ; IF CS, FATAL ERROR - EXIT DIR$ #SREA ; SPECIFY EXIT REQUEST AST CALL GETVD ; ALLOCATE A VD: UNIT BCS EXIT ; IF CS, COULDN'T - TELL USER AND EXIT CALL ASNLOG ; ASSIGN A LOGICAL NAME IF REQUESTED CALL EMIT ; EMIT THE STATUS TO INITIATOR DIR$ #CLEF ; CLEAR THE EXIT INDICATOR ; ; PROCESS AN I/O PACKET ; 10$: CALL GETIOP ; TRY TO GET AN I/O PACKET BCS EXIT ; IF CS, EXIT TASK CALL PRIOP ; PROCESS THE I/O BCS EXIT ; IF CS, FATAL ERROR BR 10$ ; ELSE, TRY TO GET MORE WORK .SBTTL ABOAST - ABORT REQUESTED AST ;+ ; **-ABOAST-ABORT REQUESTED AST ; ; THIS ROUTINE SETS THE EXIT FLAG, AND UNSTOPS THE TASK. ; ;- ABOAST: MOV #ABOERR,TEXT ; SET ERROR MESSAGE TEXT CALL ABORT ; SET THE EXIT FLAG AND UNSTOP THE TASK ASTX$S .SBTTL EXIT - CLEAN UP AND EXIT ;+ ; **-EXIT-EXIT VDV PROCESSING ;- EXIT: CALL EMIT ; EMIT STATUS TO INITIATOR IF NECESSARY XDIR$ #DSC ; DISCONNECT THE LINK (IF THERE IS ONE) XDIR$ #CLS ; CLOSE OUR MAILBOX (IF OPEN) MOV TEXT,R0 ; GET TEXT STRING TO PRINT BEQ 20$ ; IF EQ, NOTHING TO PRINT CALL PRINT ; ELSE, PRINT IT 20$: TST VDUCB ; DID WE ALLOCATE A VD: ? BEQ 40$ ; IF EQ, NO - NO NEED TO PRINT MESSAGE MOV #ATTBUF,R0 ; ELSE, POINT TO START OF FORMATTED NAME MOV #DETBUF,R1 ; POINT TO BUFFER IN DETACH MESSAGE 30$: MOVB (R0)+,(R1)+ ; COPY DEVICE NAME BNE 30$ ; ... MOV #DETMSG,R0 ; POINT TO MESSAGE CALL PRINT ; TELL USER ABOUT IT CLR VDUCB ; INDICATE NO UNIT ALLOCATED 40$: CLR USER ; CLEAR USER'S TI: UCB ADDRESS EXIT$S ; BYE-BYE ! .SBTTL EMIT - EMIT REQUEST STATUS TO INITIATOR ;+ ; **-EMIT-EMIT REQUEST STATUS TO INITIATOR ;- EMIT: TST PEMMSG ; DO WE KNOW WHO TO SEND STATUS TO ? BEQ 10$ ; IF EQ, NO (OR WE'VE DONE IT ALREADY) XDIR$ #PEM ; ELSE, SEND STATUS PEM CLR PEMMSG ; MAKE SURE WE DON'T DO IT AGAIN 10$: RETURN .SBTTL PRINT - PRINT AN ASCIZ STRING ;+ ; **-PRINT-PRINT AN ASCIZ STRING ON TI: ; ; INPUTS: ; R0 = ADDRESS OF ASCIZ STRING ; ; OUTPUTS: ; STRING PRINTED ; R0 IS MODIFIED ;- PRINT: MOV R0,TIQIO+Q.IOPL ; SET STRING ADDRESS 10$: TSTB (R0)+ ; LOOK FOR END OF STRING BNE 10$ ; ... SUB TIQIO+Q.IOPL,R0 ; CALC STRING LENGTH MOV R0,TIQIO+Q.IOPL+2 ; SET STRING LENGTH XDIR$ #TIQIO ; PRINT IT OUT RETURN .SBTTL .XDIR - EXECUTE A DIRECTIVE ;+ ; **-.XDIR-EXECUTE A DIRECTIVE ; ; THIS ROUTINE EXECUTES A DIRECTIVE. IF THE DIRECTIVE FAILS ; DUE TO LACK IF RESOURCES, THE DIRECTIVE WILL BE RE-EXECUTED ; AFTER A SIGNIFICANT EVENT. ; ; INPUTS: ; 2(SP) = ADDRESS OF DPB ; ; OUTPUTS: ; DPB ADDRESS REMOVED FROM STACK ;- .XDIR: 10$: MOV 2(SP),-(SP) ; PUSH DPB ADDRESS ONTO STACK EMT 377 ; EXECUTE THE DIRECTIVE BCC 20$ ; IF CC, OKAY CMPB $DSW,#IE.UPN ; WAS ERROR "NO RESOURCES" ? SEC ; ASSUME NO, INDICATE ERROR BNE 20$ ; IF NE, NO - RETURN WITH ERROR WSIG$S ; ELSE, WAIT A WHILE BR 10$ ; AND TRY AGAIN 20$: MOV (SP)+,(SP) ; CLEAN DPB OFF STACK RETURN .SBTTL OPEN - ACCESS REMOTE DEVICE/FILE ;+ ; **-OPEN-ACCESS REMOTE DEVICE/FILE ;- OPEN: ; ; ASSIGN LUNS AND OPEN MAILBOX ; MOV #NSERR,TEXT ; ASSUME NETWORK NOT LOADED ALUN$S #.MBXLU,#"NS ; ASSIGN MAILBOX LUN BCS 10$ ; IF CS, COULDN'T - EXIT ALUN$S #.LLLUN,#"NS ; ASSIGN LOGICAL LINK LUN BCS 10$ ; IF CS, COULDN'T - EXIT MOV #OPNERR,TEXT ; ASSUME OPEN ERROR XDIR$ #OPN ; OPEN THE NET BCS 90$ ; IF CS, EXIT TSTB NSSTAT ; SUCCESS ? BMI 90$ ; IF MI, NO XDIR$ #SPA ; SET UP OUR NETWORK DATA AST 10$: BCS 90$ ; IF CS, EXIT ; ; GET TARGET NAME AND CONNECT ; MOV #CONERR,TEXT ; ASSUME CONNECT ERROR CALL SPAAST ; GET THE ORIGINATING PEM TST FILEL ; DID WE GET A FILE NAME ? BEQ 90$ ; IF EQ, NO - EXIT XDIR$ #CON ; ATTEMPT CONNECT TO SERVER BCS 90$ ; IF CS, COULDN'T TSTB NSSTAT ; SUCCESS ? BMI 90$ ; IF MI, NO ; ; EXCHANGE CONFIGURATION MESSAGES ; MOV #PROERR,TEXT ; ASSUME PROTOCOL VIOLATION MOV #CONMSG,SNDW+Q.IOPL ; SET UP TO SEND CONFIGURATION MESSAGE MOV #CONSIZ,SNDW+Q.IOPL+2 ; ... XDIR$ #SNDW ; SEND A CONFIGURATION MESSAGE XDIR$ #RECMSG ; TRY TO GET ONE TSTB RCVSTT ; ERROR ? BMI 90$ ; IF MI, YES CMPB RCVSTT+2,#6 ; DID WE GET ENOUGH DATA ? BLO 90$ ; IF LO, NO - BAD MESSAGE CMPB RCVBUF,#TY.CON ; WAS IT A CONFIGURATION MESSAGE ? BNE 90$ ; IF NE, NO - ERROR MOV RCVBUF+C.BUFL,R0 ; ELSE, SAVE THE SERVER'S BUFFER SIZE MOV R0,MAXBUF ; ... .REPT 6 ASR R0 ; CONVERT TO NUMBER OF 64 BYTE BLOCKS .ENDR MOV R0,MAX64 ; SAVE MAX BLOCKS FOR UPDATING UISAR6 ; ; SEND THE ATTACH REQUEST AND GET THE STATUS ; MOV #IO.ATT,FUNC ; SET THE ATTACH FUNCTION MOV #REQMSG,SNDW+Q.IOPL ; SET UP FOR SENDING REQUEST MOV #REQSIZ,SNDW+Q.IOPL+2 ; ... XDIR$ #SNDW ; SEND THE REQUEST MOV #FILE,SNDW+Q.IOPL ; POINT TO THE FILE NAME MOV FILEL,SNDW+Q.IOPL+2 ; SET LENGTH OF NAME XDIR$ #SNDW ; SEND IT OVER XDIR$ #RECMSG ; RECEIVE THE STATUS TSTB RCVSTT ; ERROR ? BMI 90$ ; IF MI, YES CMPB RCVSTT+2,#6 ; DID WE GET ENOUGH DATA ? BLO 90$ ; IF LO, NO - BAD MESSAGE CMPB RCVBUF,#TY.STA ; WAS IT STATUS MESSAGE ? BNE 90$ ; IF NE, NO - ERROR MOV #DEVERR,TEXT ; ASSUME COULDN'T ACCESS DEVICE/FILE MOVB RCVBUF+S.STAT,R1 ; GET ERROR RETURN MOV #DEVBUF,R0 ; POINT TO BUFFER FOR ERROR CODE CLR R2 ; ZERO SUPPRESS CALL $CBDSG ; CONVERT IT TO ASCII MOVB #'),(R0)+ ; PUT IN TRAILING DELIMITER CLRB (R0) ; ... CMPB RCVBUF+S.STAT,#IS.SUC ; SUCCESS ? BNE 90$ ; IF NE, NO - ERROR ; ; GET DEVICE CHARACTERISITICS ; XDIR$ #RECMSG ; READ THE CHARACTERISTICS TSTB RCVSTT ; ERROR ? BPL 100$ ; IF PL, NO 90$: SEC ; INDICATE ERROR 100$: RETURN ; AND OUT .SBTTL SPAAST - NETWORK DATA AST ROUTINE ;+ ; **-SPAAST-NETWORK DATA AST SERVICE ROUTINE ; ; THIS ROUTINE IS CALLED TO PROCESS NETWORK DATA. ; ;- SPAAST: 10$: XDIR$ #GND ; GET NETWORK DATA CMPB #IE.NDA,GNDSTT ; WAS THERE ANY DATA? BEQ 100$ ; IF EQ, NO - ALL DONE MOVB GNDSTT+1,R5 ; ELSE, GET DATA TYPE ASL R5 ; CONVERT TO WORD OFFSET CALL @GNDTAB-2(R5) ; DISPATCH TO CORRECT ROUTINE BR 10$ ; LOOK FOR MORE DATA 100$: ASTX$S ; EXIT THE AST RETURN ; OR RETURN IF CALLED ; ; NETWORK DATA DISPATCH TABLE ; GNDTAB: .WORD GNDCON ; CONNECT REQUEST .WORD GNDINT ; INTERRUPT MESSAGE .WORD GNDDSC ; DISCONNECTS .WORD GNDDSC ; 3 FLAVORS .WORD GNDDSC ; .. .WORD GNDPEM ; NETWORK EVENT .SBTTL GNDCON - PROCESS CONNECT REQUEST .SBTTL GNDINT - PROCESS INTERRUPT MESSAGE .SBTTL GNDDSC - PROCESS DISCONNECT ;+ ; **-GNDCON-PROCESS CONNECT REQUEST ; ; ALL INCOMING CONNECTS ARE REJECTED ; ;- GNDCON: XDIR$ #REJ ; REJECT THE CONNECT RETURN ;+ ; **-GNDINT-PROCESS INTERRUPT MESSAGE ; ; ALL INCOMING INTERRUPT MESSAGES ARE IGNORED ; ;- GNDINT: RETURN ; TOSS IT ;+ ; **-GNDDSC-PROCESS DISCONNECT ; ; THE TASK IS UNSTOPPED, AND THE EXIT FLAG IS SET FOR DISCONNECTS ; ;- GNDDSC: MOV #ABTERR,TEXT ; SET LINK ABORTED ERROR MESSAGE ABORT: GTSK$S #GNDBUF ; GET TASK PARAMETERS (NAME) USTP$S #GNDBUF ; UNSTOP OURSELF DIR$ #SETF ; SET THE EXIT FLAG RETURN .SBTTL GNDPEM - PROCESS PEM REQUEST ;+ ; **-GNDPEM-PROCESS START/STOP NETWORK EVENT ; ; FOR A START (IO.ATT), THE USER ID, TARGET NODE NAME, AND ; FILE/DEVICE NAME ARE SAVED. ; ;- GNDPEM: CMP #IO.ATT,GNDBUF+P.FUNC ; IS THIS A START (ATTACH) REQUEST ? BNE 100$ ; IF NE, NO - TOSS IT TST USER ; ARE WE ALREADY ACTIVE ? BNE 100$ ; IF NE, YES - TOSS IT SWSTK$ 8$ ;; ELSE, ENTER SYSTEM STATE MOV #GNDBUF,R3 ;; POINT TO SENDER'S NAME CALL $SRSTD ;; LOOK FOR HIS TCB BCS 6$ ;; IF CS, NOT THERE - TOSS IT BIT #T3.PRV,T.ST3(R0) ;; ELSE, IS HE PRIVILEGED ? BNE 7$ ;; IF NE, YES - OKAY 6$: MOV @$HEADR,R0 ;; ELSE, GET SAVED SP INC 6(SP) ;; SET USER C-BIT 7$: RETURN ;; AND BACK TO USER STATE 8$: BCS 100$ ; IF CS, TOSS MESSAGE MOV GNDBUF,PEMMSG ; ELSE, REMEMBER THE TASK'S NAME MOV GNDBUF+2,PEMMSG+2 ; ... MOV GNDBUF+4,PEMMSG+4 ; ... AND TI: IDENTIFIER MOV GNDBUF+P.USER,USER ; SAVE USER'S TI: UCB ADDRESS MOV GNDBUF+P.OWNR,OWNER ; SAVE OWNER OF DEVICE MOV GNDBUF+P.NODE,CONB+N.RND ; SET TARGET NODE NAME MOV GNDBUF+P.NODE+2,CONB+N.RND+2 ; ... MOV GNDBUF+P.NODE+4,CONB+N.RND+4 ; ... MOV GNDBUF+P.LOGN,LOGNAM ; SAVE LOGICAL NAME TO ASSIGN MOV GNDBUF+P.LOGN+2,LOGNAM+2; ... MOV #GNDBUF+P.FILE,R5 ; POINT TO FILE NAME MOV (R5)+,R4 ; GET LENGTH OF NAME MOV R4,FILEL ; SAVE LENGTH MOV #FILE,R3 ; POINT TO SAVE BUFFER 10$: MOVB (R5)+,(R3)+ ; SAVE FILE/DEVICE NAME DEC R4 ; ... BNE 10$ ; ... MOV #GNDBUF+P.ACC,R5 ; POINT TO ACCESS CONTROL MOV #CONB+N.RIDC,R3 ; POINT TO ACCESS FIELD IN CONNECT BLOCK 20$: MOV (R5)+,(R3)+ ; SET THE ACCESS CONTROL INFO CMP R3,#CONB+N.RQL ; ARE WE AT THE END OF CONB$$ ? BLOS 20$ ; IF LOS, NO MOV $TKTCB,R0 ; GET OUR TCB ADDRESS MOV USER,T.UCB(R0) ; SET OUR TI: TO THE USER'S 100$: RETURN .SBTTL GETVD - GET A VIRTUAL DEVICE OF THE CORRECT TYPE ;+ ; **-GETVD-GET A VIRTUAL DEVICE OF THE CORRECT TYPE ; ; THIS ROUTINE IS CALLED AFTER A DEVICE CHARACTERISTICS MESSAGE IS RECEIVED ; TO ALLOCATE AND INITIALIZE THE DATA STRUCTURES FOR A VIRTUAL DEVICE. ; ;- GETVD: MOV #NVDERR,TEXT ; ASSUME ERROR = "NO DEVICE" MOV #DEVTBL,R0 ; POINT TO START OF DEVICE TABLE MOVB RCVBUF,DEVTYP ; SAVE REMOTE DEVICE TYPE 10$: CMPB RCVBUF,(R0) ; IS THIS THE CORRECT TYPE ? BEQ 20$ ; IF EQ, YES - FIND A FREE UNIT ADD #4,R0 ; POINT TO NEXT ENTRY CMP R0,#DEVEND ; PAST LAST TABLE ENTRY ? BLO 10$ ; IF LO, NO - KEEP LOOKING SEC ; ELSE, INDICATE ERROR BR 100$ ; AND RETURN 20$: MOVB 2(R0),NVDBUF ; SAVE DEVICE TYPE FOR POSSIBLE ERROR MOVB 3(R0),NVDBUF+1 ; ... SWSTK$ 90$ ;; ENTER SYSTEM STATE MOV $DEVHD,R1 ;; POINT TO FIRST DEVICE DCB 30$: CMP D.NAM(R1),2(R0) ;; IS THIS THE CORRECT DCB ? BEQ 40$ ;; IF EQ, YES - TRY TO FIND A UNIT 35$: MOV (R1),R1 ;; ELSE, KEEP LOOKING BNE 30$ ;; IF NE, MORE DCB'S MOV @$HEADR,R0 ;; ELSE, GET SAVED SP INC 6(R0) ;; SET USER C-BIT BR 80$ ;; AND RETURN 40$: MOVB D.UNIT+1(R1),R2 ;; GET HIGH UNIT NUMBER MOVB D.UNIT(R1),R3 ;; AND LOW UNIT NUMBER SUB R3,R2 ;; CALC NUMBER OF UCB'S ON THIS DCB MOV D.UCB(R1),R3 ;; POINT TO FIRST UCB 45$: TST U.VDV(R3) ;; IS THIS UNIT ALLOCATED ? BEQ 60$ ;; IF EQ, NO - USE IT ADD D.UCBL(R1),R3 ;; ELSE, POINT TO NEXT UCB DEC R2 ;; IS THERE ANOTHER UNIT TO CHECK ? BGE 45$ ;; IF GE, YES BR 35$ ;; ELSE, LOOK FOR ANOTHER DCB 60$: CLR TEXT ;; CLEAR OUT ERROR TEXT POINTER MOV #EX$SUC,EXSTAT ;; SET SUCCESS EXIT STATUS MOV $TKTCB,U.VDV(R3) ;; ALLOCATE THE DEVICE MOV OWNER,U.USR(R3) ;; SET THE OWNER MOV OWNER,U.OWN(R3) ;; ALLOCATE DEVICE (IF NOT GLOBAL) MOV #KILAST,U.AST(R3) ;; SET THE I/O KILL AST ADDRESS BICB #US.OFL,U.ST2(R3) ;; MARK UNIT AS ONLINE MOV RCVBUF+2,U.CW2(R3) ;; SET NUMBER OF BLOCKS MOV RCVBUF+4,U.CW3(R3) ;; ... MOV RCVBUF+6,U.CW4(R3) ;; AND BUFFER SIZE MOV R3,VDUCB ;; SAVE THE UCB ADDRESS MOV #ATTBUF,R0 ;; POINT TO BUFFER FOR FORMATTED NAME MOVB D.NAM(R1),(R0)+ ;; SET IN DEVICE NAME MOVB D.NAM+1(R1),(R0)+ ;; ... MOVB D.UNIT+1(R1),R1 ;; GET THE HI UNIT FOR THIS DCB SUB R2,R1 ;; CALC THIS UNIT'S RELATIVE NUMBER BIC #177400,R1 ;; DON'T SIGN-EXTEND CLR R2 ;; ZERO SUPPRESS CALL $CBOMG ;; CONVERT TO ASCII MOVB #':,(R0)+ ;; PUT IN TERMINATOR CLRB (R0) ;; MAKE ASCIZ 80$: RETURN ;; BACK TO USER STATE 90$: BCS 100$ ; IF CS, RETURN WITH ERROR MOV #ATTMSG,R0 ; ELSE, SET UP "DEVICE ATTACHED" MESSAGE CALL PRINT ; TELL THE USER ABOUT IT 100$: RETURN ; ; TABLE OF DEVICE TYPES ; DEVTBL: .WORD 1 ; DISK .WORD "VD ; ... .WORD 2 ; TAPE .WORD "VM ; ... .WORD 3 ; PRINTER .WORD "VP ; ... DEVEND: ; END OF TABLE .SBTTL ASNLOG - ASSIGN A LOGICAL NAME TO THE ALLOCATED DEVICE ;+ ; **-ASNLOG-ASSIGN A LOGICAL NAME TO THE ALLOCATED DEVICE ; ; THIS ROUTINE IS CALLED TO CREATE A LOGICAL DEVICE ASSIGNMENT FOR THE ; ALLOCATED VIRTUAL DEVICE. ; ;- ASNLOG: ; ; SEARCH FOR LOGICAL ASSIGNMENT CONTROL BLOCK (LCB) ; TST LOGNAM ; ANY NAME TO ASSIGN ? BEQ 60$ ; IF EQ, NO MOV #$LOGHD,R0 ; GET ADDRESS OF LCB LIST HEAD 10$: MOV R0,R1 ; GET ADDRESS OF PREVIOUS LCB MOV L.LNK(R1),R0 ; GET ADDRESS OF NEXT LCB BEQ 20$ ; IF EQ, AT END OF LIST CMP LOGNAM,L.NAM(R0) ; ELSE, ARE THE NAMES THE SAME ? BNE 10$ ; IF NE, NO CMPB LOGNAM+2,L.UNIT(R0) ; YES, UNIT NUMBER THE SAME ? BNE 10$ ; IF NE, NO CMPB #1,L.TYPE(R0) ; LOCAL ASSIGNMENT ? BNE 10$ ; IF NE, NO CMP USER,L.UCB(R0) ; SAME TI: TERMINAL ? BNE 10$ ; IF NE, NO SWSTK$ 50$ ;; ENTER SYSTEM STATE MOV VDUCB,L.ASG(R0) ;; REASSIGN LCB TO NEW PHYSICAL UNIT RETURN ;; RETURN TO USER STATE ; ; ADD AN LCB TO LIST ; 20$: MOV #$LOGHD,R1 ; YES, ADD LCB TO FRONT OF LIST MOV R1,R4 ; SAVE POINTER TO PREVIOUS LCB SWSTK$ 50$ ;; SWITCH TO SYSTEM STATE MOV #L.LGTH,R1 ;; SET LENGTH OF BLOCK CALL $ALOCB ;; TRY TO GET SPACE BCC 30$ ;; IF CS, GOT IT MOV @$HEADR,R0 ;; ELSE, GET SAVED SP INC 6(R0) ;; SET USER C-BIT BR 40$ ;; AND RETURN 30$: MOV L.LNK(R4),L.LNK(R0) ;; LINK IN LCB MOV R0,L.LNK(R4) ;; ... MOV LOGNAM,L.NAM(R0) ;; SET DEVICE NAME MOVB LOGNAM+2,L.UNIT(R0) ;; AND UNIT NUMBER MOVB #1,L.TYPE(R0) ;; SET TYPE OF ASSIGNMENT MOV VDUCB,L.ASG(R0) ;; SET PHYSICAL DEVICE ASSIGNMENT MOV USER,L.UCB(R0) ;; SET LOCAL ASSIGNMENT UCB 40$: RETURN ;; RETURN TO USER STATE 50$: BCC 60$ ; IF CC, SUCCESS MOV #ASNERR,R0 ; ELSE, WARN USER ABOUT ASSIGNMENT CALL PRINT ; ... 60$: RETURN .SBTTL GETIOP - GET AN I/O PACKET ;+ ; **-GETIOP-GET AN I/O PACKET ; ; THIS ROUTINE GETS THE NEXT I/O PACKET FOR ALLOCATE VIRTUAL DEVICE OR STOPS. ; ;- GETIOP: SWSTK$ 50$ ;; ENTER SYSTEM STATE ; ; CHECK IF TASK IS EXITING ; 10$: MOV $TKTCB,R0 ;; GET OUR TCB ADDRESS BIT #1,T.EFLG(R0) ;; IS THE EXIT FLAG SET ? BEQ 30$ ;; IF EQ, NO - LOOK FOR A PACKET ; ; TASK IS EXITING - FINISH ALL I/O WITH IE.OFL STATUS, AND MARK UNIT AS OFFLINE. ; MOV @$HEADR,R1 ;; ELSE, GET SAVED SP INC 6(R1) ;; SET USER C-BIT 20$: MOV VDUCB,R5 ;; GET VD UCB ADDRESS BISB #US.OFL,U.ST2(R5) ;; SET UNIT AS OFFLINE CLR U.VDV(R5) ;; INDICATE NO OWNING TASK CLR U.USR(R5) ;; OR USER CLR U.OWN(R5) ;; AND DEVICE NOT ALLOCATED CALL 60$ ;; TRY TO GET A PACKET BCS 40$ ;; IF CS, COULDN'T - RETURN MOV #IE.OFL&377,R0 ;; ELSE, SET OFFLINE STATUS CLR R1 ;; ... CALL $IOFIN ;; AND COMPLETE I/O BR 20$ ;; DO TILL NO MORE PACKETS ; ; TASK IS NOT EXITING, TRY TO GET A PACKET. IF NO PACKET, STOP THE TASK. ; 30$: CALL 60$ ;; TRY TO GET A REQUEST BCC 40$ ;; IF CC, GOT ONE - RETURN CALLR $STPCT ;; ELSE, STOP OURSELF 40$: RETURN ;; BACK TO USER STATE 50$: BCS 40$ ; IF CS, RETURN TO CALLER TST CURIOP ; ELSE, DO WE HAVE WORK YET ? BNE 40$ ; IF NE, YES - DO IT BR GETIOP ; ELSE, NO - LOOK AGAIN ; ; LOCAL SUBROUTINE TO FIND A PACKET ; 60$: MOV $TKTCB,R0 ;; POINT TO OUT TCB ADDRESS ADD #T.RCVL,R0 ;; POINT TO THE RECEIVE LISTHEAD MOV (R0),R3 ;; GET THE NEXT PACKET ADDRESS SEC ;; ASSUME NO PACKET BEQ 80$ ;; IF EQ, NO WORK MOV (R3),(R0) ;; UNLINK PACKET FROM LIST BNE 70$ ;; IF NE, MORE IN LIST MOV R0,2(R0) ;; ELSE, CLOSE UP LIST 70$: INC CURSEQ ;; INCREMENT PACKET SEQUENCE NUMBER CLR KILFLG ;; INDICATE KILL NOT ACTIVE ;; ... AND CLEAR C-BIT 80$: MOV R3,CURIOP ;; SAVE PACKET ADDRESS RETURN ;; RETURN TO CALLER .SBTTL KILAST - I/O KILL AST ROUTINE ;+ ; **-KILAST-I/O KILL AST ROUTINE ; ; THIS ROUTINE IS CALLED WHEN THE DRIVER IS CALLED AT IT'S ; CANCEL I/O ENTRY POINT, AND QUEUES AN AST. ; ; INPUTS: ; (SP) = ADDRESS OF TCB OF TASK WHOSE I/O IS TO BE KILLED ; ; ;- KILAST: MOV R5,-(SP) ; SAVE R5 MOV 2(SP),R5 ; GET TCB ADDRESS SWSTK$ 50$ ;; ENTER SYSTEM STATE 10$: MOV $TKTCB,R4 ;; GET OUR TCB ADDRESS ADD #T.RCVL,R4 ;; POINT TO OUR RECEIVE QUEUE 20$: MOV (R4),R3 ;; POINT TO THE NEXT I/O PACKET BEQ 40$ ;; IF EQ, ALL THROUGH CMP R5,I.TCB(R3) ;; IS THIS PACKET FROM THAT TASK ? BEQ 30$ ;; IF EQ, YES - KILL THE I/O MOV R3,R4 ;; ELSE, SET UP TO LOOK AT NEXT BR 20$ ;; AND CONTINUE 30$: MOV (R3),(R4) ;; UNLINK THE PACKET FROM THE QUEUE BNE 35$ ;; IF NE, NOT LAST PACKET MOV $TKTCB,R2 ;; ELSE, POINT TO OUR TCB MOV R4,T.RCVL+2(R2) ;; AND CLOSE LIST 35$: MOV #IE.ABO&377,R0 ;; SET ABORT ERROR CODE CLR R1 ;; INDICATE 0 BYTES TRANSFERRED CALL $IOFIN ;; COMPLETE THE I/O BR 10$ ;; AND LOOK FOR MORE 40$: RETURN ;; BACK TO USER STATE 50$: MOV CURIOP,R5 ; POINT TO CURRENT I/O PACKET BEQ 100$ ; IF EQ, NO ACTIVE REQUEST TST KILFLG ; HAS A KILL REQUEST BEEN SENT YET ? BNE 100$ ; IF EQ, YES - DON'T SEND ANOTHER CMP 2(SP),I.TCB(R5) ; ELSE, IS THIS FROM THE SAME TASK ? BNE 100$ ; IF NE, NO - ALL DONE MOV CURSEQ,KILSEQ ; ELSE, INDICATE SEQ NUMBER TO KILL INC KILFLG ; INDICATE OUTSTANDING KILL REQUEST XDIR$ #XMIKIL ; TRANSMIT THE KILL INTERRUPT MESSAGE 100$: MOV (SP)+,R5 ; RESTORE R5 TST (SP)+ ; CLEAN TCB ADDRESS OFF STACK ASTX$S ; AND EXIT THE AST .SBTTL PRIOP - PROCESS AN I/O PACKET ;+ ; **-PRIOP-PROCESS AN I/O PACKET ; ; THIS ROUTINE DISPATCHES TO THE APPROPIATE I/O ROUTINE, AND ; POSTS COMPLETION ON THE PACKET. ; ;- PRIOP: MOV CURIOP,R3 ; GET THE PACKET ADDRESS CLRB RFLAGS ; INIT THE REQUEST FLAGS MOV I.FCN(R3),FUNC ; SET THE FUNCTION FOR THE REQUEST MOVB I.FCN+1(R3),R0 ; GET THE FUNCTION CODE MOV #FCNTBL,R1 ; POINT TO THE DISPATCH TABLE 10$: CMP R0,(R1)+ ; IS THIS THE CORRECT ROUTINE ? BEQ 20$ ; IF EQ, YES - CALL IT TST -2(R1) ; AT END OF TABLE ? BEQ 20$ ; IF EQ, YES - CALL IT ILLEGAL FUNCTION TST (R1)+ ; ELSE, SKIP OVER ROUTINE ADDRESS BR 10$ ; AND KEEP LOOKING 20$: CALL @(R1) ; DISPATCH TO CORRECT ROUTINE SWSTK$ 30$ ;; ENTER SYSTEM STATE CALLR $IOFIN ;; FINISH OFF THE I/O 30$: RETURN ; AND RETURN ; ; I/O FUNCTION DISPATCH TABLE ; FCNTBL: FUNC$ IO.WLB,WRITE ; WRITE LOGICAL BLOCK FUNC$ IO.RLB,READ ; READ LOGICAL BLOCK FUNC$ IO.RLV,READ ; READ LOGICAL BLOCK REVERSE FUNC$ IO.EOF,NOTRAN ; WRITE END-OF-FILE MARK FUNC$ IO.ERS,NOTRAN ; ERASE TAPE FUNC$ IO.RWD,NOTRAN ; REWIND TAPE FUNC$ IO.SEC,NOTRAN ; SENSE TAPE CHARACTERISTICS FUNC$ IO.SMO,NOTRAN ; MOUNT AND SET TAPE CHARACTERISTICS FUNC$ IO.SPB,NOTRAN ; SPACE BLOCKS FUNC$ IO.SPF,NOTRAN ; SPACE FILES FUNC$ IO.STC,NOTRAN ; SET TAPE CHARACTERISTICS FUNC$ 0,ILEGAL ; END OF TABLE .SBTTL ILEGAL - PROCESS AN ILLEGAL FUNCTION CODE ;+ ; **-ILEGAL-PROCESS AN ILLEGAL FUNCTION CODE ; ; THIS ROUTINE RETURNS I/O STATUS OF IE.IFC ; ; INPUTS: ; R3 = I/O PACKET ADDRESS ; ; OUTPUTS: ; R0 = 1ST I/O STATUS WORD ; R1 = 2ND I/O STATUS WORD ; R3 = I/O PACKET ADDRESS ;- ILEGAL: MOV #IE.IFC&377,R0 ; SET STATUS RETURN CLR R1 ; ... RETURN .SBTTL WRITE - PROCESS WRITE REQUESTS ;+ ; **-WRITE-PROCESS WRITE REQUEST ; ; THIS ROUTINE TRANSMITS A REQUEST MESSAGE, FOLLOWED BY AS ; MANY DATA MESSAGES AS REQUIRED TO COMPLETE THE DATA ; ; INPUTS: ; R3 = I/O PACKET ADDRESS ; ; OUTPUTS: ; R0 = 1ST I/O STATUS WORD ; R1 = 2ND I/O STATUS WORD ; R3 = I/O PACKET ADDRESS ;- WRITE: MOV I.PRM(R3),CURAPR ; SAVE USER BUFFER APR BIAS MOV I.PRM+4(R3),PARAM ; SET LENGTH OF WRITE MOV I.PRM+6(R3),PARAM+2 ; SET VFC MOV I.PRM+10(R3),PARAM+4 ; SET BLOCK NUMBER MOV I.PRM+12(R3),PARAM+6 ; ... MOV PARAM,CURLEN ; SAVE TOTAL LENGTH CMPB DEVTYP,#3 ; IS REMOTE DEVICE A PRINTER ? BNE 5$ ; IF NE , NO - REQUEST STATUS BISB #RF.NST,RFLAGS ; ELSE, WRITE WITHOUT STATUS 5$: MOV #REQMSG,SND+Q.IOPL ; SET UP FOR SENDING REQUEST MOV #REQSIZ,SND+Q.IOPL+2 ; ... XDIR$ #SND ; SEND THE REQUEST 10$: MOV #SND,R0 ; ASSUME NOT LAST REQUEST MOV MAXBUF,R1 ; ASSUME WE'LL FILL HOST'S BUFFER CMP CURLEN,R1 ; WILL DATA FIT IN HOST'S BUFFER ? BHI 20$ ; IF HI, NO - SEND MAXBUF MOV #SNDW,R0 ; LAST XMIT IS SYNCHRONOUS MOV CURLEN,R1 ; SEND REMAINING DATA 20$: MOV I.PRM+2(R3),Q.IOPL(R0) ; SET VIRTUAL BUFFER ADDRESS MOV R1,Q.IOPL+2(R0) ; SET XMIT LENGTH SUB R1,CURLEN ; UPDATE REMAINING DATA COUNT 21$: MTPS #PR7 ;;; LOCK OUT INTERRUPTS MOV CURAPR,UISAR6 ;;; MAP TO USER'S BUFFER MOV #77406,UISDR6 ;;; SET 4K R/W ACCESS DIR$ R0 ;;; ISSUE THE DIRECTIVE BCC 22$ ; IF CC, OKAY CMPB $DSW,#IE.UPN ; WAS ERROR "NO RESOURCES" ? SEC ; ASSUME NO, INDICATE ERROR BNE 100$ ; IF NE, NO - RETURN WITH ERROR WSIG$S ; ELSE, WAIT A WHILE BR 21$ ; AND TRY AGAIN 22$: ADD MAX64,CURAPR ; UPDATE BUFFER APR BIAS TST CURLEN ; ANYTHING LEFT TO SEND ? BNE 10$ ; IF NE, YES - DO IT TSTB SNDSTT ; DID THE XMIT SUCCEED ? BPL 30$ ; IF PL, YES - GET STATUS 25$: MOV #IE.OFL&377,R0 ; SAY DEVICE WENT AWAY CLR R1 ; ... DIR$ #SETF ; SET EXIT FLAG BR 100$ ; AND FINISH I/O 30$: MOV #IS.SUC,R0 ; ASSUME SUCCESS MOV #PARAM,R1 ; ASSUME ALL BYTES WERE WRITTEN BITB #RF.NST,RFLAGS ; IS THIS A WRITE WITHOUT STATUS ? BNE 100$ ; IF NE, YES - FINISH I/O XDIR$ #RECMSG ; GET THE I/O STATUS TSTB RCVSTT ; ERROR ? BMI 25$ ; IF MI, YES - KILL LINK CMPB RCVBUF,#4 ; IS THIS A STATUS MESSAGE ? BNE 25$ ; IF NE, NO - PROTOCOL ERROR MOV RCVBUF+2,R0 ; GET STATUS RETURN MOV RCVBUF+4,R1 ; GET LENGTH OF DATA SENT 100$: RETURN .SBTTL READ - PROCESS READ REQUESTS ;+ ; **-READ-PROCESS READ REQUEST ; ; THIS ROUTINE TRANSMITS A REQUEST MESSAGE, AND RECEIVES AS ; MANY DATA MESSAGES AS REQUIRED TO COMPLETE THE DATA ; ; INPUTS: ; R3 = I/O PACKET ADDRESS ; ; OUTPUTS: ; R0 = 1ST I/O STATUS WORD ; R1 = 2ND I/O STATUS WORD ; R3 = I/O PACKET ADDRESS ;- READ: MOV I.PRM(R3),CURAPR ; SAVE USER BUFFER APR BIAS MOV I.PRM+4(R3),PARAM ; SET LENGTH OF READ MOV I.PRM+6(R3),PARAM+2 ; SET VFC MOV I.PRM+10(R3),PARAM+4 ; SET BLOCK NUMBER MOV I.PRM+12(R3),PARAM+6 ; ... MOV PARAM,CURLEN ; SAVE TOTAL LENGTH MOV #REQMSG,SNDW+Q.IOPL ; SET UP FOR SENDING REQUEST MOV #REQSIZ,SNDW+Q.IOPL+2 ; ... XDIR$ #SNDW ; SEND THE REQUEST 10$: MOV #REC,R0 ; ASSUME NOT LAST REQUEST MOV MAXBUF,R1 ; ASSUME WE NEED MORE THAN 1 RECEIVE CMP CURLEN,R1 ; WILL DATA FIT IN HOST'S BUFFER ? BHI 20$ ; IF HI, NO - RECEIVE MAXBUF MOV #RECW,R0 ; LAST RECEIVE IS SYNCHRONOUS MOV CURLEN,R1 ; RECEIVE REMAINING DATA 20$: MOV I.PRM+2(R3),Q.IOPL(R0) ; SET VIRTUAL BUFFER ADDRESS MOV R1,Q.IOPL+2(R0) ; SET RECEIVE LENGTH SUB R1,CURLEN ; UPDATE REMAINING DATA COUNT 21$: MTPS #PR7 ;;; LOCK OUT INTERRUPTS MOV CURAPR,UISAR6 ;;; MAP TO USER'S BUFFER MOV #77406,UISDR6 ;;; SET 4K R/W ACCESS DIR$ R0 ;;; ISSUE THE DIRECTIVE BCC 22$ ; IF CC, OKAY CMPB $DSW,#IE.UPN ; WAS ERROR "NO RESOURCES" ? SEC ; ASSUME NO, INDICATE ERROR BNE 100$ ; IF NE, NO - RETURN WITH ERROR WSIG$S ; ELSE, WAIT A WHILE BR 21$ ; AND TRY AGAIN 22$: ADD MAX64,CURAPR ; UPDATE USER APR BIAS TST CURLEN ; ANYTHING LEFT TO RECEIVE ? BNE 10$ ; IF NE, YES - DO IT TSTB RCVSTT ; DID THE RECEIVE SUCCEED ? BPL 30$ ; IF PL, YES - GET STATUS 25$: MOV #IE.OFL&377,R0 ; SAY DEVICE WENT AWAY CLR R1 ; ... XDIR$ #SETF ; SET EXIT FLAG BR 100$ ; AND FINISH I/O 30$: XDIR$ #RECMSG ; GET THE I/O STATUS TSTB RCVSTT ; ERROR ? BMI 25$ ; IF MI, YES - KILL LINK CMPB RCVBUF,#4 ; IS THIS A STATUS MESSAGE ? BNE 25$ ; IF NE, NO - PROTOCOL ERROR MOV RCVBUF+2,R0 ; GET STATUS RETURN MOV RCVBUF+4,R1 ; GET LENGTH OF DATA RECEIVED 100$: RETURN .SBTTL NOTRAN - PROCESS NON-TRANSFER REQUESTS ;+ ; **-NOTRAN-PROCESS NON-TRANSFER REQUEST ; ; THIS ROUTINE TRANSMITS A REQUEST MESSAGE, AND WAITS FOR ; THE STATUS MESSAGE. IT IS USED TO PROCESS THOSE FUNCTIONS ; WHICH DO NOT INVOLVE THE TRANSFER OF DATA. ; ; INPUTS: ; R3 = I/O PACKET ADDRESS ; ; OUTPUTS: ; R0 = 1ST I/O STATUS WORD ; R1 = 2ND I/O STATUS WORD ; R3 = I/O PACKET ADDRESS ;- NOTRAN: MOV I.PRM(R3),PARAM ; COPY PARAMETER #1 CLR PARAM+2 ; REST ARE BLANK CLR PARAM+4 ; ... CLR PARAM+6 ; ... MOV #REQMSG,SNDW+Q.IOPL ; SET UP FOR SENDING REQUEST MOV #REQSIZ,SNDW+Q.IOPL+2 ; ... ; ; HACK FOR RSX MAG-TAPE DRIVER, WHICH PROCESSES SOME REQUESTS DIFFERENTLY ; FOR LABELED AND UN-LABELED MAG-TAPES. ; CMPB DEVTYP,#2 ; IS REMOTE DEVICE A MAG-TAPE ? BNE 5$ ; IF NE , NO MOV VDUCB,R5 ; ELSE, POINT TO OUR UCB BITB #US.LAB,U.STS(R5) ; IS THE TAPE LABELED ? BEQ 5$ ; IF EQ, NO BISB #RF.LAB,RFLAGS ; ELSE, TELL THE OTHER END ABOUT IT 5$: XDIR$ #SNDW ; SEND THE REQUEST BCS 10$ ; IF CS, FATAL ERROR XDIR$ #RECMSG ; GET THE I/O STATUS TSTB RCVSTT ; ERROR ? BPL 20$ ; IF PL, NO, CONTINUE 10$: MOV #IE.OFL&377,R0 ; ELSE, SAY DEVICE WENT AWAY CLR R1 ; ... XDIR$ #SETF ; SET EXIT FLAG BR 100$ ; AND FINISH I/O 20$: CMPB RCVBUF,#4 ; IS THIS A STATUS MESSAGE ? BNE 10$ ; IF NE, NO - PROTOCOL ERROR MOV RCVBUF+2,R0 ; GET STATUS RETURN MOV RCVBUF+4,R1 ; GET LENGTH OF DATA RECEIVED 100$: RETURN .END VDV