.TITLE DADRIVER - VAX/VMS DA11-B DRIVER .IDENT /V01/ ; ; COPYRIGHT (C) 1978 ; 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 THAT IS NOT SUPPLIED BY DEC. ; ;++ ; ; FACILITY: ; ; VAX/VMS DA11-B I/O Driver ; ; ABSTRACT: ; ; This module contains the DA11-B driver: ; ; Tables for loading and dispatching ; A controller initialization routine ; An FDT routine ; The start I/O routine ; The interrupt service routine ; ; AUTHOR: ; ; C. Peters 07-SEP-78 ; ;-- .SBTTL Driver Description ;+ ; Functional specification: ; ; The DA11-B interprocessor link is a DMA data transfer channel between ; 2 VAX-11 processors. The device consists of the following: ; ; 2 DR11-B general purpose DMA interfaces ; 2 M7229 modules and BC08R cables that connect the 2 DR11-Bs ; ; The modules and cables send output signals from 1 DR11-B to the input ; signal connections of the other DR11-B. ; ; The link is a half-duplex channel that transfers data from memory on ; 1 processor to memory on the other processor in blocks of up to 32K ; words. ; ; The driver that follows depends on an outer protocol layer created by ; the application programs that request I/O from the DA11-B. One program ; on each processor drives the DA11-B. Program 1 is the master, and ; begins by initiating a transmit to the second processor. Program 2 is ; the slave, and begins by requesting a receive from the first ; processor. ; ; When Program 1's transmit completes, and consequently Program 2's ; receive completes, the programs reverse roles: i.e., Program 2 ; initiates a transmit and Program 1 requests a receive. ; ; If the application programs are not synchronized, and both request ; transmits or receives simultaneously, both requests time out, and ; the driver returns status of DEV_TIMEOUT to both programs. ; ; The device works as follows: ; ; When a transmit request arrives, the driver sets the GO, ; INTERRUPT ENABLE, and REQUEST INTERRUPT ON OTHER PROCESSOR ; bits in the CSR, and sets the direction to OUTPUT. ; ; When the other processor's driver sets the INTERRUPT ENABLE ; bit in that device's CSR, the driver receives an interrupt. ; That driver then sets the GO, INTERRUPT ENABLE bits in the ; CSR, and sets the direction to INPUT. ; ; When the transmit completes, the device interrupts on both ; processors. Both drivers check for complete transfer and return ; status to the user. Complete transfer is indicated by a zero ; count in the device's word count register. ; ;-- .SBTTL External and local symbol definitions ; ; External symbols ; $CRBDEF ; Channel request block $DDBDEF ; Device data block $IDBDEF ; Interrupt data block $IODEF ; I/O function codes $IPLDEF ; Hardware IPL definitions $IRPDEF ; I/O request packet $UCBDEF ; Unit control block $VECDEF ; Interrupt vector block ; ; Local symbols ; ; ; Argument list (AP) offsets for device-dependent QIO parameters ; P1 = 0 ; First QIO parameter P2 = 4 ; Second QIO parameter P3 = 8 ; Third QIO parameter P4 = 12 ; Fourth QIO parameter P5 = 16 ; Fifth QIO parameter P6 = 20 ; Sixth QIO parameter ; ; Other constants ; DA_TIMEOUT = 10 ; 10 second device timeout DA_DEF_BUFSIZ = 65535 ; Default buffer size ; ; DA11-B definitions that follow the standard UCB fields ; $DEFINI UCB ; Start of UCB definitions .=UCB$K_LENGTH ; Position at end of UCB $DEF UCB$W_RCVWRDCNT ; Word count for a receive .BLKW 1 $DEF UCB$W_RCVMEMEXT ; Memory extension bits of a .BLKW 1 ; receive buffer address $DEF UCB$W_RCVBUFADR ; Buffer address for a receive .BLKW 1 $DEF UCB$W_DA_DATABF ; Contents of device data buffer .BLKW 1 ; register. $DEF UCB$W_DA_WRDCNT ; Contents of device word count .BLKW 1 ; register. $DEF UCB$B_FUNC_CODE ; Extracted I/O function code. .BLKB 1 $DEF UCB$K_DA_UCBLEN ; Length of extended UCB ; ; Bit positions for device-dependent status field in UCB ; $VIELD UCB,0,<- ; Device status ,- ; Receive pending ,- ; Receive active > $DEFEND UCB ; End of UCB definitions ; ; Device register offsets from CSR address ; $DEFINI DA ; Start of DA11-B definitions .=-4 ; Position to first register. $DEF DA_WRDCNT ; Word count .BLKW 1 $DEF DA_BUFADR ; Buffer address .BLKW 1 $DEF DA_STATUS ; Control/status .BLKW 1 ; ; Bit positions for device control/status register ; _VIELD DA_STS,0,<- ; Control/status register ,- ; Start device ,- ; Block or word transfer mode ,- ; Transfer direction ,- ; Interrupt request ,- ; Extended address bits ,- ; Enable interrupts ,- ; Device ready for command ,- ; Starts slave transmit ,- ; Block or word transfer mode ,- ; Transfer direction ,- ; Interrupt request <,1>,- ; Maintenance bit ,- ; Status from other processor ,- ; Nonexistent memory flag ,- ; Error or external interrupt > $DEF DA_DATABUF ; Data buffer (holds other CPU's .BLKW 1 ; transmit word count). $DEFEND DA ; End of DA11-B definitions .SBTTL Standard tables ; ; Driver prologue table ; DPTAB - ; DPT-creation macro END=DA_END,- ; End of driver label ADAPTER=UBA,- ; Adapter type UCBSIZE=,- ; Length of UCB NAME=DADRIVER ; Driver name DPT_STORE INIT ; Start of load ; initialization table DPT_STORE UCB,UCB$B_FIPL,B,8 ; Device fork IPL DPT_STORE UCB,UCB$B_DIPL,B,22 ; Device interrupt IPL DPT_STORE UCB,UCB$L_DEVCHAR,L,<- ; Device characteristics DEV$M_NET!- ; network device DEV$M_IDV!- ; input device DEV$M_ODV> ; output device DPT_STORE UCB,UCB$B_DEVCLASS,B,DC$_SCOM ; Device class DPT_STORE UCB,UCB$W_DEVBUFSIZ,W,- ; Default buffer size DA_DEF_BUFSIZ DPT_STORE REINIT ; Start of reload ; initialization table DPT_STORE DDB,DDB$L_DDT,D,DA$DDT ; Address of DDT DPT_STORE CRB,CRB$L_INTD+4,D,- ; Address of interrupt DA_INTERRUPT ; service routine DPT_STORE CRB,CRB$L_INTD+VEC$L_INITIAL,-; Address of controller D,DA_CONTROL_INIT ; initialization routine DPT_STORE END ; End of initialization ; tables ; ; Driver dispatch table ; DDTAB - ; DDT-creation macro DEVNAM=DA,- ; Name of device START=DA_START,- ; Start I/O routine FUNCTB=DA_FUNCTABLE,- ; FDT address CANCEL=DA_CANCEL ; Cancel I/O routine ; ; Function dispatch table ; DA_FUNCTABLE: ; FDT for driver FUNCTAB ,- ; Valid I/O functions ; Write physical FUNCTAB , ; No buffered functions FUNCTAB DA_CHECK_COUNT,- ; Device-specific FDT FUNCTAB +EXE$READ, ; FDT read routine FUNCTAB +EXE$WRITE, ; FDT write routine .SBTTL DA_CONTROL_INIT, Controller initialization routine ;++ ; DA_CONTROL_INIT, Readies controller for I/O operations ; ; Functional description: ; ; Allocates the direct data path permanently, and assigns the ; controller data channel permanently. Then clears the device's ; control status register. ; ; Inputs: ; ; R4 - address of the CSR ; R5 - address of the IDB ; R6 - address of the DDB ; R8 - address of the CRB ; ; IDB$L_UCBLST contains address of device's UCB ; ; Outputs: ; ; VEC$V_PATHLOCK bit set in CRB$L_INTD+VEC$B_DATAPATH ; IDB$L_OWNER contains UCB address ; ;-- DA_CONTROL_INIT: ; Initialize controller ; JSB G^INI$BRK ; Debugging breakpoint BISB #VEC$M_PATHLOCK,- ; Insist on direct data path. CRB$L_INTD+VEC$B_DATAPATH(R8) MOVL IDB$L_UCBLST(R5),R0 ; Get address of UCB. MOVL R0,IDB$L_OWNER(R5) ; Make the device the permanent ; controller channel owner. BISW #UCB$M_ONLINE,- ; Turn the device online. UCB$W_STS(R0) CLRW DA_STATUS(R4) ; Clear device's control/status ; register. RSB ; Return .SBTTL DA_CHECK_COUNT, FDT transfer-count-valid routine ;++ ; DA_CHECK_COUNT, Rejects QIOs with odd transfer byte counts ; ; Functional description: ; ; Determines whether the specified transfer byte count is even ; or odd. Rejects QIOs with an odd transfer byte count. ; ; Inputs: ; ; R3 - Address of the IRP ; R4 - Address of the PCB ; R5 - Address of the UCB ; R6 - Address of the CCB ; R7 - Bit number of the I/O function code ; R8 - Address of the FDT routine ; AP - Address of the 1st function dependent QIO parameter ; ; Outputs: ; ; R0 - error status code if byte count is an odd value ; ;-- DA_CHECK_COUNT: ; Check for odd transfer count. BLBC P2(AP),EVEN_COUNT ; Branch on even count. MOVZWL #SS$_BADPARAM,R0 ; Return error status code. JMP G^EXE$ABORTIO ; Odd count. Abort the request. EVEN_COUNT: ; Success, even count. RSB ; Return to FDT loop in QIO ; service routine. .SBTTL DA_START, Start I/O routine ;++ ; DA_START - Start a transmit, receive, or initialize operation ; ; Functional description: ; ; This routine starts an I/O operation for a READ or WRITE I/O ; transfer. The steps are the following: ; ; Allocate a data path (NOOP, direct data path). ; Allocate and load UBA map registers. ; Compute UNIBUS start address and transfer word count. ; ; The routine then branches according to the I/O function code. ; ; The WRITE operation is performed as follows: ; ; Load device's buffer address register. ; Load device's word count register. ; Load count in device's data buffer register (informs ; receiver of number of bytes transmitted). ; Check for power failure, and exit if failure occurred. ; Activate device. ; Wait for interrupt. ; Fork. ; Compute number of words transmitted. ; Return status and transferred byte count. ; ; The READ operation is performed as follows: ; ; Save UNIBUS starting address and transfer word count ; in UCB. ; Check for power failure, and exit if failure occurred. ; Enable interrupts from device. ; Wait for interrupt. ; Fork. ; Load device's buffer address register. ; Load device's word count register. ; Check for power failure, and exit if failure occurred. ; Activate device. ; Wait for interrupt. ; Fork. ; Compute number of words transmitted. ; Return status and transferred byte count. ; ; Inputs: ; ; R3 - address of the I/O request packet ; R5 - address of the device's UCB ; ; Outputs: ; ; R0 - I/O status, and number of bytes transferred ; R1 - null ; ;-- DA_START: ; Process an I/O packet ; ; Obtain address of the controller's CSR. Clear the UCB's device- ; dependent status field. ; ; JSB G^INI$BRK ; Debugging breakpoint MOVL UCB$L_CRB(R5),R4 ; Get address of CRB. MOVL @CRB$L_INTD+VEC$L_IDB(R4),- R4 ; Get address of CSR. CLRW UCB$W_DEVSTS(R5) ; Clear device-dependent status. ; ; Isolate and save the I/O function code. ; BICB3 #^C,- ; Obtain I/O function code from IRP$W_FUNC(R3),- ; the I/O packet. Store in UCB. UCB$B_FUNC_CODE(R5) ; ; Set up the I/O transfer by allocating a data path and map registers, ; and loading the map registers. ; TRANSFER: ; Prepare for a transfer. REQDPR ; Request a data path. REQMPR ; Request a set of map ; registers. LOADUBA ; Load the map registers. ; ***32K boundary problem*** ; ; Calculate UNIBUS start address of the transfer, and the word count ; of the transfer. ; MOVZWL UCB$W_BOFF(R5),R0 ; Get byte offset in first ; page of transfer buffer. MOVL UCB$L_CRB(R5),R1 ; Get address of the CRB. INSV CRB$L_INTD+VEC$W_MAPREG(R1),- #9,#9,- ; Put starting map register R0 ; number into high bits of ; UNIBUS start address. EXTZV #16,#2,R0,R1 ; Extract the high 2-bits of ; UNIBUS start address. ASHL #DA_STS_V_XBA,R1,R1 ; Shift bits to memory extension ; positions. MOVW UCB$W_BCNT(R5),R2 ; Get number of bytes to ; transfer. DIVL #2,R2 ; Convert to words. ; ; Determine whether this is a transmit or receive request. ; CHECK_FUNCTION: ; Set up is unique for both ; receive and transmit. CMPB #IO$_WRITEPBLK,- ; Is it a write code? UCB$B_FUNC_CODE(R5) BEQL START_WRITE ; If equal, yes, branch. ; Otherwise, it's a receive. ; ; Prepare for receive: ; ; Mark the UCB to indicate that a receive is pending. Write the start ; address, memory extension bits, and word count into the UCB. Then set ; up the device's control/status bit mask to enable interrupts. When the ; companion computer starts a transmit, an interrupt will occur on the ; device. ; START_RCVPENDNG: ; Prepare for receive. MOVW R0,UCB$W_RCVBUFADR(R5) ; Store low 16-bits of start ; address in UCB receive block. MOVW R1,UCB$W_RCVMEMEXT(R5) ; Set memory extension bits ; in UCB memory bits field. MOVW R2,UCB$W_RCVWRDCNT(R5) ; Load word count into UCB. BISW #UCB$M_RCVPENDNG,- ; Set receive-pending flag in UCB$W_DEVSTS(R5) ; the UCB. MOVZWL #DA_STS_M_INTENA,R3 ; Enable interrupts in status ; bit mask. BRB CHECK_POWERFAIL ; Join powerfail checkout code. ; ; Set up to start transmit: ; ; Load word count, buffer address, and memory extension bits into the ; device's registers. Load the starting word count into the device's ; data buffer register so that the receiver can read it. ; ; Set three bits in the status setup register. These bit settings will ; cause the device to request an interrupt on the companion computer, ; and enable interrupts on this device. ; ; Since the direction and mode bits both remain clear, the direction is ; transmit from this device to the companion computer, and do a block ; mode transfer. ; START_WRITE: ; Prepare for transmit. MOVW R0,DA_BUFADR(R4) ; Store low 16-bits of start ; address in buffer address ; device register. MOVW R1,R3 ; Set memory extension bits ; in status setup register. MOVW R2,DA_DATABUF(R4) ; Load transfer count in data ; buffer. This is the protocol. MNEGW R2,DA_WRDCNT(R4) ; Load negative transfer count ; into word count register. BISW #DA_STS_M_INTENA!- ; Set interrupt enable, go, and DA_STS_M_GO!- ; request interrupt on companion DA_STS_M_OREQIN,R3 ; computer in register that ; holds device control bits. ; ; Raise IPL to check for a power failure. If no power failure, activate ; the device and wait for an interrupt. When the interrupt occurs, ; create a fork process at the device's fork IPL. ; CHECK_POWERFAIL: ; Check for power failure. DSBINT ; Raise IPL to IPL$_POWER. BBCC #UCB$V_POWER,- ; Branch if no power failure. UCB$W_STS(R5),- ; Clear bit in any case. START_DEVICE SETIPL UCB$B_FIPL(R5) ; Lower IPL back to fork IPL. BRW POWER_FAILURE ; Report an error. START_DEVICE: ; Activate device. MOVW R3,DA_STATUS(R4) ; Activate device. WFIKPCH TIMEOUT,#DA_TIMEOUT ; Wait for interrupts. ; ; Back in the main driver after a solicited interrupt. IPL is at ; device interrupt level (UCB$B_DIPL). Determine whether the interrupt ; was from a pending receive, or from an active transmit or receive. ; ; R4 - address of the CSR ; R5 - address of the UCB ; ; JSB G^INI$BRK ; Debugging breakpoint. BBCC #UCB$V_RCVPENDNG,- ; If a transmit or receive, UCB$W_DEVSTS(R5),- ; go check for success. CHECK_TRANSFER ; ; Start the receive: ; ; Mark the UCB for an active receive operation. Then retrieve the device ; register settings from the UCB and start the device. ; START_RECEIVE: ; Start a receive operation. BISW #UCB$M_RCVACTIVE,- ; Mark receive-active bit in the UCB$W_DEVSTS(R5) ; UCB. MNEGW UCB$W_RCVWRDCNT(R5),- ; Load negative word count into DA_WRDCNT(R4) ; device's count register. MOVW UCB$W_RCVBUFADR(R5),- ; Load buffer address into DA_BUFADR(R4) ; device register. MOVW UCB$W_RCVMEMEXT(R5),R3 ; Set the memory extension bits. BISW #DA_STS_M_INTENA!- ; Set the interrupt enable, go, DA_STS_M_GO!- ; and input direction bits in DA_STS_M_ODIREC,R3 ; the status holding register. BRB CHECK_POWERFAIL ; Go check for power failure. ; ; Complete transfer: ; ; A receive or transmit has completed. First create a fork process. ; Then release UBA resources, return status and the number of bytes ; transferred to I/O postprocessing. ; CHECK_TRANSFER: ; Test for transfer completion. IOFORK ; Create a fork process. ; ; Release UBA resources. ; RELMPR ; Release map registers. RELDPR ; Release data path. ; ; Calculate number of bytes transferred. On a transmit, if the device's ; word count is zero, then all bytes were transmitted. Otherwise, the ; receive buffer was too small. On a receive, if the device's word ; count is zero, and the starting word count sent by the transmitter ; is larger than the receive buffer size, then a complete transmit did ; not occur. Report data overrun. ; TSTW UCB$W_DA_WRDCNT(R5) ; Did all words transfer? BNEQ INCOMPLETE_XFER ; If not equal, no. Report an MOVZWL UCB$W_BCNT(R5),R0 ; Obtain byte transfer value. MULL2 #^X10000,R0 ; Shift into high 16-bits of R0. BBC #UCB$V_RCVACTIVE,- ; If transmitting, and all words UCB$W_DEVSTS(R5),- ; transmitted, go return success LOAD_STATUS ; status. CMPW UCB$W_RCVWRDCNT(R5),- ; If receiving, see if buffer UCB$W_DA_DATABF(R5) ; was large enough for data. BEQL LOAD_STATUS ; If match, buffer is okay. MOVW #SS$_DATAOVERUN,R0 ; Otherwise, report data did not ; all fit in buffer. BRB COMPLETE_IO ; And finish the I/O. LOAD_STATUS: ; Return normal status. MOVW #SS$_NORMAL,R0 ; Load a success code into R0. BRB COMPLETE_IO ; And call I/O postprocessing. ; ; Incomplete transfer: report an error and return the number of bytes ; successfully transferred. ; INCOMPLETE_XFER: ; All bytes did not transfer. MULL3 #2,UCB$W_DA_WRDCNT(R5),-; Calculate number of bytes left R0 ; to transfer. ADDL2 UCB$W_BCNT(R5),R0 ; Add negative bytes remaining ; to original transfer count. ; Result is bytes transferred. MULL2 #^X10000,R0 ; Shift result to high 16-bits ; of status register. MOVW #SS$_OPINCOMPL,R0 ; Return error status code. BRB COMPLETE_IO ; Call I/O postprocessing. ; ; Device timeout handling. Control arrives here if an operation does not ; complete within the allowed time limit, or if a power failure occurs. ; Release UBA resources, clear the device's control/status register, and ; return an error status code. ; TIMEOUT: ; An operation did not complete. ; JSB G^INI$BRK ; Debugging breakpoint. CLRW DA_STATUS(R4) ; Clear device status. SETIPL UCB$B_FIPL(R5) ; Restore IPL to fork level. POWER_FAILURE: ; The power failed. RELMPR ; Release map registers. RELDPR ; Release data path. MOVZWL #SS$_TIMEOUT,R0 ; Return error status. ; ; Clear the 2nd longword of I/O status and call I/O postprocessing. ; COMPLETE_IO: ; Driver processing is finished. CLRL R1 ; Return null 2nd word of I/O ; status. REQCOM ; Complete I/O. .SBTTL DA_INTERRUPT, Interrupt service routine ;++ ; DA_INTERRUPT, Analyzes interrupts, processes solicited interrupts ; ; Functional description: ; ; This routine begins by confirming that the interrupt was ; generated by a ready device. If the device is not ready, the ; routine clears the device's CSR and dismisses the interrupt. ; ; The routine then examines the device's UCB to see if a receive ; or a transmit has been started. If so, the routine restores the ; suspended driver code. ; ; Otherwise, the routine assumes that the interrupt is from the ; other computer trying to transmit, and that a receive is pending ; on this computer. If the device CSR and the UCB confirm this ; assumption, and no errors have occurred, the routine restores ; the suspended driver code. ; ; To dismiss the interrupt, the routine clears the device's CSR ; (on error only) and restores registers R0-R5 before executing ; an REI. ; ; Inputs: ; ; 0(SP) - pointer to the address of the IDB ; 4(SP) - saved R0 ; 8(SP) - saved R1 ; 12(SP) - saved R2 ; 16(SP) - saved R3 ; 20(SP) - saved R4 ; 24(SP) - saved R5 ; 28(SP) - saved PSL ; 32(SP) - saved PC ; ; Outputs: ; ; Saves the device's word count register in UCB$W_DA_WRDCNT. ; Saves the device's data buffer register in UCB$W_DA_DATABF. ; ;-- DA_INTERRUPT: ; Service device interrupt ; JSB G^INI$BRK ; Debugging breakpoint MOVL @(SP)+,R4 ; Get address of IDB and remove ; pointer from stack. MOVQ (R4),R4 ; Get address of device's CSR ; and address of device's UCB. TSTB (R4) ; Device ready bit set? BGEQ UNSOL_INTERRUPT ; No, dismiss interrupt. BBC #UCB$V_INT,- ; If device does not expect UCB$W_STS(R5),- ; interrupt, dismiss it. UNSOL_INTERRUPT MOVW DA_DATABUF(R4),- ; Save the device's data buffer UCB$W_DA_DATABF(R5) ; register. MOVW DA_WRDCNT(R4),- ; Save the device's word count UCB$W_DA_WRDCNT(R5) ; register. ; ; If a receive or a transmit is active, restore control to the main ; driver code. ; BBC #UCB$V_RCVPENDNG,- ; If not receive pending, just UCB$W_DEVSTS(R5),- ; reactivate driver at saved PC. RESTORE_DRIVER ; ; Ascertain that the companion computer requested an interrupt on the ; device, and that the device reports no error conditions. If a device ; error occurs, the active request will time out. ; BBC #DA_STS_V_IREQIN,(R4),- ; If the interrupt is of unknown DISMISS_INT ; origin, dismiss it. BBS #DA_STS_V_ERROR,(R4),- ; If a device error occurred, UNSOL_INTERRUPT ; dismiss the interrupt. ; ; This is a solicited interrupt. Restore the main driver. ; RESTORE_DRIVER: ; Jump to main driver code. MOVL UCB$L_FR3(R5),R3 ; Restore driver's R3. JSB @UCB$L_FPC(R5) ; Call driver at interrupt ; wait address. BRB DISMISS_INT ; Then dismiss the interrupt. ; ; On an unsolicited interrupt, clear the device's control/status ; register if an error occurred, or if the UCB has no active packet. ; UNSOL_INTERRUPT: ; Dismiss unsolicited interrupt. CLRW DA_STATUS(R4) ; Clear device status. ; ; Restore the state of the stack before returning from the interrupt. ; DISMISS_INT: ; Return from interrupt. POPR #^M ; Restore R0-R5 REI ; Return from interrupt. .SBTTL DA_CANCEL, Cancel I/O routine ;++ ; DA_CANCEL, Cancels an I/O operation in progress ; ; Functional description: ; ; Inputs: ; ; R2 - negated value of the channel index number ; R3 - address of the current I/O request packet ; R4 - address of the PCB canceling I/O ; R5 - address of the device's UCB ; ; Outputs: ; ;-- DA_CANCEL: ; Cancel an I/O operation RSB ; Return .SBTTL DA_END, End of driver ;++ ; Label that marks the end of the driver ;-- DA_END: ; Last location in driver .END