.TITLE MBDRIVER - STARLET MAILBOX DEVICE DRIVER .IDENT /X05/ ; ; ; COPYRIGHT (C) 1978 ; DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS 01754 ; ; 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 SOFTWARE 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. ; ;++ ; FACILITY: ; ; VAX/VMS MAILBOX DEVICE DRIVER ; ; ABSTRACT: ; ; THIS MODULE CONTAINS THE MAILBOX DRIVER I/O ROUTINES. ; ; AUTHOR: R. HEINEN 16-SEPT-76 ; ;-- ; EXTERNAL SYMBOLS ; $ACBDEF ; DEFINE AST CONTROL BLOCK $CADEF ; DEFINE CONDITIONAL ASSEMBLY $DDBDEF ; DEFINE DDB $DYNDEF ; DEFINE DYNAMIC BLOCK TYPES $IODEF ; DEFINE FUNCTION CODES $IRPDEF ; DEFINE I/O PACKET OFFSETS $IPLDEF ; DEFINE IPL NUMBERS $PCBDEF ; DEFINE PCB OFFSETS $PRDEF ; DEFINE PROCESSOR REGISTERS $PRIDEF ; DEFINE PRIORITY INCREMENTS $RSNDEF ; DEFINE RESOURCE NUMBERS $SSDEF ; DEFINE SYSTEM STATUS CODES $UCBDEF ; DEFINE UCB OFFSETS ; ; LOCAL DEFINITIONS ; UCB$L_MB_MSGQ=UCB$L_FQFL UCB$L_MB_W_AST = UCB$L_ASTQFL UCB$L_MB_R_AST = UCB$L_ASTQBL P1 = 0 ; OFFSET TO BUFFER ADDRESS IN ARGUMENT BLOCK P2 = 4 ; OFFSET TO REQUEST SIZE IN ARGUMENT BLOCK P3 = 8 ; OFFSET FOR PARAMETER 3 P4 = 12 ; OFFSET FOR PARAMETER 4 ; ; LOCAL DATA STORAGE ; .PSECT WIONONPAGED MB$DDT:: .LONG STARTIO ; STARTIO OPERATION .LONG 0 ; NO UNSOLICITED INTERRUTPS .LONG 10$ ; FUNCTION DECISION TABLE .LONG CANCELIO ; CANCEL I/O .LONG 0,0 ; DIAGNOSTIC INFO ; ; FUNCTION DECISION TABLE ; 10$: FUNCTAB ,<- ; LEGAL FUNCTIONS SETMODE,- ; ASK FOR READ OR WRITE AST'S WRITEOF,- ; WRITE EOF READLBLK,WRITELBLK,- READVBLK,WRITEVBLK,- READPBLK,WRITEPBLK> FUNCTAB, FUNCTAB FDTREAD,; READ FUNCTION FUNCTAB FDTWRITE,; WRITE FUNCTION FUNCTAB FDTSET, ; SET AST CONTROL FUNCTAB FDTEOF, ; WRITE EOF .SBTTL EXE$SNDEVMSG - SEND DEVICE DRIVER MAILBOX MESSAGE ;++ ; EXE$SNDEVMSG - SEND DEVICE SPECIFIC MESSAGE ON BEHALF OF DRIVER ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE BUILDS AND SENDS A DEVICE SPECIFIC MESSAGE TO A MAILBOX. ; THE MESSAGE IS FORMATTED AS FOLLOWS: ; ; WORD 0 = TYPE OF MESSAGE ; WORD 1 = UNIT OF DEVICE ; REMAINDER = COUNTED STRING OF DEVICE NAME ; ; INPUTS: ; ; R2 = ADDRESS OF ; R3 = MAILBOX UCB ADDRESS ; R4 = TYPE OF MESSAGE ; R5 = DEVICE UCB ADDRESS ; ; ; OUTPUTS: ; ; R0 = STATUS OF THE OPERATION ; R1,R2,R3,R4,R5 ARE DISTROYED ; ; STATUS RETURNS: ; ; SEE EXE$WRTMAILBOX. ;-- EXE$SNDEVMSG:: ; SEND MESSAGE FOR DEVICE DRIVER PUSHL R5 ; SAVE SENDING DEVICE UCB PUSHR #^M ; PUSH MESSAGE TYPE AND RESERVE SPACE MOVW UCB$W_UNIT(R5),2(SP) ; INSERT UNIT OF DEVICE MOVL UCB$L_DDB(R5),R5 ; ADDRESS SENDING DDB MOVL SP,R2 ; COPY MESSAGE ADDRESS PUSHR #^M ; SAVE MESSAGE ADDRESS AND TARGET UCB EXTZV #0,#4,DDB$T_NAME(R5),-(SP); GET SIZE OF NAME TO 15 CHARAS INCL (SP) ; SET UP TO COPY SIZE TOO MOVC3 (SP),DDB$T_NAME(R5),4(R2); COPY NAME ADDL3 #4,(SP)+,R3 ; GET TOTAL MESSAGE SIZE POPR #^M ; GET ADDRESS AND TARGET UCB BSBB EXE$WRTMAILBOX ; DO THE MAILBOX WRITE ADDL #20,SP ; RESTORE STACK POPR #^M ; RESTORE SENDING UCB RSB ; RETURN .SBTTL SYSTEM INTERNAL WRITE TO MAILBOX SUBROUTINE ;++ ; EXE$WRTMAILBOX - WRITE TO MAILBOX SUBROUTINE FOR EXECUTIVE USE ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED BY SYSTEM ROUTINES TO WRITE A MESSAGE TO A MAILBOX. ; ; INPUTS: ; ; R3 = SIZE OF MESSAGE ; R4 = MESSAGE ADDRESS ; R5 = MAILBOX UCB ADDRESS ; ; OUTPUTS: ; ; R0 = STATUS OF OPERATION ; ; R1,R2 USED. ; ; COMPLETION CODES: ; ; SS$_NORMAL ; SS$_DEVOFFLIN - MAILBOX IS NOT ONLINE ; SS$_MBTOOSML - MESSAGE TOO LARGE FOR MAILBOX ; SS$_MBFULL - MAILBOX FULL OF MESSAGES ; SS$_INSFMEM - MEMORY ALLOCATION PROBLEM ; ;-- EXE$WRTMAILBOX:: ; ; ; SET THE PROPER IPL FOR INTERLOCK ; MFPR #PR$_IPL,-(SP) ; SAVE CURRENT IPL CMPB UCB$B_FIPL(R5),(SP) ; HIGH ENOUGH? BLEQU 10$ ; IF LEQU THEN YES SETIPL UCB$B_FIPL(R5) ; SET THE PROPER IPL ; ; MAIL THE MESSAGE ; 10$: MOVZWL #SS$_DEVOFFLINE,R0 ; ASSUME OFF LINE BBC #UCB$V_ONLINE,UCB$W_STS(R5),20$; BR IF NOT ONLINE MOVZWL #SS$_MBFULL,R0 ; ASSUME MESSAGE WILL NOT FIT CMPW UCB$W_MSGCNT(R5),UCB$W_MSGMAX(R5); MAIL BOX FULL? BEQL 20$ ; IF YES THEN NO WRITE MOVZWL #SS$_MBTOOSML,R0 ; ASSUME MESSAGE TOO BIG MOVAB 22(R3),R1 ; SET SIZE TO REQUEST CMPW R3,UCB$W_BUFQUO(R5) ; MESSAGE FIT? BGTRU 20$ ; IF GTRU THEN NO CMPW R3,UCB$W_DEVBUFSIZ(R5) ; BIGGER THAN ALLOWED? BGTRU 20$ ; IF YES THEN ALSO ERROR PUSHR #^M ; SAVE REGISTERS FROM MOVC BSBW EXE$ALONONPAGED ; GET THE MEMORY BLOCK BLBC R0,15$ ; RETURN UNSUCESSFULLY ON FAILURE ; ; FILL IN BLOCK ; PUSHAQ (R2)+ ; SAVE BLOCK ADDRESS AND PASS LINK WORDS MOVW R1,(R2)+ ; INSERT BLOCK SIZE MOVW #DYN$C_BUFIO,(R2)+ ; INSERT BLOCK TYPE MOVW 4(SP),(R2)+ ; INSERT SIZE OF MESSAGE CLRL (R2)+ ; SET NO PACKET MOVL SCH$GL_CURPCB,R0 ; GET CURRENT PCB MOVL PCB$L_PID(R0),(R2)+ ; INSERT IT ( WHATEVER IT IS! ) ; ; COPY DATA ; MOVC3 4(SP),(R4),(R2) ; MOVE DATA ; ; INSERT IN MESSAGE QUEUE ; POPR #^M ; RESTORE BLOCK ADDRESS MOVL 8(SP),R5 ; RESTORE MAILBOX UCB ADDRESS BSBW INSMBQUEUE ; INSERT ON QUEUE MOVZBL #SS$_NORMAL,R0 ; SET SUCCESS 15$: POPR #^M ; RESTORE REGISTERS 20$: ENBINT ; ENABLE INTERUPTS TO CALLER'S IPL RSB ; AND RETURN .SBTTL CANCELIO - CANCEL I/O ON MAILBOX UNIT ;++ ; CANCELIO - CANCEL I/O ON MAILBOX UNIT ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED TO CANCEL ALL OUTSTANDING I/O FOR A PARTICULAR ; PROCESS AND CHANNEL ON A MAILBOX UNIT. ; IF THE UNIT IS BUSY, THE CURRENT READ PACKET IS CHECKED AND COMPLETED ; IF IT BELONGS TO THE CANCELLING PROCESS. ALL QUEUED REQUESTS HAVE BEEN REMOVED. ; IF NO READER EXISTS THEN THE QUEUE OF OUTSTANDING MESSAGES IS SEARCHED ; FOR MESSAGES AND WAITING WRITES. IF A PID MATCH EXISTS THEN THESE I/O ; ARE ALSO COMPLETED ALONG WITH REMOVING THE MESSAGES. ; THE FINAL ACTION IS TO SEARCH THE QUEUE OF AST REQUESTS TO REMOVE THE ONES ; ASSOCIATED WITH THE CANCELLING PROCESS. ; ; INPUTS: ; ; R2 = NEGITIVE OF CHANNEL NUMBER ; R3 = CURRENT PACKET ADDRESS ; R4 = PCB OF CANCELLING PROCESS ; R5 = UCB OF UNIT ; ; OUTPUTS: ; ; R4,R5 ARE PRESERVED ; ; IPL = DEVICE FORK IPL ;-- CANCELIO: ; CANCEL I/O ON MAILBOX UNIT MOVQ R6,-(SP) ; SAVE R6,R7 MOVL R2,R6 ; COPY CHANNEL NUMBER BBC #UCB$V_BSY,UCB$W_STS(R5),10$; BUSY? CMPL PCB$L_PID(R4),IRP$L_PID(R3); PIDS MATCH? BNEQ 40$ ; IF NO THEN CANCEL DONE CMPW R6,IRP$W_CHAN(R3) ; CHANNEL MATCH? BNEQ 40$ ; IF NEQ THEN NO MOVQ #SS$_ABORT,R0 ; SET STATUS FOR ABORT BSBW IOC$REQCOM ; COMPLETE THE REQUEST BRB 40$ ; AND CANCEL IS DONE ; ; NO READER WAITING - CHECK MESSAGE QUEUE ; 10$: MOVAB UCB$L_MB_MSGQ(R5),R2 ; ADDRESS MESSAGE QUEUE MOVL R2,R0 ; COPY LIST HEAD ADDRESS 20$: MOVL (R2),R2 ; ADDRESS LIST ENTRY CMPL R0,R2 ; END OF LIST? BEQL 40$ ; IF YES THEN DONE CMPL PCB$L_PID(R4),18(R2) ; MESSAGE BELONG TO CANCELLING PROCESS? BNEQ 20$ ; IF NO THEN SEARCH MORE MOVL 14(R2),R3 ; ADDRESS PACKET IF ANY BEQL 20$ ; IF EQL THEN NO ASSOC PACKET CMPW R6,IRP$W_CHAN(R3) ; CHANNEL MATCH? BNEQ 20$ ; IF NEQ THEN NO ; BUT GET RID OF MESSAGE MOVQ #SS$_ABORT,IRP$L_MEDIA(R3); SET STATUS BSBW COM$POST ; COMPLETE THE OPERATION 30$: REMQUE (R2),R0 ; REMOVE MESSAGE FROM QUEUE ADDW 12(R2),UCB$W_BUFQUO(R5) ; ADJUST QUOTA BSBW EXE$DEANONPAGED ; DEALLOCATE MESSAGE BRB 10$ ; SEARCH LIST FROM THE START ; ; SEARCH AST QUEUE ; 40$: MOVAB UCB$L_MB_W_AST(R5),R7 ; ADDRESS LIST OF AST'S BSBW COM$FLUSHATTNS ; FLUSH ATTENTION AST'S MOVAB UCB$L_MB_R_AST(R5),R7 ; ADDRESS WRITER AST'S BSBW COM$FLUSHATTNS ; FLUSH THAT LIST MOVQ (SP)+,R6 ; RESTORE REGISTERS RSB ; RETURN TO CALLER .SBTTL CHECKIO - CHECK READ AND WRITE PARAMETERS .ENABL LSB ;++ ; READCHECKIO - CHECK READ PARAMETERS ; WRITECHECKIO - CHECK WRITE PARAMETERS ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED BY THE READ AND WRITE FDT ROUTINES TO VALIDATE THE ; I/O REQUEST. THE CHECKS ARE MADE BASED ON THE SETTING OF THE IRP$V_FUNC ; OPERATION DIRECTION BIT. THE CHECKS ARE, 1) ACCESS TO UNIT BY UIC, ; 2) MESSAGE REQUEST SIZE WITHIN MAX MESSAGE SIZE, 3) BUFFER ACCESSIBLE. ; ; 0 LENGTH TRANSFERS AND ACCESS VIOLATIONS CAUSE COMPLETIONS HERE. ; ; INPUTS: ; ; R3 = PACKET ADDRESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = ADDRESS OF THE FIRST QIO PARAMETER ; ; OUTPUTS: ; ; R0 = BUFFER ADDRESS ; R1 = BUFFER SIZE ; R3 = PACKET ADDRESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; ; IMPLICIT OUTPUTS: ; ; THE BUFFER ADDRESS AND COUNT IS SAVED IN IRP$L_MEDIA. ;-- READCHECKIO: ; CHECK READ PARAMETERS PUSHAB W^EXE$READCHK ; READ CHECKS NEEDED MOVAB W^EXE$CHKRDACCES,R0 ; BRB 10$ ; CONTINUE IN COMMON WRITECHECKIO: ; SET UP FOR WRITE CHECK MOVAB W^EXE$CHKWRTACCES,R0 ; SET UP WRITE CHECK PUSHAB W^EXE$WRITECHK ; 10$: MOVZWL UCB$W_VPROT(R5),R1 ; SET UP FOR UIC CHECK MOVL UCB$L_OWNUIC(R5),R2 ; CLRW IRP$W_BOFF(R3) ; RESET QUOTA JSB (R0) ; CHECK UIC ACCESS BLBC R0,ERROR ; BR IF ACCESS FAILURE MOVZWL P2(AP),R1 ; GET BUFFER SIZE BEQL 70$ ; IF EQL THEN COMPLETE HERE CMPW R1,UCB$W_DEVBUFSIZ(R5) ; MESSAGE SIZE IN RANGE? BGTRU 50$ ; IF GTRU THEN NO MOVL P1(AP),R0 ; GET BUFFER ADDRESS MOVL R0,IRP$L_MEDIA(R3) ; SAVE BUFFER ADDRESS RSB ; RETURN AND CHECK BUFFER 50$: MOVZWL #SS$_MBTOOSML,R0 ; SET BOX TOO SMALL ERROR: BRW EXE$ABORTIO ; ABORT THE I/O 70$: MOVZBL #SS$_NORMAL,R0 ; COMPLETE 0 LENGTH TRANSFERS BRW EXE$FINISHIOC ; .DSABL LSB .SBTTL FDTREAD - READ FUNCTION DECISION ROUTINE ;++ ; FDTREAD - FUNCTION DECISION ROUTINE FOR READ OPERATIONS ; ; FUNCTIONAL DESCRIPTION: ; ; THE USER REQUEST IS VAILDATED FOR: ; ; 1.ACCESS BY UIC. ; 2.REQUEST WITHIN MAXIMUM MESSAGE SIZE. ; 3.BUFFER ACCESSIBLE FOR WRITE. ; ; THEN THE PACKET IS QUEUED ONTO THE UCB FOR PROCESSING WHEN THE UNIT IS IDLE. ; FOR READ NOW FUNCTIONS, IF NO MESSAGES ARE PRESENT IN THE MAILBOX ; THE OPERATION IS COMPLETED. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = CURRENT PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = PARAMETER BLOCK AT USER ARGUMENT "P1" ; ; OUTPUTS: ; ; THE PACKET IS QUEUED VIA "EXE$QIODRVPKT" OR ; THE REQUEST IS COMPLETED WITH AN ERROR VIA "EXE$ABORTIO" ; ; STATUS CODES: ; ; SS$_NOPRIV - USER DOES NOT HAVE PRIVILEGE TO READ MAILBOX ; SS$_ACCVIO - BUFFER ACCESS VIOLATION ( "EXE$READCHK" ) ; SS$_MBTOOSML - REQUEST EXCEEDS THE MAXIMUM MESSAGE SIZE ; SS$_ENDOFFILE - FOR "READNOW" NO DATA RETURN ; SS$_NORMAL - NORMAL STATUS ( "STARTIO" ) ;-- FDTREAD: ; BSBB READCHECKIO ; VALIDATE THE REQUEST ; ; UPDATE MEASUREMENT COUNTER IF ENABLED ; .IF NE CA$_MEASURE INCL PMS$GL_MBREADS ; COUNT MAILBOX READS .ENDC ; ; CHECK FOR READ NOW FUNCTIONS ; BBC #IO$V_NOW,IRP$W_FUNC(R3),50$; BR IF NOT "NOW" ; ; READ NOW ; ; TEST TO SEE IF THERE ARE ANY MESSAGES WAITING ; SETIPL UCB$B_FIPL(R5) ; SET TO FORK IPL TSTW UCB$W_MSGCNT(R5) ; ANY MESSAGES? BNEQ 50$ ; IF NEQ THEN YES ; ; COMPLETE "READNOW" FUNCTIONS BECAUSE NO MESSAGES ARE AVAILABLE ; MOVZWL #SS$_ENDOFFILE,R0 ; SET NO TRANSFER AND STATUS BRW EXE$FINISHIOC ; COMPLETE THE I/O ; ; QUEUE PACKET TO DRIVER LIST ; 50$: BRW EXE$QIODRVPKT ; QUEUE PACKET ON UCB .SBTTL FDTSET - SET UP ATTENTION AST FUNCTION ;++ ; FDTSET - SET UP ATTENTION AST ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE PROCESSES SET MODE REQUESTS TO ENABLE OR DISABLE AN ATTENTION ; AST. THE WORK IS DONE BY A COMMUNICATION DRIVER SUBROUTINE AFTER A CHECK ; IS MADE TO SEE IF THE REQUESTOR HAS ACCESS TO THE MAILBOX. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = CURRENT PCB ; R5 = UCB ADDRESS FOR MAILBOX UNIT ; ; OUTPUTS: ; ; NONE, THE I/O IS COMPLETED ; ; STATUS RETURNS: ; ; SS$_NORMAL - SUCCESSUFL COMPLETION ; SS$_INSFMEM - INSUFICIENT MEMORY ; SS$_EXQUOTA - AST QUOTA EXCEEDED ;-- FDTSET: ; SET RECEIVE AST FUNCTION ; ; SEE IF USER CAN READ THIS MAILBOX ; MOVZWL UCB$W_VPROT(R5),R1 ; GET UNIT PROTECTION MOVL UCB$L_OWNUIC(R5),R2 ; GET OWNER UIC BSBW EXE$CHKRDACCES ; CHECK THE ACCESS OF THIS USER BLBC R0,ERROR ; IF LOW CLEAR THEN ERROR MOVAB UCB$L_MB_W_AST(R5),R7 ; ASSUME WRITER AST BBC #IO$V_READERAST,IRP$W_FUNC(R3),10$; BR IF NOT READER AST TSTL (R7)+ ; POINT TO READER AST LIST 10$: PUSHR #^M ; SAVE PCB AND LIST HEAD BSBW COM$SETATTNAST ; CONTINUE IN COMMON POPR #^M ; POP PCB AND SET LIST HEAD ADDRESS SETIPL UCB$B_DIPL(R5) ; SET UP THE IPL BBS #IO$V_READERAST,IRP$W_FUNC(R3),15$; BR IF READER AST TSTW UCB$W_MSGCNT(R5) ; ANY MESSAGES? BEQL 25$ ; IF EQL THEN NONE BRB 20$ ; IF NEQ THEN DELIVER AST 15$: BBC #UCB$V_BSY,UCB$W_STS(R5),25$; BR IF NOT BUSY 20$: BSBW COM$DELATTNAST ; DELIVER THE ASTS 25$: MOVL R1,R4 ; RESTORE PCB BRW EXE$FINISHIOC ; COMPLETE THE I/O .SBTTL FDTEOF - WRITE EOF MESSAGE TO MAILBOX ;++ ; FDTEOF - WRITE EOF MESSAGE TO THE MAILBOX ; ; FUNCTIONAL DESCRIPTION: ; ; THIS IS THE FDT ROUTINE FOR IO$WRITEOF. THE ACTION IS TO BUILD A ; ZERO LENGHT MESSAGE AND TO INSERT IT IN THE MAILBOX. ; THIS MESSAGE, WHEN READ RESULTS IN AN SS$_ENDOFILE STATUS RETURN. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = CURRENT PCB ADDRESS ; R5 = MAILBOX UCB ADDRESS ; ; OUTPUTS: ; ; THE I/O IS COMPLETED IN THE WRITE FDT LOGIC. ( SEE BELOW) ;-- FDTEOF: ; CLRL IRP$W_BOFF(R3) ; SET NO TRANSFER AND NO QUOTA MOVZWL UCB$W_VPROT(R5),R1 ; GET VOLUME PROTECTION MOVL UCB$L_OWNUIC(R5),R2 ; GET THE OWNER UIC BSBW EXE$CHKWRTACCES ; CHECK THE ACCESS BLBC R0,ERROR ; IF ERROR THEN BR CLRL R1 ; SET NO DATA MOVAB (SP),R0 ; FAKE GOOD ADDRESS FOR THE FUTURE MOVC BRB WRITE ; WRITE THE MESSAGE .SBTTL FDTWRITE - WRITE OPERATION FDT ROUTINE ;++ ; FDTWRITE -- FUNCTION DECISION ACTION ROUTINE FOR WRITE FUNCTIONS ; ; FUNCTIONAL DESCRIPTION: ; ; THE USER REQUEST IS VALIDATED FOR PRIVILEGE, SIZE, ACCESS AND AVAILABLE ; SPACE. IF VALID, A BUFFERED I/O BLOCK IS ALLOCATED (IMPLIED RESOURCE WAIT). ; THE BLOCK IS SET UP AND QUEUED TO THE UNIT MESSAGE LIST. IF THE UNIT ; IS BUSY, THE OUTSTANDING READ OPERATION IS COMPLETED DIRECTLY. ; IN THE CASE OF "WRITENOW" FUNCTIONS THE I/O IS COMPLETED BEFORE THE ; MESSAGE IS QUEUED. OTHERWISE THE READ COMPLETE ROUTINE COMPLETES ; THE MESSAGE ASSOCIATED WRITE. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = CURRENT PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = ADDRESS OF USER ARGUMENT BLOCK AT "P1" ; ; OUTPUTS: ; ; THE I/O IS COMPLETED IN ERROR, THE I/O IS RESTARTED BECAUSE OF ; RESOURCE WAIT, OR THE I/O IS COMPETED NORMALLY. ; ; STATUS RETURNS: ; ; SS$_MBTOOSML - MESSAGE IS TOO BIG ; SS$_ACCVIO - BUFFER ACCESS VIOLATION ( "EXE$WRITECHK" ) ; SS$_MBFULL - MAILBOX IS FULL ; SS$_NOPRIV - USER DOES NOT HAVE WRITE PRIVILEGE ; SS$_NORMAL - SUCCESSFUL STATUS ; SS$_INSFMEM - NO MEMORY FOR BUFFER ALLOCATION ;-- FDTWRITE: ; BSBW WRITECHECKIO ; CHECK OPERATION PARAMETERS WRITE: PUSHR #^M ; SAVE REGISTERS ADDL #22,R1 ; ADJUST REQUEST SIZE FOR HEADER ; ; GET BUFFER ; BSBW EXE$ALONONPAGED ; ALLOCATE A BUFFER BLBC R0,55$ ; CONTINUE POPR #^M ; RESTORE PACKET ADDRESS AND DATA ADDRESS ; ; SET UP BLOCK ; PUSHR #^M ; SAVE BLOCK,PACKET,PCB AND UCB ADDL #8,R2 ; POINT PAST FIXED PART MOVW R1,(R2)+ ; INSERT SIZE MOVB #DYN$C_BUFIO,(R2)+ ; INSERT TYPE MOVB #IPL$_MAILBOX,(R2)+ ; INSERT IPL MOVW IRP$W_BCNT(R3),(R2)+ ; INSERT MESSAGE SIZE MOVL R3,(R2)+ ; INSERT SAVED PACKET ADDRESS BBC #IO$V_NOW,IRP$W_FUNC(R3),15$; BR IF NOT "NOW" CLRL -4(R2) ; RESET MESSAGE PACKET POINTER 15$: MOVL PCB$L_PID(R4),(R2)+ ; INSERT PID OF SENDER ; ; COPY DATA FROM USER TO SYSTEM ; MOVC3 IRP$W_BCNT(R3),(R0),(R2); MOVE CHARACTERS TO SYSTEM SPACE POPR #^M ; RESTORE REGISTERS ; ; MAKE FINAL QUOTA CHECKS INTERLOCKED WITH DRIVER WRITERS ; ; THESE CHECKS MUST BE MADE AT DRIVER FORK LEVEL TO PRESERVE THE ; INTEGRITY OF THE QUOTAS. IF THE QUOTA IS EXCEEDED THEN THE PROCESS ; IS PLACED IN A "RSN$_MAILBOX" WAIT STATE. THE PROCEEDURE FOR ; PLACING THE PROCESS IN THE WAIT STATE IS COMPLICATED BY THE ; HIGHER THAN "IPL$_SYNCH" EXECUTION LEVEL. IN THIS CASE IT ; IS OK TO CALL RESOURCE WAIT BECAUSE THE IPL WAS RAISED TO FORK ; LEVEL AND NOT REACHED BECAUSE OF AN INTERRUPT LEVEL FORK. ; ; ; MAIL BOX OVER QUOTA? ; 20$: DSBINT UCB$B_FIPL(R5) ; RAISE TO DRIVER FORK LEVEL ; ; TEST FIRST TO SEE IF ROOM IS AVAILABLE FOR THE MESSAGE ; CMPW IRP$W_BCNT(R3),UCB$W_BUFQUO(R5); MESSAGE FIT? BGTRU 60$ ; IF GTR THEN NO ; ; SEE IF MAILBOX IS FULL ; CMPW UCB$W_MSGCNT(R5),UCB$W_MSGMAX(R5); FULL? BEQL 60$ ; IF EQL THEN YES ; ; QUEUE THE MESSAGE ; PUSHR #^M ; SAVE UCB ADDRESS AND PACKET BSBB INSMBQUEUE ; INSERT THE MESSAGE POPR #^M ; RESTORE UCB ADDRESS AND PACKET ENBINT ; LOWER IPL ; ; SEE IF WRITE I/O GETS COMPLETED NOW ; BBS #IO$V_NOW,IRP$W_FUNC(R3),50$; BR IF WRITE NOW BRW EXE$QIORETURN ; RETURN TO CALLER ; ; FINISH WRITE I/O OPERATION ; 50$: MOVL IRP$W_BCNT-2(R3),R0 ; GET TRANSFER COUNT MOVW #SS$_NORMAL,R0 ; SET STATUS IN LOW BRW EXE$FINISHIOC ; COMPLETE THE I/O 55$: POPR #^M MOVZBL #RSN$_NPDYNMEM,R1 ; SET RESOURCE TO AWAIT BRB 65$ ; 60$: MOVL R2,R0 ; DEALLOCATE MESSAGE BLOCK PUSHL R3 ; SAVE PACKET BSBW EXE$DEANONPAGED ; POPL R3 ; RESTORE PACKET MOVZBL #RSN$_MAILBOX,R1 ; SET RESOURCE TO AWAIT 65$: SETIPL #IPL$_SYNCH ; UP IPL FOR WAIT BRW EXE$IORSNWAIT ; ENTER WAIT STATE .SBTTL INSERT MESSAGE IN MAILBOX QUEUE ;++ ; INSMBQUEUE - INSERT MESSAGE ON MAILBOX QUEUE ; ; INPUTS: ; ; R2 = ADDRESS OF MESSAGE BLOCK ; R5 = UCB OF MAILBOX ; ; OUTPUTS: ; ; THE MESSAGE IS QUEUED AND IF THE UNIT IS BUSY THEN ; CONTROL IS TRANSFERED TO "FINISHREAD" TO COMPLETE THE ; WAITING READ REQUEST. ;-- INSMBQUEUE: ; INCW UCB$W_MSGCNT(R5) ; ADJUST MESSAGE COUNT SUBW 14(R2),UCB$W_BUFQUO(R5) ; ADJUST BYTE QUOTA BY MESSAGE SIZE .IF NE CA$_MEASURE ; CHECK FOR MEASUREMENT ENABLED INCL PMS$GL_MBWRITES ; COUNT MAILBOX WRITES .ENDC ; ; TEST UNIT BUSY -- IF BUSY FINISH OUTSTANDING READ ; BBS #UCB$V_BSY,UCB$W_STS(R5),FINISHREAD; BRANCH IF BUSY ; ; INSERT MESSAGE IN QUEUE ; INSQUE (R2),@UCB$L_MB_MSGQ+4(R5); INSERT MESSAGE IN QUEUE ; ; DELIVER ALL AST'S WAITING FOR MESSAGES ON THIS MAILBOX ; MOVAB UCB$L_MB_W_AST(R5),R4 ; ADDRESS ATTENTION LIST HEAD BRW COM$DELATTNAST ; DELIVER THE AST'S .SBTTL STARTIO - STARTIO OPERATION ;++ ; STARTIO - START READ OPERATION ON IDLE MAILBOX UNIT ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED WHEN THE UNIT IS NOT BUSY AND THERE IS A ; PACKET TO PROCESS. IF THERE IS ANY MESSAGE WAITING THE READ IS COMPLETED ; OTHERWISE, AN RSB IS DONE LEAVING THE UNIT BUSY AND THE PACKET IN ; LIMBO. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2 = MESSAGE ADDRESS ON TRANSFER TO "FINISHREAD". ; ; OTHERWISE AN RSB IS DONE. ;-- STARTIO: ; REMQUE @UCB$L_MB_MSGQ(R5),R2 ; GET MESSAGE IF ANY FROM QUEUE BVC FINISHREAD ; IF V-CLEAR THEN COMPLETE THE READ MOVAB UCB$L_MB_R_AST(R5),R4 ; ADDRESS LIST OF READER AST'S BRW COM$DELATTNAST ; DELIVER AST'S .SBTTL FINISHREAD - FINISH READ I/O OPERATION ;++ ; FINISHREAD - FINISH READ OPERATION ; ; FUNCTIONAL DECRIPTION: ; ; THIS ROUTINE IS ENTERED WHEN THE UNIT IS BUSY AND A MESSAGE ; IS AVAILABLE. ; THE WAITING READ IS COMPLETED ALONG WITH THE MATCHING WRITE ; REQUEST IF THE WRITE WAS A WAIT TYPE. ; ; INPUTS: ; ; R2 = MESSAGE ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ;-- FINISHREAD: ; MOVL UCB$L_IRP(R5),R3 ; GET CURRENT I/O PACKET MOVL R2,IRP$L_SVAPTE(R3) ; INSERT BLOCK ADDRESS IN PACKET MOVAB 22(R2),(R2)+ ; INSERT ADDRESS OF DATA MOVL IRP$L_MEDIA(R3),(R2)+ ; INSERT USER VIRTUAL ADDRESS TSTL (R2)+ ; PASS TYPE WORD ADDW (R2),UCB$W_BUFQUO(R5) ; ADJUST QUOTA BY MESSAGE BLOCK SIZE CMPW IRP$W_BCNT(R3),(R2) ; REQUEST GTRU ACTUAL? BGTRU 10$ ; IF GTRU THEN MESSAGE SIZE CORRECT MOVW IRP$W_BCNT(R3),(R2) ; OTHERWISE REQUEST SIZE IS CORRECT 10$: ASHL #16,(R2),R0 ; GET SIZE TO UPPER WORD MOVW #SS$_NORMAL,R0 ; ASSUME NORMAL STATUS MOVW (R2)+,IRP$W_BCNT(R3) ; REPLACE ORIGIONAL SIZE WITH CORRECT BNEQ 15$ ; IF NEQ THEN OK MOVW #SS$_ENDOFFILE,R0 ; SET EOF STATUS 15$: DECW UCB$W_MSGCNT(R5) ; ADJUST MESSAGE COUNT PUSHL R3 ; SAVE PACKET OF READER MOVL IRP$L_PID(R3),R1 ; GET READER PID MOVL (R2)+,R3 ; GET WRITER PACKET BEQL 20$ ; IF EQL THEN NONE MOVQ R0,IRP$L_MEDIA(R3) ; SET READ STATUS AND PID OF RECEIVER MOVZBW #SS$_NORMAL,IRP$L_MEDIA(R3); INSURE SUCCESS BSBW COM$POST ; COMPLETE THE I/O 20$: MOVL (R2),-(SP) ; GET WRITER PID MOVL R0,-(SP) ; SAVE STATUS VALUE MOVZBL #RSN$_MAILBOX,R0 ; SET NUMBER OF RESOURCE AVAILABLE BSBW SCH$RAVAIL ; DECLARE IT POPR #^M ; RESTORE REGISTERS REQCOM ; COMPLETE REQUEST!!! .END