.TITLE XMDRIVER - VAX/VMS DMC-11 DRIVER .IDENT /X05/ ; ; COPYRIGHT (C) 1977 ; 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 INCLU- ; SION 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 DMC-11 I/O DRIVER ; ; ABSTRACT: ; ; THIS MODULE CONTAINS THE DMC-11 DRIVER FDT ROUTINES, ; INTERRUPT DISPATCHER, INTERRUPT SERVICE AND FORK ROUTINES. ; ; AUTHOR: ; ; R.HEINEN 24-AUG-77 ;-- ; ; EXTERNAL SYMBOLS ; $ACBDEF ; DEFINE AST CONTROL BLOCKS $CRBDEF ; DEFINE CRB $DYNDEF ; DEFINE DYNAMIC DATA TYPES $EMBDEF ; DEFINE ERROR LOG SYMBOLS $IDBDEF ; DEFINE IDB $IODEF ; DEFINE I/O SYMBOLS $IPLDEF ; DEFINE IPLS $IRPDEF ; DEFINE I/O PACKET $MSGDEF ; DEFINE SYSTEM MESSAGES $PCBDEF ; DEFINE PCB $PRDEF ; DEFINE PROCESSOR CONSTANTS $RSNDEF ; DEFINE RESOURCE NUMBERS $UBADEF ; DEFINE UBA VALUES $UCBDEF ; DEFINE UCB $VADEF ; DEFINE VIRTUAL ADDRESS $XMDEF ; DEFINE DMC DRIVER SYMBOLS $VECDEF ; DEFINE CRB VECTOR ; ; LOCAL SYMBOL DEFINITIONS ; ; ARGUMENT LIST OFFSETS FOR QIO ; P1 = 0 ; ARG #1 ETC. P2 = 4 ; P3 = 8 ; ; ; DMC UCB DEFINITIONS ; $DEFINI .BLKB -76 $DEF UCB$Q_XM_ATTN .BLKQ 1 $DEF UCB$Q_XM_RCVS .BLKQ 1 $DEF UCB$Q_XM_FREE .BLKQ 1 $DEF UCB$Q_XM_CURCV1 .BLKQ 1 $DEF UCB$Q_XM_CURCV2 .BLKQ 1 $DEF UCB$L_XM_ERRFKB .BLKQ 1 $DEF UCB$W_XM_QUOTA .BLKW 1 .BLKB 1 $DEF UCB$B_XM_EIPL .BLKB 1 .BLKL 1 $DEF UCB$L_XM_LSTPRT .BLKL 1 $DEF UCB$L_XM_LSTCSR .BLKL 1 $DEF UCB$L_XM_BASAD .BLKL 1 $DEF UCB$L_XM_AST .BLKL 1 $DEF UCB$W_XM_BASMP .BLKW 1 .BLKW 1 ; ; DMC-11 CSR DEFINITIONS ; ; CHANGE OVER TO 0+ ; _VIELD XM_RCV,0,<- ; DEFINITION FOR RCV CONTROL BLOCK ,- ; BLOCK IN USE BUT IDLE ,- ; HARDWARE RECEIVE IN PROGRESS > _VIELD XM_DS,0,<- ; DEFINITION FOR DEVSTS ,- ; STATUS OF RECEIVES ,- ; TRANSMIT CONTROL I PENDING ,- ; MAILBOX NOTIFIED > _VIELD XM_FC,0,<- ; INTERNAL FUNCTION CODES ,- ; TRANSMIT - REQ. ONLINE ,- ; START PROTOCOL - REQ. OFFLINE ,- ; STOP PROTOCOL - REQ. ONLINE ,- ; CHANGE MODE - REQ. OFFLINE > $DEF XM_I_CSR .BLKW 1 ; INPUT CSR _VIELD XM_I,0,<- ; BIT DEFINITIONS ,- ; REQUEST TYPE ,- ; RECEIVE OR XMIT FLAG <,2>,- ; RESERVED BITS ,- ; REQUEST INTERRUPT ,- ; INTERRUPT ENABLED ,- ; PORT AVAILABLE <,3>,- ; MAINT BITS ,- ; LOOP BACK <,2>,- ; MAINT BITS ,- ; MASTER CLEAR ,- ; RUN > $DEF XM_O_CSR .BLKW 1 ; OUTPUT CSR _VIELD XM_O,0,<- ; BIT DEFINITIONS ,- ; INTERRUPT TYPE ,- ; RECEIVE OR XMIT <,3>,- ; RESERVED BITS ,- ; INTERRUPT ENABLE ,- ; READY > $DEF XM_PORT .BLKW 1 ; DEFINE PORT OFFSET _VIELD XM_E,0,<- ; ERROR WORD DEFINITIONS ,- ; DATA CHECK ,- ; TIMEOUT ,- ; DATA OVERRUN ,- ; ENTER MOP MODE RECEIVED ,- ; LOST DATA ,- ; TRANSFER ERROR ON UBA ,- ; LINE DOWN ,- ; START RECEIVED ,- ; NON EXMEM ,- ; PROCEEDURE ERROR > ; ; DEFINITION OF THE XM DRIVER RECEIVE MESSAGE BLOCK ; .=0 MSG_LINK: .BLKL 2 MSG_BLKSIZE: .BLKW 1 MSG_BLKTYPE: .BLKB 1 MSG_FIPL: .BLKB 1 MSG_UBVA: MSG_FPC: .BLKL 1 MSG_MAP1: MSG_PORT: .BLKL 1 MSG_MAP2: MSG_CSR: .BLKL 1 MSG_DATA: .PSECT WIONONPAGED ; ; LOCAL STORAGE ; ; DRIVER DDT ; XM$DDT:: .LONG STARTIO ; START I/O .LONG 0 ; UNSOLICITED INTERRUPT .LONG FUNCTABLE ; FUNCTION DECESION TABLE .LONG EXT_CANCELIO ; CANCEL I/O, EXTERNAL .LONG REGDUMP ; REGISTER DUMP ROUTINE .WORD 16 ; DIAG BUFFER SIZE .WORD 16+EMB$L_DV_REGSAV ; ERROR LOG ENTRY SIZE ; ; FUNCTION TABLE ; FUNCTABLE: ; FUNCTAB ,- ; LEGAL FUNCTIONS FUNCTAB , ; BUFFERED I/O - READ FUNCTAB XMITFDT,; FUNCTAB RCVFDT,; FUNCTAB SETMODEFDT,; .SBTTL XM$INIT - INITIALIZE DMC-11 UNIT AND UCB ;++ ; XM$INIT - INITIALIZE DMC-11 UNIT AND UCB ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED AT SYSTEM STARTUP TO INITIALIZE THE UNIT UCB ; AND CHECK FOR THE PRESENCE OF THE PHYSICAL UNIT. ; ; INPUTS: ; ; R4 = ADDRESS OF THE UNIT CSR ; R5 = ADDRESS OF THE UNITS IDB ; R9 = ADDRESS OF THE UNIT CRB ; ; OUTPUTS: ; ; R4,R5,R9 ARE PRESERVED ;-- XM$INITIAL:: ; INITIALIZE THE DMC-11 UCB PUSHL R5 ; SAVE IDB ADDRESS MOVZBL IDB$B_UNITS(R5),R3 ; GET NUMBER OF UNITS ON THIS CONTROLLER BEQL 100$ ; IF EQL THEN NONE MOVL IDB$L_UCBLST-4(R5)[R3],R5; GET THE ADDRESS OF THE UCB BEQL 100$ ; IF EQL THEN NONE BSBW RESET_UCB ; INIT THE UCB 100$: POPL R5 ; TSTW (R4) ; SYNCH THE UBA RSB ; RETURN TO INIT PATH .SBTTL XMITFDT - TRANSMIT I/O OPERATION FDT ROUTINE ;++ ; XMITFDT - TRANSMIT I/O OPERATION FDT ROUTINE ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE SETS UP THE INTERNAL FUNCTION CODE FOR TRANSMIT AND ; TRANSFERS CONTROL TO THE EXEC DIRECT I/O WRITE FDT ROUTINE. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = CURRENT PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; ; OUTPUTS: ; ; R3,R4,R5,R6,R7 ARE PRESERVED ; ;-- XMITFDT: ; TRANSMIT FDT ROUTINE INSV #XM_FC_V_WRITE,#IRP$V_FCODE,#IRP$S_FCODE,IRP$W_FUNC(R3) BRW EXE$WRITE ; CONTINUE .SBTTL RCVFDT - RECEIVE I/O OPERATION FDT ROUTINE ;++ ; RCVFDT - RECEIVE I/O OPERATION FDT ROUTINE ; ; FUNCTIONAL DESCRIPTION: ; ; THE SPECIFIED BUFFER IS CHECKED FOR ACCESSIBILITY. THE BUFFER ADDRESS AND COUNT ; ARE SAVED IN THE PACKET. THEN IPL IS SET TO DEVICE FORK IPL AND IF A MESSAGE IS ; AVAILABLE THE OPERATION IS COMPLETED. OTHERWISE THE PACKET IS QUEUED ONTO ; THE WAITING RECEIVE LIST. THE MAILBOX NOTIFIED BIT IS CLEARED. ; ; FOR FUNCTIONS SPECIFING IO$M_NOW, THE I/O IS COMPLETED WITH STATUS EQUAL TO ; SS$_ENDOFILE IF NO MESSAGE IS AVAILABLE WHEN THE TEST IS MADE. ; ; FOR FUNCTIONS SPECIFING IO$M_DSABLMBX THE MAILBOX IS DISABLED. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = ADDRESS OF THE FIRST OPERATION SPECIFIC QIO PARAMETER ; ; OUTPUTS: ; ; R0 = THE STATUS OF THE RECEIVE QIO OPERATION ; R3 = I/O PACKET ADDRESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = ADDRESS OF THE FIRST OPERATION SPECIFIC PARAMETER ; ;-- RCVFDT: ; READ OPERATION FDT MOVL P1(AP),R0 ; GET USER BUFFER ADDRESS MOVZWL P2(AP),R1 ; BSBW EXE$READCHK ; CHECK THE BUFFER ; NO RETURN ON 0 SIZE OR NO ACCESS SETIPL UCB$B_FIPL(R5) ; RAISE IPL TO LOCK DATA BASE BICW #XM_DS_M_NOTIF,UCB$W_DEVSTS(R5); CLEAR NOTIFIED STATUS BBC #IO$V_DSABLMBX,IRP$W_FUNC(R3),10$; BR IF NO DISABLE MAILBOX BICW #XM$M_STS_MBX,UCB$L_DEVDEPEND(R5); DISABLE MAILBOX 10$: REMQUE @UCB$Q_XM_ATTN(R5),R2 ; DEQUEUE A RECEIVED MESSAGE BVS 15$ ; IF V-SET THEN NONE MOVZBL #SS$_NORMAL,R0 ; SET TRANSFER STATUS BSBW FINISHRCVQIO ; MATCH THE RECEIVE WITH THE MESSAGE BRB 20$ ; RETURN TO CALLER 15$: BBS #IO$V_NOW,IRP$W_FUNC(R3),25$; BR IF READ NOW INSQUE (R3),@UCB$Q_XM_RCVS+4(R5); PUT PACKET ON WAITING LIST 20$: MOVZBL #SS$_NORMAL,R0 ; SET QIO STATUS BRW EXE$QIORETURN ; RETURN TO CALLER 25$: BSBW IOC$DIAGBUFILL MOVZWL #SS$_ENDOFFILE,R0 ; SET END OF FILE ERROR MOVL UCB$L_DEVDEPEND(R5),R1 ; SET SECOND STATUS BRW EXE$FINISHIO ; COMPLETE THE REQUEST .SBTTL SETMODEFDT - SET MODE I/O OPERATION FDT DISPATCH ROUTINE ;++ ; SETMODEFDT - SET MODE FDT PROCESSING ; ; FUNCTIONAL DESCRIPTION: ; ; THIS IS THE FDT ROUTINE FOR SETMODE FUNCTIONS. THERE ARE THREE FUNCTIONS BASED ON ; SUBFUNCTION MODIFIER BIT. ; ; 1) CHANGE MODE -- NO MODIFIER BIT. ; THIS FUNCTION IS DONE IN THE STARTIO ROUTINE. CONTROL IS PASSED TO ; EXE$SETMODE TO VALIDATE THE NEW MODE BUFFER AND QUEUE THE PACKET. ; ; 2) INITIALIZE THE UNIT -- IO$M_STARTUP SET. ; THIS FUNCTION IS DONE PARTIALLY HERE AND THE REMAINDER IS DONE IN STARTIO. ; THE ACTION HERE IS TO PICK UP THE USER BUFFERED I/O QUOTA AND ALLOCATE ; THE BASE TABLE. THE BASE TABLE ADDRESS IS SAVED IN IRP$L_SVAPTE. THE QUOTA ; TAKEN FROM THE USER IS IN IRP$W_BCNT. THIS VALUE WILL BE THE IOSB+2 VALUE ; AT I/O DONE. THIS FUNCTION IS COMPLETE WHEN THE BASE TABLE HAS BEEN GIVEN ; TO THE UNIT. THE MAILBOX IS ENABLED AND A RECEIVE IS STARTED. ; ; 3) SHUTDOWN UNIT -- IO$M_SHUTDOWN SET. ; THIS FUNCTION SHUTS DOWN THE UNIT AND OPTIONALLY RESETS THE MODE. ; A CANCEL I/O IS PREFORMED, ALL OUTSTANDING I/O IS COMPLETED, THE BASE ; TABLE AND MESSAGE BLOCKS ARE ALL RETURNED AND THE UNIT IS LEFT IN AN IDLE ; STATE. THIS FUNCTION CANNOT BE DONE HERE AND THE FDT PROCESSING IS ; THAT OF ALL SETMODE OPERATIONS. ; ; 4) REQUEST ATTENTION AST -- IO$M_ATTNAST ; THIS FUNCTION SETS UP A AST TO BE DELIVERED ON ONE OF THE FOLLOWING ; CONDITIONS: ; ; FATAL ERROR THAT CAUSED SHUTDOWN. ; MESSAGE AVAILABLE TO BE RECEIVED. ; ; ; INPUTS: ; ; R3 = I/O PACKET ADDESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; AP = ADDRESS OF THE FIRST QIO PARAMETER ; ; OUTPUTS: ; ; R3 = I/O PACKET ADDRESS ; R4 = PCB ADDRESS ; R5 = UCB ADDRESS ; R6 = CCB ADDRESS ; R7 = FUNCTION CODE ; ;-- SETMODEFDT: ; SET MODE FDT PROCESSING MOVW IRP$W_FUNC(R3),R7 ; GET ENTIRE FUNCTION CODE BBS #IO$V_ATTNAST,R7,10$ ; BR IF AST REQUEST BBS #IO$V_STARTUP,R7,20$ ; BR IF STARTUP FUNCTION MOVZBW #XM_FC_V_CHANGE,IRP$W_FUNC(R3); ASSUME MODE CHANGE BBC #IO$V_SHUTDOWN,R7,5$ ; BR IF NOT SHUTDOWN OF UNIT MOVZBW #XM_FC_V_STOP,IRP$W_FUNC(R3); SET INTERNAL FUNCTION CODE 5$: BRW EXE$SETMODE ; PROCESS IN EXEC COMMON 10$: MOVAB UCB$L_XM_AST(R5),R7 ; SET ADDRESS OF CONTROL BLOCK LIST BSBW COM$SETATTNAST ; SET UP ATTENTION AST DSBINT UCB$B_FIPL(R5) ; CHECK FOR MESSAGES AVAILABLE MOVAB UCB$Q_XM_ATTN(R5),R0 ; ADDRESS LIST HEAD FOR MESSAGES CMPL R0,UCB$Q_XM_ATTN(R5) ; EMPTY LIST? BEQL 15$ ; IF EQL THEN YES PUSHL R3 ; SAVE PACKET BSBW DEL_ATTN_AST ; DELIVER THE AST POPL R3 15$: BRW EXE$FINISHIOC ; COMPLETE THE I/O ; ; FDT ROUTINE FOR UNIT INIT ; 20$: MOVZBW #XM_FC_V_START,IRP$W_FUNC(R3); INSERT INTERNAL FUNCTION CODE MOVL P1(AP),R2 ; ADDRESS MODE DATA MOVZWL #SS$_ACCVIO,R0 ; ASSUME ACCESS VIOLATION ON BUFFER IFNORD #8,(R2),100$ ; BR IF NOT READABLE MOVQ (R2),IRP$L_MEDIA(R3) ; SAVE DATA IN PACKET MOVZBL P3(AP),R1 ; GET NUMBER OF MESSAGES TO ALLOCATE MOVZWL 2(R2),R2 ; GET THE MESSAGE SIZE MOVZWL #SS$_BADPARAM,R0 ; ASSUME BAD PARAMETER MULW R2,R1 ; GET NEEDED QUOTA BVS 100$ ; IF V-SET THE OVERFLOW ADDW #256,R1 ; ADD IN BASE TABLE SIZE BVS 100$ ; IF V-SET THEN OVERFLOW MOVL R1,R7 ; COPY QUOTA TAKEN PUSHL R3 ; SAVE PACKET ADDRESS BSBW EXE$BUFFRQUOTA ; CHECK QUOTA BLBC R0,100$ ; BR IF ERROR MOVZWL #256,R1 ; ALLOCATE THE BASE TABLE BSBW EXE$ALONONPAGED ; ALLOCATE THE MEMORY POPR #^M ; BRING BACK PACKET ADDRESS BLBC R0,110$ ; ENTER RESOURCE WAIT STATE FOR MEMORY MOVW R7,IRP$W_BOFF(R3) ; SAVE AS QUOTA FOR THIS I/O SUBW R7,PCB$W_BYTCNT(R4) ; ADJUST QUOTA MOVL R2,IRP$L_SVAPTE(R3) ; SAVE BASE TABLE ADDRESS MOVW #256,8(R2) ; SET UP AS BUFFERED I/O BLOCK CLRQ (R2) ; WITH NO DATA BISW #IRP$M_BUFIO,IRP$W_STS(R3); FAKE A BUFFERED I/O BICW #IRP$M_FUNC,IRP$W_STS(R3); SET WRITE DIRECTION BRW EXE$QIODRVPKT ; GIVE PACKET TO DRIVER 100$: POPL R3 ; RESTORE PACKET BRW EXE$ABORTIO ; ABORT THE I/O ; ; MEMORY ALLOCATION FAILURE ; 110$: MOVZBL #RSN$_NPDYNMEM,R0 ; SET RESOURCE TO AWAIT SETIPL #IPL$_SYNCH ; RAISE IPL BRW EXE$IORSNWAIT ; RESTART I/O .SBTTL STARTIO - START XMIT OR SETMODE I/O OPERATION ;++ ; STARTIO - START XMIT OR SETMODE OPERATION ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED WHEN THE UNIT IS IDLE AND THERE IS A PACKET AVAILABLE ; TO PROCESS. IN THE CASE OF SETMODE, THE FUNCTION CODE HAS BEEN CLEARED TO ; SPEED UP THE FUNCTION DISPATCH. ; ; XMIT FUNCTIONS -- ; ; THE ACTION IS TO SET UP THE UBA MAP AND DATA PATH AND REQUEST ; THE CONTROL IN INTERRUPT. THE UNIT MUST BE IN A RUN STATE. ; ; SETMODE FUNCTIONS -- ; ; FOR ALL FUNCTIONS A CHANGE IN THE CHARACTERISTICS IS DONE. ; ; FOR STARTUP, THE ACTION IS TO REQUEST AND SET UP THE UBA ; MAP AND DATAPATH FOR THE BASE TABLE AND RECEIVES. THIS DATA IS SAVED ; AFTER ALLOCATION IN THE UCB. AFTER THIS A BASEIN IS REQUESTED AND ; WHEN IT COMPLETES, THE I/O IS COMPETED. ; ; FOR SHUTDOWN, THE ACTION IS TO MASTER CLEAR THE UNIT AND TRANSFER CONTOROL ; TO THE SHUTUP UNIT ROUTINE WHICH COMPLETES ALL OUTSTANDING I/O AND DELEATES ; THE ALLOCATED BUFFERS AS IF A FATAL ERROR HAD OCCURED. ; ; INPUTS: ; ; R3 = PACKET ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; NONE ;-- STARTIO: ; START SETMODE OR XMIT OPERATION MOVL UCB$L_DEVDEPEND(R5),R1 ; GET STATUS AND CHARACTERISTICS CLRL R2 ; ASSUME UNIT NEED NOT BE ACTIVE BLBS IRP$W_FUNC(R3),10$ ; BR IF NOT EVEN - NOT ACTIVE INCL R2 ; MUST BE ACTIVE 10$: CMPZV #XM$V_STS_ACTIVE,#1,R1,R2; CHECK STATUS - ACTIVE? BNEQ 20$ ; IF NEQ THEN DEVICE NOT READY BICB3 #^X0C0,IRP$W_FUNC(R3),R1; GET XM FUNCTION ALONE CASE R1,TYPE=B, ; ; DEVICE NOT READY ; 20$: MOVZWL #SS$_DEVACTIVE,R0 ; SET DEVICE ACTIVE TSTB R2 ; EXPECT ON OR OFF BEQL 30$ ; IF EQL THEN ACTIVE AND SHOULD BE IDLE MOVZWL #SS$_DEVOFFLINE,R0 ; SET DEVICE NOT ON LINE 30$: REQCOM ; COMPLETE REQUEST .SBTTL XMIT - START XMIT I/O ;++ ; XMIT - START XMIT I/O ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED TO START A TRANSMIT I/O OPERATION. THE MAP REGISTERS ; AND DATA PATH HAVE BEEN ALLOCATED. PRIOR TO STARTING THE I/O THE ACTUAL ; TRANSFER REQUEST SIZE IS ADJUSTED TO REFLECT THE LINE'S MAX MESSAGE SIZE. ; ; INPUTS: ; ; R3 = I/O PACKET FOR TRANSMIT FUNCTION ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; CONTROL IS PASSED TO RQSTXMITSTRT. ; ; R4 = CSR ADDRESS ; R5 = UCB ADDRESS ;-- XMIT: ; START TRANSMIT I/O BBC #IO$V_ENABLMBX,IRP$W_FUNC(R3),10$; BR IF MAILBOX NOT TO BE ENABLED BBSS #XM$V_STS_MBX,UCB$L_DEVDEPEND(R5),10$; ENABLE MAILBOX 10$: BSBW IOC$REQMAPREG ; REQUEST MAP REGISTER FOR OPERATION BSBW IOC$REQDATAP ; REQUEST DATA PATH MOVL IRP$W_BOFF(R3),IRP$L_MEDIA(R3); MOVE OFFSET AND SIZE CMPW UCB$W_DEVBUFSIZ(R5),IRP$L_MEDIA+2(R3); REQUEST SIZE IN RANGE? BGEQU 15$ ; IF GEQU THEN OK MOVW UCB$W_DEVBUFSIZ(R5),IRP$L_MEDIA+2(R3) 15$: MOVL UCB$L_CRB(R5),R2 ; ADDRESS CRB INSV CRB$L_INTD+VEC$W_MAPREG(R2),- #9,#7,IRP$L_MEDIA(R3); INSERT MAP REGISTER IN ADDRESS EXTZV #7,#2,CRB$L_INTD+VEC$W_MAPREG(R2),R2; GET HIGH TWO BITS INSV R2,#30,#2,IRP$L_MEDIA(R3); INSERT HIGH BITS BSBW IOC$LOADUBAMAP ; LOAD THE UBA FOR TRANSFER BRW RQSTXMITSTRT ; SET STATE TO REQUEST XMIT START .SBTTL START - START UNIT ;++ ; START - START PROTOCOL ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE INITIATES PROTOCOL ON THE UNIT. THE ACTION IS TO ALLOCATE ; THE MAPS AND DATAPATHS FOR THE BASE TABLE AND RECEIVES. ONCE THIS IS DONE, ; THE UNIT IS MASTER CLEARED AND THE BASE TABLE AND MODE ARE SET UP. ; THE THE FREE LIST IS FILLED AND THE FIRST RECEIVE STARTED. ; ; IF A FAILURE OCCURS THE UNIT SHUTDOWN SEQUENCE IS ENTERED. ; ; INPUTS: ; ; R3 = I/O PACKET ; R5 = UCB ADDRESS ; ; IMPLICIT INPUTS: ; ; IRP$L_MEDIA CONTAINS A COPY OF THE MODE BUFFER SPECIFIED BY THE USER. ; IRP$L_SVAPTE CONTAINS THE ADDRESS OF THE ALLOCATED BASE TABLE. ; IRP$W_BOFF CONTAINS THE QUOTA TAKEN FROM THE USER FOR THE UNIT. ; ; OUTPUTS: ; ; THE REQUEST IS COMPETED. ;-- START: ; START PROTOCOL OPERATION BSBW CHANGE_MODE ; INSERT NEW CHARACTERISTICS SUBW3 #256,IRP$W_BOFF(R3),UCB$W_XM_QUOTA(R5); CALC AND SAVE FREE LIST QUOTA MOVL IRP$L_PID(R3),UCB$L_PID(R5); SAVE STARTER'S PID ; ; IF THE I/O PACKET QUOTA ADJUSTMENT IS ZEROED, THEN THE QUOTA IS CONSISTENT ; CLRW IRP$W_BOFF(R3) ; SET NO QUOTA CHANGE ON THIS I/O ; ; SAVE UCB MAP AND DATA PATH INFO. THIS DATA IS USED IN TRANSMIT FUNCTIONS ; IF THE DATA SHOWS THAT THIS UNIT IS PERMANENTLY ALLOCATED DATA PATH 0 ; THEN NO ALLOCATION TAKES PLACE ; MOVL IRP$L_SVAPTE(R3),UCB$L_XM_BASAD(R5); SAVE ADDRESS OF THE BASE TABLE CLRL IRP$L_SVAPTE(R3) ; SET NO BLOCK FOR I/O POST MOVW UCB$W_DEVBUFSIZ(R5),UCB$W_BCNT(R5); SET UP TO ALLOCATE THE RECEIVE MAPS MOVW #511,UCB$W_BOFF(R5) ; SET WORST CASE PAGE CROSS MOVL UCB$L_CRB(R5),R4 ; ADDRESS UNIT CRB MOVW CRB$L_INTD+VEC$W_MAPREG(R4),UCB$L_XM_ERRFKB(R5); SAVE XMIT MAP AND DP DATA MOVB CRB$L_INTD+VEC$B_DATAPATH(R4),UCB$L_XM_ERRFKB+4(R5) CMPB #1@VEC$V_PATHLOCK,CRB$L_INTD+VEC$B_DATAPATH(R4); PERM DP=0? BEQL 50$ ; IF EQL THEN NO MORE ALLOCATION NEEDED CLRB CRB$L_INTD+VEC$B_DATAPATH(R4); RESET DATA BSBW IOC$REQDATAP ; REQUEST DATA PATH FOR FIRST RECEIVE BLOCK MOVB CRB$L_INTD+VEC$B_DATAPATH(R4),UCB$Q_XM_CURCV1(R5); SAVE DP NUMBER BSBW IOC$REQDATAP ; REQUEST DATA PATH FOR SECOND RECEIVE BLOCK MOVB CRB$L_INTD+VEC$B_DATAPATH(R4),UCB$Q_XM_CURCV2(R5); SAVE DP NUMBER ; ; ALLOCATE MAP REGISTERS FOR RECEIVE BLOCKS AND BASE TABLE. THE BASE TABLE ; IS MAPPED USING DATA PATH 0 ; 50$: CLRW CRB$L_INTD+VEC$W_MAPREG(R4); SET NO MAP ALLOCATED BSBW IOC$REQMAPREG ; REQUEST THE MAP REGISTERS MOVW CRB$L_INTD+VEC$W_MAPREG(R4),UCB$Q_XM_CURCV1+2(R5); SAVE DATA BSBW IOC$REQMAPREG ; REQUEST OTHER SET MOVW CRB$L_INTD+VEC$W_MAPREG(R4),UCB$Q_XM_CURCV2+2(R5); SAVE DATA ; ; MAP BASE TABLE ; EXTZV #0,#9,UCB$L_XM_BASAD(R5),UCB$W_BOFF(R5); GET PAGE OFFSET FOR BASE TABLE MOVW #256,UCB$W_BCNT(R5) ; SET SIZE BSBW IOC$REQMAPREG ; REQUEST MAP REGISTER FOR BASE TABLE MOVW CRB$L_INTD+VEC$W_MAPREG(R4),UCB$W_XM_BASMP(R5) EXTZV #0,#VEC$V_MAPLOCK,UCB$W_XM_BASMP(R5),R2; GET MAP REG NUMBER MOVL @CRB$L_INTD+VEC$L_ADP(R4),R1; ADDRESS ADAPTER MOVAL UBA$L_MAP(R1)[R2],R2 ; ADDRESS MAP REGISTER SET EXTZV #VA$V_VPN,#VA$S_VPN,UCB$L_XM_BASAD(R5),R1; GET VPN FROM BUFFER ADDRESS MOVAL @MMG$GL_SPTBASE[R1],R1 ; ADDRESS SYSTEM PAGE TABLE BASE MOVL (R1)+,R3 ; START WITH PTE BLSS 55$ ; IF LSS THEN VALID BSBW IOC$PTETOPFN ; GET VALID PTE 55$: INSV #^X0400,#21,#11,R3 ; INSERT UBA BITS MOVL R3,(R2)+ ; LOAD MAP MOVL (R1)+,R3 ; START WITH PTE BLSS 60$ ; IF LSS THEN VALID BSBW IOC$PTETOPFN ; GET VALID PTE 60$: INSV #^X0400,#21,#11,R3 ; INSERT UBA BITS MOVL R3,(R2) ; LOAD MAP MOVZWL UCB$W_BOFF(R5),R1 ; GET OFFSET OF BASE TABLE INSV CRB$L_INTD+VEC$W_MAPREG(R4),#9,#7,R1; EXTZV #7,#2,CRB$L_INTD+VEC$W_MAPREG(R4),R0; GET HIGH TWO BITS INSV R0,#30,#2,R1 ; INSERT IN RESULT MOVW UCB$L_XM_ERRFKB(R5),CRB$L_INTD+VEC$W_MAPREG(R4) MOVB UCB$L_XM_ERRFKB+4(R5),CRB$L_INTD+VEC$B_DATAPATH(R4) MOVL @CRB$L_INTD+VEC$L_IDB(R4),R4; GET THE CSR DSBINT UCB$B_DIPL(R5) ; LOCK OUT INTERRUPTS FROM DEVICE MOVW #XM_I_M_MASTCLR,(R4) ; MASTER CLEAR THE UNIT CLRW 2(R4) ; CLRW 4(R4) CLRW 6(R4) BSBW SYNCH_UNIT ; LOOP TO AWAIT SYNC BBC #XM$V_CHR_LOOPB,UCB$L_DEVDEPEND(R5),70$; BR IF NO LOOP BACK BISW #XM_I_M_LOOPB,(R4) ; SET LOOP BACK BSBW SYNCH_UNIT ; AWAIT UNIT 70$: BISW #XM_I_M_RQSTI!3,(R4) ; REQUEST BASE IN BISW #XM_I_M_RQSTI!3,(R4) ; REQUEST BASE IN BSBB SYNCH_UNIT ; AWAIT UNIT BITW #^X080,(R4) ; READY? BEQL 100$ ; IF EQL THEN NO MOVW R1,XM_PORT(R4) ; INSERT DATA ASHL #-16,R1,R1 ; ADJUST FOR OTHER WORD MOVW R1,XM_PORT+2(R4) ; INSERT BSBW SYNCH_UNIT ; AWAIT UNIT BICW #XM_I_M_RQSTI,(R4) ; FREE PORT BSBW SYNCH_UNIT ; AWAIT UNIT BISW #XM_I_M_RQSTI!1,(R4) ; REQUEST CONTROL I BISW #XM_I_M_RQSTI!1,(R4) ; REQUEST CONTROL I BSBB SYNCH_UNIT ; AWAIT UNIT BITW #^X080,(R4) ; READY? BEQL 100$ ; IF EQL THEN NO CLRW XM_PORT(R4) BICW3 #^C,- UCB$L_DEVDEPEND(R5),XM_PORT+2(R4); SET MODE DATA BICW #XM_I_M_RQSTI,(R4) ; FREE PORT BSBB SYNCH_UNIT ; SYNCH THE UNIT BISW #XM_I_M_INTEN,(R4) ; ENABLE INTERRUPT BISW #XM_I_M_INTEN,2(R4) ; ENABLE INTERRUPT MOVW XM_I_CSR(R4),UCB$L_XM_LSTCSR(R5); SAVE CSR AND PORT MOVW XM_O_CSR(R4),UCB$L_XM_LSTCSR+2(R5); MOVW XM_PORT(R4),UCB$L_XM_LSTPRT(R5); MOVW XM_PORT+2(R4),UCB$L_XM_LSTPRT+2(R5); BISB #3,UCB$W_DEVSTS(R5) ; SET BOTH BLOCKS AVAIL FOR RECEIVE ENBINT ; RETURN TO FORK IPL BSBW FILLFREELIST ; FILL THE FREE LIST AND START THE FIRST RECEIVE MOVL UCB$L_IRP(R5),R3 ; GET THE CURRENT PACKET BISW #XM$M_STS_ACTIVE,UCB$L_DEVDEPEND(R5); SET DEVICE ACTIVE BRW REQNORMAL ; COMPLETE THE REQUEST ; ; ERROR IN STARTING DEVICE ; 100$: ; ENBINT ; ENABLE INTERRUPTS BRB STOP ; SHUT THE UNIT DOWN ; ; WAIT ROUTINE ; ; THE STACK CONTAINS A RETURN ADDRESS AND AN IPL ; SYNCH_UNIT: SETIPL 4(SP) ; RE-ENABLE INTERRUPTS MOVZWL #^X0400,R0 ; SET LOOP COUNT 10$: SOBGTR R0,10$ SETIPL UCB$B_DIPL(R5) ; RESET IPL RSB ; AND RETURN .SBTTL CHANGE MODE AND CHARACTERISTIC DATA ;++ ; CHANGE - CHANGE MODE AND CHARACTERISTICS FUNCTION PROCESSING ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED FOR CHANGING THE MODE AND CHARACTERISTICS ON AN IDLE ; UNIT: ; ; INPUTS: ; ; R3 = ADDRESS OF THE PACKET ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; THE I/O IS COMPLETED VIA REQNORMAL ;-- CHANGE: BSBB CHANGE_MODE ; INSERT NEW DATA BRW REQNORMAL ; COMPLETE CHANGE_MODE: MOVL IRP$L_MEDIA+2(R3),UCB$W_DEVBUFSIZ(R5); INSERT NEW BUFFER SIZE AND MODE RESET_UCB: ; RESET UCB DATA STORAGE MOVAB UCB$Q_XM_RCVS(R5),UCB$Q_XM_RCVS(R5); SET UP EMPTY RECEIVE LIST MOVAB UCB$Q_XM_RCVS(R5),UCB$Q_XM_RCVS+4(R5); CLRL UCB$L_XM_AST(R5) ; SET EMPTY ATTN AST LIST MOVAB UCB$Q_XM_FREE(R5),UCB$Q_XM_FREE(R5); SET UP EMPTY FREE LIST MOVAB UCB$Q_XM_FREE(R5),UCB$Q_XM_FREE+4(R5); MOVAB UCB$Q_XM_ATTN(R5),UCB$Q_XM_ATTN(R5); SET UP EMPTY ATTN LIST MOVAB UCB$Q_XM_ATTN(R5),UCB$Q_XM_ATTN+4(R5); CLRL UCB$L_XM_BASAD(R5) ; NO BASE TABLE CLRW UCB$L_DEVDEPEND+2(R5) ; NO ERROR STATE CLRB UCB$L_DEVDEPEND+1(R5) ; SET NO STATUS CLRW UCB$W_DEVSTS(R5) ; CLRW UCB$W_XM_QUOTA(R5) ; SET NO ASSOCIATED QUOTA CLRQ UCB$Q_XM_CURCV1(R5) ; RESET BOTH CURRENT RCV CONTROL BLOCKS CLRQ UCB$Q_XM_CURCV2(R5) MOVB UCB$B_FIPL(R5),UCB$B_XM_EIPL(R5) RSB .SBTTL STOP - SHUT DOWN UNIT I/O FUNCTION ;++ ; STOP - SHUT DOWN UNIT FUNCTION PROCESSING ; ; FUNCTIONAL DESCRIPTION: ; ; THIS FUNCTION SHUTS THE UNIT DOWN, RETURNING ALL BUFFERS, CANCELLING I/O ; AND STOPING THE PROTOCOL. ; ; INPUTS: ; ; R3 = I/O PACKET ADDRESS ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; I/O COMPLETED VIA REQNORMAL ;-- STOP: ; SHUT DOWN UNIT BICW #UCB$M_BSY,UCB$W_STS(R5); SET NOT BUSY TO AVOID THIS BEING CANCELED BSBW SHUTDOWN ; SHUT DOWN THE UNIT MOVL UCB$L_IRP(R5),R3 ; RESTORE PACKET ADDRESS BSBB CHANGE_MODE ; CHANGE MODE BRW REQNORMAL ; COMPLETE FUNCTION .SBTTL XM$ACPRCV - PRIVILEGED RECEIVE SUBROUTINE ;++ ; XM$ACPRCV - ENTRY FOR PRIVILEGED SOFTWARE TO RECEIVE MESSAGES ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED BY PRIVILEGED SOFTWARE TO RECEIVE MESSAGES ; WITHOUT PERFORMING READ QIO'S. THE NEXT AVAILABLE MESSAGE BLOCK ; IS TAKEN FROM THE ATTENTION QUEUE AND GIVEN TO THE CALLER. THE SIZE ; AND OFFSET TO THE DATA ARE SETUP IN BLOCK+12 AND +14. ; ; INPUTS: ; ; R5 = ADDRESS OF THE UCB ; ; KERNEL MODE AT ANY IPL LOWER THAN DEVICE FORK IPL. ; ; OUTPUTS: ; ; R0 = 0 IF NO BLOCK , 1 IF FOUND ; R2 = BLOCK ADDRESS IF FOUND ; R5 = UCB ADDRESS ; ; R1,R3,R4 ARE PRESERVED. ;-- XM$ACPRCV:: ; PUSHR #^M ; SAVE REGISTERS DSBINT UCB$B_FIPL(R5) CLRL R0 ; ASSUME NO RETURN REMQUE @UCB$Q_XM_ATTN(R5),R2 ; GET A BLOCK BVS 40$ ; IF V-SET THEN NONE ADDW UCB$W_DEVBUFSIZ(R5),UCB$W_XM_QUOTA(R5); ADJUST QUOTA FOR ALLOCATION PUSHL R2 ; SAVE REGISTERS BSBB FILLFREELIST ; FILL FREE LIST AND START RECEIVE POPL R2 ; RESTORE BLOCK ADDRESS MOVZBW #MSG_DATA,14(R2) ; SET UP OFFSET AND DATA SIZE BICW3 #^X0C000,MSG_PORT+2(R2),12(R2); MOVZBL #1,R0 ; SET SUCCESS 40$: ENBINT ; POPR #^M RSB .SBTTL FILLFREELIST - FILL MESSAGE FREE LIST ;++ ; FILLFREELIST - FILL MESSAGE BLOCK FREE LIST ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE FILLS THE MESSAGE FREE LIST UP TO THE QUOTA ALLOCATED ; AT UNIT INITIALIZATION. ; ; INPUTS: ; ; R5 = UCB ; ; OUTPUT: ; ; R5 = UCB ADDRESS ;-- FILLFREELIST: ; FILL FREE LIST CMPW UCB$W_DEVBUFSIZ(R5),UCB$W_XM_QUOTA(R5); ENOUGH SPACE? BGTRU 100$ ; IF GTRU THEN NO, STOP LOOP CLRL R1 ; ZERO SIZE REGISTER ADDW3 #MSG_DATA,UCB$W_DEVBUFSIZ(R5),R1; GET BLOCK SIZE BSBW EXE$ALONONPAGED ; ALLOCATE THE MEMORY BLBC R0,100$ ; IF FAILURE THEN DONE MOVW R1,MSG_BLKSIZE(R2) ; INSERT SIZE MOVB #DYN$C_NET,MSG_BLKTYPE(R2); INSERT TYPE MOVB UCB$B_FIPL(R5),MSG_FIPL(R2); INSERT FUTURE FORK IPL INSQUE (R2),UCB$Q_XM_FREE(R5) ; INSERT BLOCK ON LIST SUBW UCB$W_DEVBUFSIZ(R5),UCB$W_XM_QUOTA(R5); REMOVE BLOCK FROM QUOTA BRB FILLFREELIST ; CONTINUE 100$: TSTB UCB$W_DEVSTS(R5) ; ANY RCV CONTROL BLOCKS AVAIL? BNEQ STARTRECEIVE ; IF NEQ THEN START RECEIVE RSB ; OTHERWISE RETURN .SBTTL STARTRECEIVE - START RECEIVE ON UNIT ;++ ; STARTRECEIVE - START RECEIVE ON IDLE UNIT ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE REMOVES A FREE MESSAGE BLOCK FROM THE FREE LIST AND IF ONE IS ; PRESENT, LOADS THE UBA TO MAP IT AND SETS THE STATE TO REQUEST A RECEIVE START. ; ; INPUTS: ; ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; CONTROL IS PASSED TO RQSTRCVSTRT. ; ; R4 = CSR ADDRESS ; R5 = UCB ADDRESS ;-- STARTRECEIVE: ; START RECEIVE OPERATION FFS #0,#8,UCB$W_DEVSTS(R5),R4; GET FIRST AVAILABLE CONTROL BLOCK BEQL 1$ ; BR IF NO BIT FOUND REMQUE @UCB$Q_XM_FREE(R5),R2 ; REMOVE FREE BLOCK FROM LIST BVC 5$ ; IF V-SET THEN NONE 1$: RSB 5$: BBCC R4,UCB$W_DEVSTS(R5),10$ ; SET RCV CONTROL BLOCK NOT AVAILABLE 10$: MOVAQ UCB$Q_XM_CURCV1(R5)[R4],R4; ADDRESS CONTROL BLOCK MOVL R2,4(R4) ; SAVE BLOCK ADDRESS MOVB #XM_RCV_M_INUS,1(R4) ; SET CONTROL BLOCK INUSE BUT IDLE MOVW UCB$W_DEVBUFSIZ(R5),MSG_UBVA+2(R2); INSERT SIZE MOVAB MSG_DATA(R2),R1 ; ADDRESS BUFFER ITSELF MOVW R1,MSG_UBVA(R2) ; INSERT BUFFER OFFSET INSV 2(R4),#9,#7,MSG_UBVA(R2); INSERT MAP REGISTER DATA EXTZV #7,#2,2(R4),R0 ; GET TWO HIGH BITS INSV R0,#30,#2,MSG_UBVA(R2) ; INSERT IN UBVA ; ; BUILD UBA MAP REGISTER DATA AND LOAD MAP ; EXTZV #0,#VEC$V_MAPLOCK,2(R4),R0; GET MAP REG NUMBER TO START MOVL UCB$L_CRB(R5),R2 ; ADDRESS ADAPTER MOVL @CRB$L_INTD+VEC$L_ADP(R2),R2; MOVAL UBA$L_MAP(R2)[R0],R2 ; ADDRESS MAP IN ADAPTER PUSHL R6 ; MOVZWL UCB$W_DEVBUFSIZ(R5),R6 ; GET NUMBER OF MAPS TO LOAD EXTZV #VA$V_BYTE,#VA$S_BYTE,R1,R0; GET OFFSET OF BUFFER MOVAB ^X01FF(R6)[R0],R6 ; CALC HIGHEST RELITIVE ADDRESS ASHL #-9,R6,R6 ; GET NUMBER OF MAPS TO LOAD MOVZBL (R4),R0 ; GET DATA PATH NUMBER BLBC R1,15$ ; IF LOW CLEAR THEN BYTE ALIGNED BISB #^X040,R0 ; INSERT BYTE BIT FOR UBA 15$: BISW #^X0400,R0 ; SET VALID EXTZV #VA$V_VPN,#VA$S_VPN,R1,R1; GET PTE INDEX OF VA MOVAL @MMG$GL_SPTBASE[R1],R1 ; ADDRESS PTE FOR BUFFER 20$: MOVL (R1)+,R3 ; GET PTE BLSS 25$ ; IF LESS THEN VALID BSBW IOC$PTETOPFN ; VALIDATE IT 25$: INSV R0,#21,#11,R3 ; MERGE UBA DATA BITS MOVL R3,(R2)+ ; LOAD MAP SOBGTR R6,20$ ; CONTINUE UNTIL DONE POPL R6 ; RESTORE REGISTER BRW RQSTRCVSTRT ; START RECEIVE .SBTTL XM$PORTINT - DMC-11 PORT READY INTERRUPT SERVICE ;++ ; XM$PORTINT - DMC-11 PORT READY INTERRUPT SERVICE ; ; FUNCTIONAL DESCRIPTION: ; ; THIS INTERRUPT OCCURS WHEN THE PORT IS READY FOR THE DRIVER TO PASS DATA ; TO THE DMC-11. PRIOR TO THIS, THE REQUEST FOR THE PORT WAS MADE BY ; RQSTRCVSTRT/RQSTXMITSTRT. AFTER THE PORT IS LOADED, IT IS FREED. IF MORE ; RECEIVE BUFFERS ARE FREE THEN ANOTHER PORT LOAD IS REQUESTED. ; ; INPUTS: ; ; 0(SP) = ADDRESS OF THE UNIT IDB ADDRESS ; ; R1,R2,R3,R4,R5 ARE AT 4(SP) ; ; OUTPUTS: ; ; INTERRUPT IS DISMISSED. ;-- XM$PORTINT:: ; DMC11 INPUT PORT AVAILABLE MOVL @(SP)+,R4 ; GET IDB ADDRESS MOVQ (R4),R4 ; R4= CSR, R5= UCB BICB #UCB$M_TIM,UCB$W_STS(R5); CLEAR TIME OUT EXPECTED BBCC #UCB$V_INT,UCB$W_STS(R5),100$; EXIT IF NOT EXPECTED CLRL R3 BICW3 #^X0FFFB,XM_I_CSR(R4),R3; GET THE CSR DATA BEQL 80$ ; IF EQL THEN TRANSMIT MOVAB UCB$Q_XM_CURCV1(R5),R3 ; ADDRESS FIRST CONTROL BLOCK BBS #XM_RCV_V_INUS,1(R3),20$; BR IF FIRST BLOCK AVAIL ADDL #8,R3 ; POINT TO NEXT BLOCK BBC #XM_RCV_V_INUS,1(R3),60$; BR IF THIS BLOCK NOT AVAIL 20$: MOVB #XM_RCV_M_INPR,1(R3) ; SET CONTROL BLOCK IN PROGRESS MOVL 4(R3),R2 ; LOAD PORT MOVW MSG_UBVA(R2),XM_PORT(R4); LOAD PORT MOVW MSG_UBVA+2(R2),XM_PORT+2(R4); 60$: BICW #XM_I_M_RQSTI,XM_I_CSR(R4); FREE PORT BBC #XM_RCV_V_INUS,UCB$Q_XM_CURCV2+1(R5),INTEXIT; IS SECOND BLOCK STILL AVAIL? BSBB RQSTRCVSTRT ; REQUEST RECEIVE START BRB INTEXIT ; CONTINUE 80$: BBCC #XM_DS_V_XMTPND,UCB$W_DEVSTS(R5),100$; CLEAR AND BR IF NOT ASSERTED MOVL UCB$L_IRP(R5),R3 ; GET PACKET ADDRESS MOVW IRP$L_MEDIA(R3),XM_PORT(R4); LOAD PORT MOVW IRP$L_MEDIA+2(R3),XM_PORT+2(R4); 100$: BICW #XM_I_M_RQSTI,XM_I_CSR(R4); FREE PORT INTEXIT: ; EXIT INTERRUPT POPR #^M ; REI ; .SBTTL RQSTRCVSTRT/RQSTXMITSTRT .ENABL LSB ;++ ; RQSTRCVSTRT - REQUEST PORT FOR RECEIVE START ; RQSTXMITSTRT - REQUEST PORT FOR XMIT START ; ; FUNCTIONAL DESCRIPTION: ; ; EACH OF THESE ROUTINES SETS UP THE PROPER PORT DATA, SETS THE STATE BIT, ; SETS THE UNIT IN A WAIT FOR INTERRUPT STATE ( 5 SECOND TIMEOUT ) AND ; REQUESTS THE PORT. ; ; INPUTS: ; ; R5 = UCB ; ; OUTPUTS: ; ; R5 = UCB ;-- RQSTRCVSTRT: ; REQUSET RECEIVE START MOVZBL #XM_I_M_RCV,R2 ; SET UP CSR BRB 50$ ; CONTINUE IN COMMON RQSTXMITSTRT: ; REQUEST XMIT START CLRL R2 ; SET DIRECTION BISW #XM_DS_M_XMTPND,UCB$W_DEVSTS(R5) ; ; SET UP WAIT FOR NEXT INTERRUPT ; 50$: MOVL UCB$L_CRB(R5),R4 ; GET CRB ADDRESS MOVL @CRB$L_INTD+VEC$L_IDB(R4),R4; GET CSR ADDRESS DSBINT UCB$B_DIPL(R5) ; LOCK OUT DEVICE INTERRUPTS BITB #UCB$M_INT,UCB$W_STS(R5); INTERRUPT EXPECTED? BNEQ 120$ ; IF NEQ THEN YES SETIPL #IPL$_POWER ; RAISE TO LOCK OUT ALL INTERRUPTS ADDL3 #5,EXE$GL_ABSTIM,UCB$L_DUETIM(R5); SET UP TIMER BISB #UCB$M_TIM!UCB$M_INT,UCB$W_STS(R5); SET TIMER BBCC #UCB$V_TIMOUT,UCB$W_STS(R5),100$; CLEAR TIMED OUT 100$: BISW #XM_I_M_RQSTI,R2 ; SET UP NEW CSR BISW R2,(R4) ; MAKE REQUEST BISW R2,(R4) ; AND AGAIN 120$: ENBINT ; ENABLE INTERRUPTS RSB ; RETURN .DSABL LSB .SBTTL XM$CTRLINT - DMC11 CONTROL INTERRUPT ;++ ; XM$CNTRLINT - DMC11 CONTROL INTERRUPT ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS THE INTERRUPT SERVICE FOR DMC11 CONTROL INTERRUPTS. ; THE INTERRUPTS CAN SIGNAL RECEIVE OR TRANSMIT BUFFER DONE AND ERRORS. ; ; INPUTS: ; ; 00(SP) = ADDRESS OF UNIT IDB ADDRESS ; ; R1,R2,R3,R4,R5 ARE AT 4(SP) ; ; OUTPUTS: ; ; THE INTERRUPT IS DISMISSED ; ; IMPLICIT OUTPUTS: ; ; IF THE INTERRUPT SIGNALS AN ERROR, ; THE PORT IS HELD AND A FORK IS DONE ON THE UCB CONTEXT ; TO THE ERROR PROCESSING LOGIC. ; ; IF THE INTERRUPT SIGNALS RECEIVE DONE, ; THE PORT IS FREED. ; THE NEXT RECEIVE IS STARTED IF POSSIBLE. ; A FORK IS CREATED USING THE MESSAGE BLOCK TO COMPLETE THE OPERATION. ; ; IF THE INTERRUPT SIGNALS XMIT DONE, ; THE PORT IS FREED. A FORK TO PROCESS THE COMPLETED MESSAGE ; IS DONE ON THE CURRENT I/O PACKET. ;-- XM$CTRLINT:: ; DMC11 CONTROL INTERRUPT MOVL @(SP),R4 ; R4= CSR, R5= UCB MOVQ (R4),R4 ; MOVAB B^INTEXIT,(SP) ; SET UP RETURN ADDRESS MOVW XM_O_CSR(R4),R2 ; GET ENTIRE CSR ASHL #16,R2,R2 ; SHIFT MOVW XM_I_CSR(R4),R2 ; AND LOAD LOW MOVW XM_PORT+2(R4),R3 ; GET ENTIRE PORT ASHL #16,R3,R3 MOVW XM_PORT(R4),R3 ; BITL #<^X03>@16,R2 ; BEQL 10$ ; IF EQL THEN YES 5$: MOVAB UCB$L_XM_ERRFKB(R5),R5 ; ADDRESS FORK BLOCK FOR ERROR FORK PUSHAB W^ERRORFORK ; SET UP FORK PROCESS ADDR MOVL R2,R4 ; SAVE CSR'S AS DATA IN FORK BRW EXE$FORK ; FORK 10$: MOVL R2,UCB$L_XM_LSTCSR(R5) ; SAVE PORT AND CSR MOVL R3,UCB$L_XM_LSTPRT(R5) ; BICW #XM_O_M_READY,XM_O_CSR(R4); FREE DATA PORT BITL #XM_O_M_RCV@16,R2 ; WAS IT XMIT DONE? BEQL 40$ ; IF EQL THEN YES MOVL R3,R1 ; COPY PORT DATA INSV UCB$W_DEVBUFSIZ(R5),#16,#14,R1; RESTORE ORIGINAL DATA MOVAB UCB$Q_XM_CURCV1(R5),R4 ; ADDRESS CONTROL BLOCK BBC #XM_RCV_V_INPR,1(R4),15$; BR IF NOT IN USE MOVL 4(R4),R2 ; ADDRESS BLOCK CMPL R1,MSG_UBVA(R2) ; IS THIS THE BLOCK? BEQL 20$ ; IF EQL THEN YES 15$: MOVAB UCB$Q_XM_CURCV2(R5),R4 ; ADDRESS OTHER CONTROL BLOCK BBC #XM_RCV_V_INPR,1(R4),120$; BR IF NOT IN PROGRESS MOVL 4(R4),R2 ; ADDRESS BLOCK CMPL R1,MSG_UBVA(R2) ; THIS MESSAGE BNEQ 120$ ; IF NEQ THEN NO 20$: CLRB 1(R4) ; FREE CONTROL BLOCK PUSHL R2 ; SAVE BLOCK ADDRESS PUSHR #^M ; SAVE PORT DATA AND UCB MOVZBL (R4),R2 ; GET DATA PATH NUMBER BSBB 200$ ; PURGE DATA PATH AND CHECK FOR ERROR MOVAB UCB$Q_XM_CURCV1(R5),R1 ; ADDRESS BLOCK STARTS SUBL R1,R4 ; GET BLOCK NUMBER BBSS R4,UCB$W_DEVSTS(R5),25$ ; SET CONTROL BLOCK FREE 25$: BSBW STARTRECEIVE ; START A NEW RECEIVE IF POSSIBLE MOVL R5,R4 ; SAVE UCB IN FORK POPR #^M ; R3 = PORT DATA, R4 = UCB, R5 = BLOCK ADDR PUSHAB B^RCVDONEFORK ; SET UP FORK PROCESS ADDR BRW EXE$FORK ; FORK 40$: BITW #UCB$M_BSY,UCB$W_STS(R5); SKIP IF NOT BUSY BEQL 120$ ; IF EQL THEN NOT BUSY MOVL UCB$L_CRB(R5),R1 ; GET DATA PATH USED MOVZBL CRB$L_INTD+VEC$B_DATAPATH(R1),R2; BSBB 200$ ; PURGE DATA PATH AND CHECK FOR ERROR MOVL R5,R4 ; SAVE UCB IN FORK MOVL UCB$L_IRP(R5),R5 ; ADDRESS CURRENT PACKET MOVL R3,IRP$W_BOFF(R5) ; SAVE TRANSFER DATA MOVL IRP$L_PID(R5),IRP$L_MEDIA(R5);SAVE PACKET DATA FROM FORK MOVB IRP$B_RMOD(R5),IRP$L_MEDIA+4(R5); SAVE RMODE MOVB UCB$B_FIPL(R4),IRP$B_RMOD(R5); SET IPL FOR FORK MOVQ IRP$L_AST(R5),R3 ; PUSHAB W^XMITDONEFORK ; XMIT DONE FORK BRW EXE$FORK ; FORK 120$: RSB ; RETURN ; ; PURGE DATA PATH AND CHECK FOR ERROR IN TRANSFER ; 200$: MOVL UCB$L_CRB(R5),R1 ; ADDRESS ADAPTER MOVL @CRB$L_INTD+VEC$L_ADP(R1),R1; ASHL #UBA$V_DPR_BNE,#1,UBA$L_DPR(R1)[R2] ASHL #31-UBA$V_DPR_XMTER,UBA$L_DPR(R1)[R2],R1; ANY ERROR? BGEQ 210$ ; IF GEQ THEN NO MOVL UCB$L_XM_LSTCSR(R5),R2 ; GET LAST CSR ASHL #XM_E_V_TRNER,#1,R3 ; MOVAB W^5$,(SP) ; CHANGE RETURN ADDRESS 210$: RSB .SBTTL RCVDONEFORK - RECEIVE DONE FORK PROCESS ;++ ; RCVDONEFORK - RECEIVE DONE FORK PROCESS ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS ENTERED AT DEVICE FORK LEVEL WHEN A RECEIVE BUFFER DONE ; HAS OCCURED. THE COMPLETED MESSAGE BLOCK IS USED AS THE FORK BLOCK. ; ; INPUTS: ; ; R3 = PORT DATA ; R4 = UCB ADDRESS ; R5 = ADDRESS OF THE MESSAGE BLOCK OR FORK BLOCK ; ; OUTPUTS: ; ; R5 = UCB ADDRESS ; ;-- .WORD RCVTIMEOUT-. RCVDONEFORK: ; RECEIVE DONE FORK MOVL R5,R2 ; COPY ADDRESS OF THE MESSAGE BLOCK MOVL R4,R5 ; RESTORE UCB ADDRESS MOVZBL #SS$_NORMAL,R0 ; SET UP TRANSFER STATUS REMQUE @UCB$Q_XM_RCVS(R5),R3 ; REMOVE WIATING RECEIVE BVC FINISHRCVQIO ; IF FOUND THEN FINISH THE I/O INSQUE (R2),@UCB$Q_XM_ATTN+4(R5); QUEUE MESSAGE BLOCK BITW #XM_DS_M_NOTIF,UCB$W_DEVSTS(R5); ALREADY NOTIFIED? BNEQ 40$ ; IF NEQ THEN YES BITW #XM$M_STS_MBX,UCB$L_DEVDEPEND(R5); ENABLED? BEQL 40$ ; IF EQL THEN NO MOVL UCB$L_AMB(R5),R3 ; ADDRESS MAILBOX BEQL 40$ ; IF EQL THEN NONE MOVZBL #MSG$_XMUNSOLIC,R4 ; SET MESSAGE TYPE BSBW EXE$SNDEVMSG ; SEND MESSAGE BLBC R0,40$ ; IF LOW CLEAR THEN NOT SENT BISW #XM_DS_M_NOTIF,UCB$W_DEVSTS(R5); SET NOTIFIED 40$: BSBW DEL_ATTN_AST ; RSB ; RETURN FROM FORK .SBTTL FINISHRCVQIO - FINISH RECEIVE QIO PROCESSING ;++ ; FINISHRCVQIO - FINISH RECEIVE QIO PROCESSING ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE COMPLETES A RECEIVE OPERATION THAT HAS BEEN MATCHED WITH A ; MESSAGE BLOCK. AFTER THE RECEIVE HAS BEEN COMPLETED THE MESSAGE FREE LIST IS FILLED ; AND A RECEIVE IS STARTED IF NEEDED. ; ; INPUTS: ; ; R0 = STATUS OF THE OPERATION ; R2 = ADDRESS OF MESSAGE BLOCK OR 0 IF THE I/O IS TO ABORTED ; R3 = PACKET ADDRESS OF THE RCV QIO ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R5 = UCB ADDRESS ;-- FINISHRCVQIO: ; FINISH RCV QIO PROCESSING CLRL R1 ; ASSUME NO TRANSFER MOVL R2,IRP$L_SVAPTE(R3) ; INSERT ADDRESS OF THE BUFFERED BLOCK BEQL 10$ ; IF EQL THEN NO MESSAGE BLOCK MOVAB MSG_DATA(R2),(R2) ; SET UP BLOCK FOR DATA MOVE MOVL IRP$L_MEDIA(R3),4(R2) ; INSERT SAVED USER VIRTUAL ADDRESS ADDW UCB$W_DEVBUFSIZ(R5),UCB$W_XM_QUOTA(R5); ADJUST UNIT QUOTA PUSHAB W^FILLFREELIST ; SET UP TRIP THROUGH FREELISTFILL BICW3 #^X0C000,MSG_PORT+2(R2),R1; GET SIZE OF TRANSFER CMPW R1,IRP$W_BCNT(R3) ; REQUEST LARGER THAN ACTUAL? BGTRU COMPLETE_IO ; BR IF NO 10$: MOVW R1,IRP$L_MEDIA+2(R3) ; SAVE TRANSFER COUNT COMPLETE_IO: MOVL UCB$L_DEVDEPEND(R5),IRP$L_MEDIA+4(R3); MOVW R0,IRP$L_MEDIA(R3) ; SET STATUS BBC #IRP$V_DIAGBUF,IRP$W_STS(R3),20$; BR IF NO DIAGNOSTIC BUFFER ADDL3 #8,@IRP$L_DIAGBUF(R3),R0; ADDRESS BUFFER PAST START TIME MOVQ EXE$GQ_SYSTIME,(R0)+ ; INSERT STOP TIME MOVZWL UCB$W_ERRCNT(R5),(R0)+ ; INSERT ERROR COUNTER BSBB REGDUMP ; DUMP REGISTERS 20$: BRW COM$POST ; POST THE I/O .SBTTL XMITDONEFORK - TRANSMIT DONE FORK PROCESS ;++ ; XMITDONEFORK - TRANSMIT DONE FORK PROCESS ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS A FOR PROCESS TO COMPLETE TRANSMIT OPERATIONS. ; THE FORK BLOCK USED IS THE I/O PACKET. ; ; INPUTS: ; ; R3,R4 CONTAIN IRP DATA ; R5 = ADDRESS OF THE FORKBLOCK - I/O PACKET ; ; OUTPUTS: ; ; THE REQUEST IS COMPLETED VIA REQCOM. ;-- .WORD XMTIMEOUT-. XMITDONEFORK: ; TRANSMIT DONE FORK MOVQ R3,IRP$L_AST(R5) ; SAVE FORK DATA MOVL R5,R3 ; COPY BLOCK ADDRESS MOVB IRP$L_MEDIA+4(R3),IRP$B_RMOD(R3); RESTORE MODE MOVL IRP$L_MEDIA(R3),IRP$L_PID(R3); RESTORE PID BICW #^X0C000,IRP$W_BCNT(R3) ; SET UP TRANSFER SIZE BICW #^C,IRP$W_BOFF(R3); RESET I/O POST DATA MOVL IRP$L_UCB(R3),R5 ; GET UCB FOR UNIT BSBW IOC$RELDATAP ; RELEASE DATA PATH BSBW IOC$RELMAPREG ; RELEASE MAP REGISTER REQNORMAL: ; COMPLETE A NORMAL REQUEST BSBW IOC$DIAGBUFILL MOVL IRP$W_BCNT-2(R3),R0 ; SET UP FOR I/O DONE MOVZBW #SS$_NORMAL,R0 ; INSERT STATUS MOVL UCB$L_DEVDEPEND(R5),R1 ; REQCOM ; COMPLETE AND START NEXT .SBTTL TIMEOUT ROUTINES ; ; DEVICE TIMEOUT ROUTINES ; RCVTIMEOUT: MOVL R4,R5 ; GET UCB ADDRESS BRW SHUTDOWN ; SHUTDOWN THE UNIT XMTIMEOUT: MOVL IRP$L_UCB(R5),R5 ; GET THE UCB ADDRESS BRW SHUTDOWN ; SHUT THE UNIT DOWN ERRTIMEOUT: MOVAB UCB$L_XM_ERRFKB(R5),R5 ; GET THE UCB ADDRESS BRW SHUTDOWN ; SHUT THE UNIT DOWN .SBTTL REGDUMP - DMC-11 ERROR LOG AND DIAGNOSTICS REGISTER DUMP ;++ ; REGDUMP - ERROR LOG AND DIAGNOSTICS REGISTER DUMP ROUTINE ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED TO RETURN THE DMC-11 ERROR LOG AND DIAGNOSTICS ; BUFFER ON ERROR OR DIAGNOSTIC QIO FUNCTION. ; ; INPUTS: ; ; R0 = ADDRESS OF THE BUFFER ; R5 = UCB ADDRESS OF THE UNIT ; ; OUTPUTS: ; ; R0,R1 ARE USED ; R5 = UCB ADDRESS OF THE UNIT ;-- REGDUMP: MOVZBL #8,(R0)+ ; INSERT NUMBER OF RETURNED LONG WORDS MOVL UCB$L_XM_LSTCSR(R5),(R0)+; INSERT LAST CSR MOVL UCB$L_XM_LSTPRT(R5),(R0)+; INSERT LAST PORT BBC #XM$V_STS_ACTIVE,UCB$L_DEVDEPEND(R5),20$; BR IF NOT ACTIVE MOVL UCB$L_XM_BASAD(R5),R1 ; ADDRESS UNIT BASE TABLE MOVL 3(R1),(R0)+ ; RETURN 8 BYTES OF ERROR COUNTERS MOVL 7(R1),(R0)+ ; BRB 30$ ; CONTINUE 20$: CLRQ (R0)+ ; RETURN NO ERRORS 30$: CLRQ (R0)+ ; CLRQ (R0) ; RSB .SBTTL ERRORFORK - ERROR FORK RPOCESS ;++ ; ERRORFORK - ERROR PROCESSING FORK ; ; FUNCTIONAL DESCRIPTION: ; ; THIS IS THE FORK PROCESS THAT HANDLES ERRORS ON THE DMC UNIT. ; THE ACTION IS TO SIGNAL THE OWNER PROCESS VIA MAILBOX OR AST OF THE ; ATTENTION CONDITION. AND THEN, IF THE ERROR IS FATAL, SHUT DOWN THE UNIT. ; ; ; INPUTS: ; ; R3 = PRE FORT PORT VALUE ; R4 = PRE FORK CSR VALUE ; R5 = ADDRESS OF THE UCB FORK BLOCK ; ; OUTPUTS: ; ; NONE ;-- .WORD ERRTIMEOUT-. ERRORFORK: ; ERROR PROCESSING FORK MOVAB -UCB$L_XM_ERRFKB(R5),R5 ; ADDRESS UCB BSBW ERL$DEVICERR ; LOG THE ERROR INCW UCB$W_ERRCNT(R5) ; ADJUST COUNT BITW #,UCB$L_XM_LSTPRT+2(R5) BNEQ FATALERROR ; IF NEQ THEN YES BISB UCB$L_XM_LSTPRT+2(R5),UCB$L_DEVDEPEND+1(R5); SAVE DATA BSBB DEL_ATTN_AST ; TELL OWNER MOVL UCB$L_CRB(R5),R1 ; FREE DATA PORT MOVL @CRB$L_INTD+VEC$L_IDB(R1),R1; GET CSR ADDRESS BICW #XM_O_M_READY,XM_O_CSR(R1); RSB ; RETURN ; ; DELIVER ERROR ATTENTION AST'S ; DEL_ATTN_AST: MOVAB UCB$L_XM_AST(R5),R1 ; MOVL R1,R4 ; COPY LIST HEAD ADDRESS 10$: MOVL (R1),R1 ; ADDRESS A BLOCK BEQL 15$ ; IF EQL THEN DONE MOVL UCB$L_DEVDEPEND(R5),ACB$L_KAST+4(R1); CHANGE PARAM BRB 10$ 15$: BRW COM$DELATTNAST ; DELIVER AST'S ; ; FATAL ERROR ; FATALERROR: BICW #XM$M_STS_ACTIVE,UCB$L_DEVDEPEND(R5); CLEAR ACTIVE BICW3 #^C,UCB$L_XM_LSTPRT+2(R5),UCB$L_DEVDEPEND+2(R5) BITW #,UCB$L_XM_LSTPRT+2(R5) BEQL 10$ ; SOFTWARE ERROR? BISB #XM$M_ERR_FATAL@-16,UCB$L_DEVDEPEND+2(R5); SET FATAL ERROR 10$: MOVZBL #MSG$_XMLINEDOWN,R4 ; SEND MESSAGE MOVL UCB$L_AMB(R5),R3 ; ASSOCIATED MAILBOX? BEQL 15$ ; IF EQL THEN NO BSBW EXE$SNDEVMSG ; SEND MESSAGE ; IGNORE ERROR 15$: BSBB DEL_ATTN_AST ; TELL AST HOLDERS .SBTTL SHUTDOWN - SHUT DOWN UNIT ;++ ; SHUTDOWN - SHUT DOWN UNIT ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED TO SHUT DOWN THE DMC UNIT AS A RESULT OF A SETMODE AND STOP ; PROTOCOL OR FATAL ERROR. THE ACTION IS TO PERFORM A CACNEL I/O AND THEN TO ; CLEAN UP THE UNIT DATA BASE. ; ; INPUTS: ; ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R5 = UCB ADDRESS ; ; R0-R4 ARE DISTROYED. ;-- SHUTDOWN: ; SHUT DOWN UNIT MOVL UCB$L_CRB(R5),R4 ; GET UNIT CSR MOVL @CRB$L_INTD+VEC$L_IDB(R4),R4; DSBINT UCB$B_DIPL(R5) ; RAISE TO DEVICE IPL FOR MASTER CLEAR BICW #UCB$M_INT!UCB$M_TIM,UCB$W_STS(R5); SET NO EXPECT OR TIMEOUT BICB #XM$M_STS_ACTIVE@-8,UCB$L_DEVDEPEND+1(R5); SET INACTIVE CLRW (R4) ; MASTER CLEAR THE UNIT TO STOP IT ENBINT ; RETURN TO FORK LEVEL CLRL R2 ; SET TO CANCEL ALL THE I/O BSBW CANCELIO ; CANCEL ALL MOVL UCB$L_XM_BASAD(R5),R0 ; ADDRESS THE BASE TABLE MOVZWL #256,8(R0) ; MAKE IT A REAL MEMORY BLOCK ADDW 8(R0),UCB$W_XM_QUOTA(R5); ADJUST QUOTA BSBW EXE$DEANONPAGED ; DEALLOCATE IT MOVL UCB$L_CRB(R5),R4 ; ADDRESS CRB MOVW UCB$Q_XM_CURCV1+2(R5),CRB$L_INTD+VEC$W_MAPREG(R4); DEALLOCATE THE MAP REGISTER BSBW IOC$RELMAPREG ; MOVW UCB$Q_XM_CURCV2+2(R5),CRB$L_INTD+VEC$W_MAPREG(R4); DEALLOCATE THE MAP REGISTER BSBW IOC$RELMAPREG ; MOVB UCB$Q_XM_CURCV1(R5),CRB$L_INTD+VEC$B_DATAPATH(R4); REALEASE RECEIVE MAP BSBW IOC$RELDATAP ; MOVB UCB$Q_XM_CURCV2(R5),CRB$L_INTD+VEC$B_DATAPATH(R4); REALEASE RECEIVE MAP BSBW IOC$RELDATAP ; MOVW UCB$W_XM_BASMP(R5),CRB$L_INTD+VEC$W_MAPREG(R4) BSBW IOC$RELMAPREG BITB #XM_RCV_M_INPR!XM_RCV_M_INUS,UCB$Q_XM_CURCV1+1(R5); BEQL 5$ ; IF EQL THEN NOT IN USE INSQUE @UCB$Q_XM_CURCV1+4(R5),UCB$Q_XM_FREE(R5) 5$: BITB #XM_RCV_M_INPR!XM_RCV_M_INUS,UCB$Q_XM_CURCV2+1(R5); BEQL 10$ ; IF EQL THEN NOT IN USE INSQUE @UCB$Q_XM_CURCV2+4(R5),UCB$Q_XM_FREE(R5) 10$: REMQUE @UCB$Q_XM_FREE(R5),R0 ; DEALLOCATE THE FREE LIST BVS 20$ ; IF V-SET THEN NONE ADDW 8(R0),UCB$W_XM_QUOTA(R5); ADJUST QUOTA BSBW EXE$DEANONPAGED ; DEALLOCATE THE BLOCK BRB 10$ ; CONTINUE UNTIL DONE 20$: MOVZWL UCB$L_PID(R5),R0 ; GET PID OF LAST STARTER MOVL SCH$AL_PCB[R0],R0 ; GET PCB OF OWNER CMPL PCB$L_PID(R0),UCB$L_PID(R5); STILL THERE? BNEQ 25$ ; IF NOT THEN BR ADDL UCB$W_XM_QUOTA(R5),PCB$W_BYTCNT(R0); RETURN QUOTA 25$: RSB ; RETURN TO CALLER .SBTTL CANCELIO - CANCEL I/O ON UNIT, INTERNAL AND EXTERNAL ;++ ; CANCELIO - CANCEL I/O ON UNIT, INTERNAL ; EXT_CANCELIO - CANCEL I/O ON UNIT, EXTERNAL ; ; FUNCTIONAL DESCRIPTION: ; ; THIS ROUTINE IS USED TO CANCEL SPECIFIC OR ALL I/O PENDING ON A DMC UNIT. ; ; INPUTS: ; ; R2 = CHANNEL NUMBER OR 0 IF CANCEL ALL ; R3 = CURRENT I/O PACKET IF BUSY ; R4 = PCB ADDRESS IF SPECIFIC CANCEL ; R5 = UCB ADDRESS ; ; OUTPUTS: ; ; R2,R3,R4,R5 ARE SAVED ; ;-- EXT_CANCELIO: ; EXTERNAL CANCEL I/O TSTB UCB$W_REFC(R5) ; REF COUNT 0? BNEQ CANCELIO ; IF NEQ THEN STILL ACTIVE BRW SHUTDOWN ; OTHERWISE SHUT THE UNIT DOWN CANCELIO: ; CANCEL I/O MOVZWL #SS$_ABORT,R0 ; ASSUME ABORT AS STATUS BBC #UCB$V_BSY,UCB$W_STS(R5),5$; BR IF NOT BUSY BSBB CHECKPKT ; SEE IF PACKET SHOULD BE CANCELED AND CANCEL BNEQ 5$ ; IF NEQ THEN NO MATCH MOVZWL #SS$_ABORT,R0 ; SET STATUS MOVL UCB$L_DEVDEPEND(R5),R1 ; PUSHR #^M ; SAVE REGISTERS BSBW IOC$REQCOM ; COMPLETE REQUEST POPR #^M ; 5$: MOVAB UCB$Q_XM_RCVS(R5),R1 ; ADDRESS LIST HEAD MOVL (R1),R3 ; GET LIST ENTRY 10$: CMPL R3,R1 ; LIST END? BEQL 20$ ; IF EQL THEN YES PUSHL (R3) ; SAVE LINK TO NEXT BSBB CHECKPKT ; CANCEL IF MATCH BNEQ 15$ ; IF NEQ THEN NO MATCH REMQUE (R3),R3 ; REMOVE ENTRY FROM LIST CLRW IRP$L_MEDIA+2(R3) ; SET NO TRANSFER BSBW COMPLETE_IO ; COMPLETE THE I/O 15$: POPL R3 ; RESTORE LINK BRB 10$ 20$: RSB ; RETURN TO CALLER ; ; SUBROUTINE TO CHECK FOR SPECIFIC CANCEL ; CHECKPKT: TSTL R2 ; ALL? BEQL 30$ ; IF EQL THEN YES - CANCEL CMPL R4,IRP$L_PID(R3) ; PID MATCH? BNEQ 30$ ; IF NEQ THEN NO CMPW R2,IRP$W_CHAN(R3) ; CHANNEL MATCH? 30$: RSB ; RETURN TO CALLER ; .END