.TITLE KSDRIVER VAX/VMS KS 2050 SERIES CAMAC DRIVER .IDENT 'V05-001' .NOSHOW CONDITIONALS .LIBRARY /SYS$LIBRARY:LIB/ ; SYSTEM MACRO LIBRARY .LIBRARY /CAMDEF/ ; CAMAC MACRO LIBRARY ;********************************************************************** ; ; ; VAX/VMS DEVICE DRIVER FOR THE KINETIC SYSTEMS 2050 CAMAC INTERFACE ; ; ;********************************************************************** ;++ ; ; FACILITY: ; ; OAK RIDGE NATIONAL LABORATORY ; FUSION ENERGY DIVISION ; TOKAMAK SECTION ; ; ABSTRACT: ; ; This device driver supports the KS 2050 series CAMAC interface. ; The KS 2050 is a serial CAMAC interface designed for Digital Equipment ; Corporation UNIBUS machines. The KS 2051 is the parallel highway ; counterpart of the 2050 unit. A detailed description of the hardware ; may be found in the KS 2050 Series Reference Manual. A brief synopsis ; of the 2050 series hardware characteristics follows. ; ; DEVICE REGISTERS: ; ; Control Register(CTR)-Offset 0 ; Contains mode select bits, error control bits, clock select/ ; clock rate bits, 'DONE'/'ERROR' bits, 'DONE'/'ERROR' interrupt ; enable bit and the 'GO' bit. ; ; ; Serial Error/Status Register(SES)-Offset 2 ; Contains amplified error status information, error ; recovery control/status information and the serial 'Q' ; and 'X' responses. ; ; Parallel Error/Status Register(PES)-Offset 4 ; Contains amplified error and status information about ; parallel highway transactions including branch X and Q ; responses and branch timeout status. Also contains control ; bits for branch demand enable and auto-GL enable. ; ; Command Register(CMR)-Offset 6 ; Contains the CAMAC station number(N), subaddress(A), ; function code(F) and error control bits. ; ; Crate Address/Data High Register(cdh)-Offset 10 ; Contains memory format control bit('16'/'24'), ; CAMAC crate address(C) and the HSB for programmed I/O ; operations. ; ; Data Low Register(DLR)-Offset 12 ; Contains the low order 16 bits of data for programmed I/O ; operations. ; ; Demand FIFO Register(DFR)-Offset 14 ; Contains serial demand FIFO status and reads SGL ; patterns from the demand FIFO. ; ; Demand/Compare Register(DCR)-Offset 16 ; Contains demand FIFO status indicators, the serial demand interrupt ; enable, the demand compare SGL pattern and the GO-ON-COMPARE enable ; for deferred command execution. ; ; Memory Address Extended Register(MAE)-Offset 30 ; Contains the 2 high order bits of the UNIBUS addresses used ; to specify transmit and recieve buffers. ; ; Transmit Mmeory Address Register(TMA)-Offset 32 ; Contains the low order 16 bits of the UNIBUS address used to ; transmit data to the KS 2050(CAMAC DMA write operations/list mode). ; ; Reply Memory Address Register(RMA)-Offset 34 ; Contains the low order 16 bits of the UNIBUS address used to receive ; data from the KS 2050(CAMAC DMA read operations/list mode). ; ; Word Count Register(WCR)-Offset 36 ; Contains the 16-bit word count for all CAMAC DMA operations to ; be transferred to/from the computer memory. ; ; MODES OF OPERATION: ; ; Programmed I/O Mode(Mode 0) ; ; Q Scan/Stop On Word Count Mode(Mode 1) ; ; Q Stop/Stop On Word Count Mode(Mode 2) ; ; Stop On Word Count Mode(Mode 3) ; ; Execute List Mode(Mode 4) ; ; Parallel GL Mode(Mode 6) ; ; Parallel Branch Initialize Mode(Mode 7) ; ; Q Repeat/Stop On Word Count Mode(Mode 8) ; ; ; ; AUTHOR: ; ; Edward T. Blair 18-MARCH-1982 ; ; REVISION HISTORY: ; V02-000 E.T. Blair, 25-MAY-1982 ; Addition of conditional assembly for single/multi unit ; driver generation. ; V02-001 E.T. Blair, 11-JUNE-1982 ; Add code to support 16/24 bit Programmed I/O requests. ; Add code to reset TMA and RMA address extend bits in ; the MAE register before masking in new values. ; ; V02-002 E.T. Blair, 12-JUNE-1982 ; Add code to support error logging for UNIBUS errors ; posted by the KS 2050 device. This code may be ; conditionally assembled by switch KS_X_ERLS. ; ; V03-000 E.T. BLAIR, 25-JUNE-1982 ; Add support for CAMAC ACP. ; Modify KS 2050 MODE 0 processing to utilize double ; page mapping to transfer CAMAC read data to user's ; buffer. ; ; V03-001 E.T. Blair, 27-july-1982 ; Make references to CAMAC specific data structures from ; CAMDEF.MLB to provide a common source of all structures ; and definitions for all CAMAC system software. ; ; V03-002 E.T. Blair, 6-AUGUST-1982 ; Add code to queue a deaccess IRP to the CAMAC ACP provided ; it is mounted, any time an I/O is cancelled for a particular ; VMS channel(eg. DEASSIGN, CANCEL, image/process rundown). This ; addition is necessary because VMS normal CANCEL flow will not ; queue the normal 'ACPCONTROL' IRP to the ACP if no "file" activity ; is in progress(i.e. no file window mapped for the channel) or ; the channel is assigned to a device mounted 'FOREIGN'. Also, ; made changes necessary to allow LAMAST requests to be queued to ; the CAMAC ACP through the crate UCB's even though they are not ; explicitly mounted. ; ; V03-003, E.T. Blair,18-AUG-1982 ; Delete conditional assembly code for single/multi unit code ; generation in the device driver. With the addition of the ; CAMAC ACP, this whole issue needs to be reevaluated at a later ; date to come up with a clean solution and implementation ; in order to maintain full functionality independent of single ; or multiple unit driver assembly. ; ; V03-004, E.T. Blair,24-AUG-1982 ; Add routine to perform internal allocation of IRP's. This routine ; is utilized to allocate a DEACCESS IRP to signal the CAMAC ACP ; an I/O channel is being deassigned and by the MODE 4(List Mode) ; FDT routine(replaces call to EXE$ALLOCIRP) to allocate an IRP ; extension when the execute list requires a reply list to support ; it's execution. Routine name is KS_ALOIRP. ; ; V03-005, E.T. Blair,27-AUG-1982 ; Correct documentation errors in the preambles for the KS_FDT_LAMAST ; and KS_FDT_SETC routines. These errors were found while converting ; the serial highway driver code to function as a parallel highway ; driver. ; ; V04-000, E.T. Blair,31-AUG-1982 ; Make changes necessary to support V02 of the CAMAC ACP. This version ; and ones subsequent will not work properly with V01 of the ACP. ; These changes are confined to KS_FDT_LAMAST and it's expected ; parameters. ; ; V04-001, E.T. Blair,7-SEP-1982 ; Change KS 2050 register template prefix for the serial control ; register to allow both serial and parallel register template macros ; to be expanded in the CAMAC access procedure modules without ; conflicting symbol names. Also, change the byte count for '24' ; bit Programmed I/O's from #4 to #3 so the crate number from ; the CDH register is not transferred back as CAMAC read data. ; ; V05-000, E.T. Blair, 23-SEP-1982 ; Add changes to support new KS 2050 firmware. The new firmware supports ; a Q-Repeat mode and a firmware reset bit in the control register. ; Also, to support the addition of the parallel system, a SH/PH ; bit(software indicator only) has been added to the CAMAC I/O status ; block returned by the SH/PH device drivers. ; ; V05-001, E.T. Blair, 25-JAN-1983 ; Check HSU link for 0 in KS_CANCEL to prohibit system bugcheck ; in the event that the UNIT_INIT is not called by SYSGEN due ; to an invalid CSR address or a malfunctioning highway driver ; that failed to respond when addressed. ;-- .PAGE .SBTTL SERIAL DRIVER MACRO DEFINITIONS .MACRO WAITMUSEC,DELAY,?L1,?L2,?L3 MOVZWL DELAY,R2 ; GET DELAY L1: DECL R2 ; DECREMENT COUNT BLSS L3 ; IF NEG, DONE MFPR #PR$_ICR,R0 ; GET MUSEC CLOCK L2: MFPR #PR$_ICR,R1 ; SAMPLE AGAIN CMPL R0,R1 ; SAME? BEQL L2 ; IF SO, SAMPLE TILL DIFFERENT BRB L1 ; RECORD MUSEC TICK L3: .ENDM WAITMUSEC .MACRO TIME TVAL MFPR #PR$_ICR,TVAL ; GET REAL TIME CLOCK .ENDM TIME .MACRO GETUBA,BOFF,MAPREG,UBADR .IF B,BOFF .ERROR 0 ; MISSING BYTE OFFSET .ENDC .IF B,MAPREG .ERROR 0 ; MISSING MAP REGISTER .ENDC .IF B,UBADR .ERROR 0 ; MISSING UNIBUS ADDRESS OUTPUT .ENDC MOVZWL BOFF,UBADR ; BYTE OFFSET(ZERO EXTEND) INSV MAPREG,- ; INSERT UBA MAP REGISTER AT PAGE #9,#9,- ; BOUNDARY IN UNIBUS MEMORY UBADR ; ADDRESS .ENDM GETUBA .MACRO REQCAMAC,?L1,?L2 CMPB IRP$B_PRI(R3),#16 ; CHECK PROCESS PRIORITY BLSS L1 ; IF REALTIME, HIGH PRI REQUEST REQPCHAN ; LOW PRI REQUEST BRB L2 ; COMMON FLOW L1: REQPCHAN PRI=HIGH ; HIGH PRI CONT REQUEST L2: .ENDM REQCAMAC .MACRO SETTMA,UBADDR .IF NB,UBADDR MOVL UBADDR,R0 ; GET UNIBUS TRANSMIT MEM ADDRESS ; NOTE: R0 IS DESTROYED BY THIS MACRO .ENDC MOVW R0,KS_W_TMA(R4) ; SET TMA REG CLRW R0 ; CLEAR LOW UBA BITS ASHL #,- ; POSITION MAE BITS R0,R0 BISW R0,KS_W_MAE(R4) ; MASK TMA BITS INTO MAE .ENDM SETTMA .MACRO SETRMA,UBADDR .IF NB,UBADDR MOVL UBADDR,R0 ; GET UNIBUS TRANSMIT MEM ADDRESS ; NOTE: R0 IS DESTROYED BY THIS MACRO .ENDC MOVW R0,KS_W_RMA(R4) ; SET RMA REG CLRW R0 ; CLEAR LOW UBA BITS ASHL #,- ; POSITION MAE BITS R0,R0 BISW R0,KS_W_MAE(R4) ; MASK RMA BITS INTO MAE .ENDM SETRMA .MACRO NULLUBA,MAPREG,NUMREG,UBADDR .IF B,MAPREG .ERROR 0 ; MISSING MAP REG NUMBER .ENDC .IF B,NUMREG .ERROR 0 ; MISSING NUMBER OF MAP REGS .ENDC .IF B,UBADDR .ERROR 0 ; MISSING UNIBUSS ADDRESS .ENDC MOVZBL NUMREG,UBADDR ; COMPUTE UNIBUSS ADDRESS DECL UBADDR ; FOR HIGH UBA MAP REG ADDW MAPREG,UBADDR ASHL #9,UBADDR,UBADDR .ENDM NULLUBA .PAGE .SBTTL DATA STRUC AND SYMBOL DEFINITIONS ; ; SYSTEM DATA STRUCTURE DEFINITIONS ; $CRBDEF ; Channel request block $DCDEF ; Device classes and types $DDBDEF ; Device data block $DEVDEF ; Device characteristics $DYNDEF ; Data structure type codes $IDBDEF ; Interrupt data block $IPLDEF ; Hardware IPL definitions $SSDEF ; System status codes $VADEF ; Virtual address defs $AQBDEF ; ACP CONTROL BLOCK $VCBDEF ; VOLUME CONTROL BLOCK $VECDEF ; Interrupt vector block $JIBDEF ; Job Information Block $PRDEF ; Processor registers $PCBDEF ; Process Control Block $EMBDEF ; Error log buffer struc ; ; CAMAC specific structures and definitions from CAMDEF.MLB ; .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK $SHPARMS ; SERIAL DRIVER PARAMETERS/SWITCHES .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK $PHPARMS ; PARALLEL DRIVER PARAMETERS/SWITCHES .ENDC ; END PARALLEL SWITCH BLOCK $KSIRPDEF ; KS DRIVER IRP DEFINITION $KSUCBDEF ; KS DRIVER UCB DEFINITION $KSREGS ; KS 2050 REGISTER AND MASK DEFINITIONS $KSIODEF ; CAMAC I/O FUNCTION CODES $RTBDEF ; REGISTER TEMPLATE BLOCK ; ; 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 .SBTTL DRIVER TABLE DEFINITIONS ; ; DRIVER PROLOGUE TABLE ; .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK DPTAB - ; DPT MUST BE FIRST END=KS_END,- ; End of driver label ADAPTER=UBA,- ; Adapter type UCBSIZE=,- ; Length of UCB FLAGS=DPT$M_SVP,- ; RESERVE SPTE FOR UNIT NAME=SHDRIVER ; Driver name .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK DPTAB - ; DPT MUST BE FIRST END=KS_END,- ; End of driver label ADAPTER=UBA,- ; Adapter type UCBSIZE=,- ; Length of UCB FLAGS=DPT$M_SVP,- ; RESERVE SPTE FOR UNIT NAME=PHDRIVER ; Driver name .ENDC ; END PARALLEL BLOCK 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,20 ; Device interrupt IPL .IF NE,KS_X_ERLS ; BEGIN 'ERLS=1' SWITCH BLOCK DPT_STORE UCB,UCB$L_DEVCHAR,L,<- ; Device characteristics DEV$M_ELG!- ; ERROR LOG ENABLE DEV$M_SHR!- ; SHAREABLE DEVICE DEV$M_RTM!- ; REAL TIME DEVICE DEV$M_IDV!- ; INPUT DEVICE DEV$M_ODV> ; OUTPUT DEVICE .IFF ; BEGIN 'ERLS=0' SWITCH BLOCK DPT_STORE UCB,UCB$L_DEVCHAR,L,<- ; Device characteristics DEV$M_SHR!- ; SHAREABLE DEVICE DEV$M_RTM!- ; REAL TIME DEVICE DEV$M_IDV!- ; INPUT DEVICE DEV$M_ODV> ; OUTPUT DEVICE .ENDC ; END 'ERLS=0' SWITCH BLOCK DPT_STORE UCB,UCB$B_DEVCLASS,- ; DEVICE CLASS AS B,DC$_REALTIME ; REALTIME DEVICE DPT_STORE REINIT ; START OF RELOAD ; INITIALIZATION .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK DPT_STORE DDB,DDB$L_DDT,D,SH$DDT ; Address of DDT .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK DPT_STORE DDB,DDB$L_DDT,D,PH$DDT ; Address of DDT .ENDC ; END PARALLEL BLOCK DPT_STORE CRB,CRB$L_INTD+4,- ;DONE ISR ADDRESS D,KS_ISR_DONE DPT_STORE CRB,- ; ERROR ISR ADDRESS CRB$L_INTD+VEC$K_LENGTH+4,- D,KS_ISR_ERR .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK DPT_STORE CRB,- ; SERIAL DEMAND ISR CRB$L_INTD+<2*VEC$K_LENGTH>+4,- D,KS_ISR_DEMAND DPT_STORE CRB,- ; IGNORE PARALLEL DEMAND ISR CRB$L_INTD+<3*VEC$K_LENGTH>+4,- D,KS_ISR_DISMISS .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK DPT_STORE CRB,- ; IGNORE SERIAL DEMAND ISR CRB$L_INTD+<2*VEC$K_LENGTH>+4,- D,KS_ISR_DISMISS DPT_STORE CRB,- ; PARALLEL DEMAND ISR CRB$L_INTD+<3*VEC$K_LENGTH>+4,- D,KS_ISR_DEMAND .ENDC ; END PARALLEL BLOCK DPT_STORE CRB,- ; Address of controller CRB$L_INTD+VEC$L_INITIAL,- ; initialization routine D,KS_CONTROL_INIT DPT_STORE END ; End of initialization ; tables ; ; DRIVER DISPATCH TABLE ; .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK .IF NE,KS_X_ERLS ; BEGIN 'ERLS=1' SWITCH BLOCK KS_DUMP_CNT = 13 ; ERR LOG DUMP COUNT KS_P_ERLENGTH = <+EMB$L_DV_REGSAV+4> ; ERR LOG MSG BUFFER LEN DDTAB - ; DDT CREATION MACRO DEVNAM=SH,- ; Name of device UNITINIT=KS_UNIT_INIT,- ; Unit initialization START=KS_START,- ; Start I/O routine FUNCTB=KS_FUNCTABLE,- ; FDT address CANCEL=KS_CANCEL,- ; Cancel I/O routine REGDMP=KS_REG_DUMP,- ; Register dump routine ERLGBF=KS_P_ERLENGTH ; ERROR LOG BFR .IFF ; BEGIN 'ERLS=0' SWITCH BLOCK DDTAB - ; DDT CREATION MACRO DEVNAM=SH,- ; Name of device UNITINIT=KS_UNIT_INIT,- ; Unit initialization START=KS_START,- ; Start I/O routine FUNCTB=KS_FUNCTABLE,- ; FDT address CANCEL=KS_CANCEL ; Cancel I/O routine .ENDC ; END 'ERLS=0' SWITCH BLOCK .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK .IF NE,KS_X_ERLS ; BEGIN 'ERLS=1' SWITCH BLOCK KS_DUMP_CNT = 13 ; ERR LOG DUMP COUNT KS_P_ERLENGTH = <+EMB$L_DV_REGSAV+4> ; ERR LOG MSG BUFFER LEN DDTAB - ; DDT CREATION MACRO DEVNAM=PH,- ; Name of device UNITINIT=KS_UNIT_INIT,- ; Unit initialization START=KS_START,- ; Start I/O routine FUNCTB=KS_FUNCTABLE,- ; FDT address CANCEL=KS_CANCEL,- ; Cancel I/O routine REGDMP=KS_REG_DUMP,- ; Register dump routine ERLGBF=KS_P_ERLENGTH ; ERROR LOG BFR .IFF ; BEGIN 'ERLS=0' SWITCH BLOCK DDTAB - ; DDT CREATION MACRO DEVNAM=SH,- ; Name of device UNITINIT=KS_UNIT_INIT,- ; Unit initialization START=KS_START,- ; Start I/O routine FUNCTB=KS_FUNCTABLE,- ; FDT address CANCEL=KS_CANCEL ; Cancel I/O routine .ENDC ; END 'ERLS=0' SWITCH BLOCK .ENDC ; END PARALLEL BLOCK ; ; FUNCTION DECISION TABLE ; KS_FUNCTABLE: ; FDT for driver FUNCTAB ,- ; Valid I/O functions ; RETRIEVE CRATE DATA FUNCTAB ; BUFFERED FUNCTION CODES FUNCTAB KS_FDT_CAMIO,- ; CAMAC I/O ROUTINE FUNCTAB KS_FDT_MOUNT,- ; MOUNT CAMAC ACP FUNCTAB KS_FDT_ACP,- ; ACP CONTROL FDT FUNCTAB KS_FDT_LAMAST,- ; SET LAM AST FDT FUNCTAB KS_FDT_SETC,- ; SET HIGHWAY CHARS FUNCTAB KS_FDT_SENSM,- ; SENSE CRATE FDT .DSABL LSB .PAGE .SHOW EXPANSIONS .ENABL LSB .SBTTL KS_CONTROL_INIT, CONTROLLER INITIALIZATION ROUTINE ;++ ; KS_CONTROL_INIT, Readies controller for I/O operations ; ; Functional description: ; ; The operating system calls this routine in 3 places: ; ; at system startup ; during driver loading and reloading ; during recovery from a power failure ; ; Inputs: ; ; R4 - address of the CSR (controller status register) ; R5 - address of the IDB (interrupt data block) ; R6 - address of the DDB (device data block) ; R8 - address of the CRB (channel request block) ; ; Outputs: ; ; The routine must preserve all registers except R0-R3. ; ;-- KS_CONTROL_INIT: ; Initialize controller ; ; DISABLE ALL KS 2050/2051 INTERRUPTS AND SET 'SUSPEND' BIT. ; ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME ASSUME SCT_M_SSP,EQ,PCT_M_SSP BICW #SCT_M_IE,KS_W_CTR(R4) ; DISABLE COMPLETION INTERRUPTS BISW #SCT_M_SSP,KS_W_CTR(R4) ; SET SUSPEND BIT IN CTR .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK BICW #DCR_M_SDIE,- ; DISABLE DEMAND INTERRUPTS KS_W_DCR(R4) .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK BICW #PES_M_BDIE,- ; DISABLE PARALLEL DEMAND INTERRUPTS KS_W_PES(R4) .ENDC ; END PARALLEL BLOCK ; ; TOGGLE FIRMWARE RESET AND WAIT FOR 'KS_P_RSWAIT' MICROSEC. ; ASSUME SCT_M_RESET,EQ,PCT_M_RESET ; ASSUME SERIAL AND PARALLEL SAME BISW #SCT_M_RESET,- ; ASSERT FIRMWARE RESET KS_W_CTR(R4) BICW #SCT_M_RESET,- ; CLEAR FIRMWARE RESET KS_W_CTR(R4) WAITMUSEC - ; DELAY WHILE SETTLES DELAY=#KS_P_RSWAIT .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK ; ; CLEAN UP DEMAND FIFO. BIT-CAN ANY DEMANDS FOUND. ; 30$: BITW #DFR_M_DFE,- KS_W_DFR(R4) ; TEST DEMAND FIFO REGISTER BEQL 30$ ; IF NOT EMPTY, POP ANOTHER .ENDC ; END SERIAL BLOCK RSB ; RETURN TO CALLER .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_UNIT_INIT, UNIT INITIALIZATION ROUTINE ;++ ; KS_UNIT_INIT: READIES HIGHWAY SUPPORT UNIT AND CRATE SUPPORT ; UNITS FOR OPERATION. ; ; Functional description: ; ; The operating system calls this routine after calling the ; controller initialization routine: ; ; at system startup ; during driver loading ; during recovery from a power failure ; ; ; The following operations are performed for unit initialization ; for the Highway Support Unit(Unit 0): ; Set the unit 'ON-LINE' in the UCB status field. ; Clear the HSU support block pointer field. ; ; No unit initialization is performed for Crate Support Units ; (Units 1-N). These units must be explicitly set on-line ; via a 'SETCHAR' I/O function request made through the ; Highway Support Unit(Unit 0) for each such CSU. ; ; ; Inputs: ; ; R4 - address of the CSR (controller status register) ; R5 - address of the UCB (unit control block) ; ; Outputs: ; ; The routine must preserve all registers except R0-R3. ; ;-- KS_UNIT_INIT: ; UNIT INITIALIZATION ROUTINE TSTW UCB$W_UNIT(R5) ; CHECK IF HIGHWAY SUPP UNIT BNEQ 10$ ; NOT 0, CRATE SUPP UNIT ; ; HIGHWAY SUPPORT UNIT CALL ; BBS #UCB$V_POWER,- ; CHECK IF POWER FAIL UCB$W_STS(R5),20$ ; AND SKIP INIT CODE IF SET BISW #UCB$M_ONLINE,- UCB$W_STS(R5) ; SET UNIT ON-LINE CLRW UCB$W_DEVSTS(R5) ; CLEAR DEVICE STATUS MOVL R5,UCB$L_HSU(R5) ; STORE HSU LINK TO SELF .IF NE,KS_X_LAMS ; BEGIN 'LAMS' SWITCH BLOCK CLRL UCB$L_DMDAST(R5) ; ZAP DEMAND AST LISTHEAD .ENDC ; END 'LAMS' SWITCH BLOCK 20$: RSB ; RETURN TO CALLER ; ; CRATE SUPPORT UNIT CALL ; 10$: CLRW UCB$W_DEVSTS(R5) ; ZERO DEVICE STATUS BISW #DSTS_M_MULTI,- ; INDICATE MULTI UNIT SYSTEM UCB$W_DEVSTS(R5) BISW #UCB$M_ONLINE,- ; SET UNIT ON-LINE UCB$W_STS(R5) MOVL UCB$L_CRB(R5),R1 ; LOCATE CRB FROM UCB MOVL CRB$L_INTD+VEC$L_IDB(R1),- R1 ; LOCATE IDB FROM CRB MOVL IDB$L_UCBLST(R1),- ; LINK CRATE UCB TO HSU UCB$L_HSU(R5) .IF NE,KS_X_LAMS ; BEGIN 'LAMS' SWITCH BLOCK CLRL UCB$L_LSB(R5) ; ZAP LAM SUPP BLOCK ADDRESS .ENDC ; END 'LAMS' SWITCH BLOCK RSB ; RETURN TO CALLER .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_CAMIO, CAMAC I/O FDT ROUTINE ;++ ; KS_FDT_CAMIO: CAMAC I/O FDT ROUTINE ; ; Functional description: ; ; This FDT routine provides device specific processing ; for all CAMAC I/O requests to user modules. Functions ; performed by this routine include: ; Validation of the register template block data, ; Verification of access rights to DMA buffer(s), ; Verification of memory lock for DMA buffer(s), ; Place KS 2050 register data into IRP, ; Place user buffer address(es) into IRP, ; Queue the IRP to the specified unit. ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_CAMIO: ; CAMAC I/O FDT ROUTINE MOVL P1(AP),R0 ; GET ADDRESS OF REG BLOCK IFRD #RTB_K_LENGTH,- ; PROBE RTB FOR READ (R0),10$ ; ACCESS. IF SO, CONTINUE. MOVZWL #SS$_ACCVIO,R0 ; DECLARE ACCESS VIOLATION BRB 90$ ; ABORT THIS REQUEST 10$: MOVQ RTB_W_CTR(R0),- ; TRANSFER REG TEMPLATE IRP$W_CTR(R3) ; TO IRP ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME ASSUME SCT_M_SSP,EQ,PCT_M_SSP ASSUME SCT_M_GO,EQ,PCT_M_GO BICW #,- ; AND GO BIT IRP$W_CTR(R3) ; ; EXTRACT MODE FIELD FROM CONTROL REG AND USE TO ; PROCESS THE I/O REQUEST BY CASES. ; ASSUME SCT_M_M,EQ,PCT_M_M ; ASSUME SERIAL AND PARALLEL MODES SAME EXTZV #SCT_V_M,#SCT_S_M,- ; GET MODE FROM CTR IN IRP IRP$W_CTR(R3),R0 CASEB R0,#0,#KS_P_MAXM ; VECTOR TO MODE PROCESS 20$: .WORD KS_CAMIO_M0-20$ ; MODE 0(PROGRAMMED I/O) .WORD KS_CAMIO_M1-20$ ; MODE 1(Q-SCAN/STOP ON WORD COUNT) .WORD KS_CAMIO_M2-20$ ; MODE 2(Q-STOP/STOP ON WORD COUNT) .WORD KS_CAMIO_M3-20$ ; MODE 3(STOP ON WORD COUNT) .WORD KS_CAMIO_M4-20$ ; MODE 4(EXECUTE LIST) .WORD KS_CAMIO_MERR-20$ ; MODE 5 INVALID .WORD KS_CAMIO_MERR-20$ ; MODE 6 NVALID .WORD KS_CAMIO_MERR-20$ ; MODE 7 INVALID .WORD KS_CAMIO_M8-20$ ; MODE 8(Q-REPEAT/STOP ON WORD COUNT) ; ; ERROR HANDLER FOR ILLEGAL MODE FIELD ; KS_CAMIO_MERR: MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER STATUS 90$: JMP G^EXE$ABORTIO ; ABORT I/O REQUEST .DSABL LSB .ENABL LSB KS_CAMIO_M0: ; ; MODE 0 PROCESSOR ; PROGRAMMED I/O CAMAC REQUEST. ; ; PROCESSOR ACTION: ; VERIFY CRATE/STATION ADDRESS WITH THE LEVEL OF I/O FUNCTION ; CODE SPECIFIED. IF CAMAC WRITE FUNCTION, INSERT DATA INTO THE ; FIELDS OF THE IRP REGISTER TEMPLATE. IF CAMAC READ FUNCTION, ; LOCK BUFFER INTO MEMORY AND SAVE PARAMETERS FOR START I/O ; TO DOUBLE MAP PROCESS BUFFER TO CROSS LOAD CAMAC READ DATA. ; THEN QUEUE THE I/O TO THE SPECIFIED UNIT. ; BICW #,- ; EXTENSION VALID IRP$W_STS(R3) CLRL IRP$L_SVAPTE(R3) ; CLEAR BUFFER SVAPTE CLRL IRP$L_DPRMAP(R3) ; CLEAR UBA PARAMETER FIELDS CLRL IRP$L_UBADDR(R3) MOVL P2(AP),R0 ; GET BUFFER ADDRESS MOVZBL #2,R1 ; SET LENGTH AT 2 BYTES BBS #CDH_V_16,- ; IF '16' SET IN CDH, OK IRP$W_CDH(R3),10$ ; TO CONTINUE MOVZBL #4,R1 ; CHANGE LENGTH TO 4 BYTES 10$: EXTZV #CMR_V_F,#CMR_S_F,- ; CHECK IF CAMAC READ OR WRITE IRP$W_CMR(R3),R2 CMPB R2,#7 ; CHECK FOR READ FUNC BGTR 80$ ; IF NOT, CHECK FOR WRITE ; LENGTH IN R1 FROM ABOVE JSB G^EXE$READLOCK ; CHECK/LOCK FOR READ FUNCTION ; ONLY RETURNS SUCCESS BRB 50$ ; QUEUE IRP TO UNIT 80$: CMPB R2,#16 ; CHECK FOR WRITE BLSS 50$ ; IF LESS, CONTROL FUNC CMPB R2,#23 ; TEST UPPER RANGE FOR WRITE BGTR 50$ ; IF GREATER, CONTROL FUNC ; LENGTH IN R1 FROM ABOVE TSTL R0 ; DATA BUFFER SPECIFIED? BEQL 50$ ; IF 0, ASSUME WRITE DATA ; IN RTB JSB G^EXE$WRITECHK ; CHECK BUFFER ACCESSABILITY ; CHECK ONLY RETURNS SUCCESS MOVW (R0),IRP$W_DLR(R3) ; INSERT DATA LOW INTO IRP CLRB IRP$W_CDH(R3) ; CLEAR DATA HIGH BYTE BBS #CDH_V_16,- ; IF '16' MODE, ALL THRU IRP$W_CDH(R3),50$ ; GO QUEUE I/O MOVB 2(R0),IRP$W_CDH(R3) ; INSERT DATA HIGH INTO IRP 50$: JMP G^EXE$QIODRVPKT ; EXIT FDT BY QUEUEING IRP 90$: JMP G^EXE$ABORTIO ; ABORT THIS REQUEST .DSABL LSB .ENABL LSB KS_CAMIO_M1: ; ; MODE 1 PROCESSOR. ; Q-SCAN/STOP ON WORD COUNT MODE. ; KS_CAMIO_M2: ; ; MODE 2 PROCESSOR. ; Q-STOP/STOP ON WORD COUNT MODE. ; KS_CAMIO_M3: ; ; MODE 3 PROCESSOR. ; STOP ON WORD COUNT MODE. ; KS_CAMIO_M8: ; ; MODE 8 PROCESSOR. ; Q-REPEAT/STOP ON WORD COUNT ; ; PROCESSOR ACTION: ; THIS MODE PROCESSOR MUST INSURE THAT THE SPECIFIED USER ; BUFFER IS LOCKED INTO PHYSICAL MEMORY FOR THE ENSUEING ; DIRECT I/O OPERATION. THE CAMAC FUNCTION CODE IS EXAMINED ; FOR VALIDITY AND THE SPECIFIED BUFFER IS CHECKED FOR ACCESS ; CONSISTENCY WITH THE SPECIFIED CAMAC FUNCTION CODE. THE ; BUFFER PAGES ARE THEN MEMORY LOCKED FOR THE DURATION OF ; I/O REQUEST. ; BICW #,- ; IRP EXTENSION IRP$W_STS(R3) CLRL IRP$L_SVAPTE(R3) ; CLEAR BUFFER POINTERS IN IRP CLRL IRP$L_DPRMAP(R3) ; CLEAR DPR+MAP FIELD MOVL P2(AP),R0 ; GET USER BUFFER ADDRESS BEQL 55$ ; IF 0, BAD PARAMETER MOVZWL P3(AP),R1 ; BUFFER LENGTH BEQL 55$ ; IF 0, BAD PARAMETER BLBC R1,50$ ; IF INTEGRAL WORD COUNT, CONTINUE 55$: MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER BRB 90$ ; ABORT REQUEST 50$: ASHL #-1,R1,R2 ; CONVERT TO WORD COUNT MNEGW R2,IRP$W_WCR(R3) ; SAVE NEG BFR WORD COUNT EXTZV #CMR_V_F,#CMR_S_F,- ; GET CAMAC FUNCTION CODE IRP$W_CMR(R3),R2 CMPB R2,#7 ; CHECK IF CAMAC READ BGTR 10$ ; IF NOT, CHECK FOR WRITE JSB G^EXE$READLOCK ; LOCK PAGES FOR CAMAC READ ; READLOCK ONLY RETURNS ON SUCCESS BRB 60$ ; QUEUE IRP TO UNIT 10$: CMPB R2,#16 ; CHECK IF CAMAC WRITE BLSS 20$ ; IF LESS THAN 16, ABORT CMPB R2,#23 ; COMPLETE WRITE CHECK BLEQ 30$ ; IF WRITE, CONTINUE 20$: MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER STATUS BRW 90$ ; ABORT THE REQUEST 30$: JSB G^EXE$WRITELOCK ; LOCK BUFFER PAGES FOR CAMAC WRITE ; WRITELOCK ONLY RETURNS ON SUCCESS 60$: JMP G^EXE$QIODRVPKT ; QUEUE THE I/O REQUEST TO THE UNIT 90$: JMP G^EXE$ABORTIO ; ABORT THE REQUEST .DSABL LSB .ENABL LSB KS_CAMIO_M4: ; ; MODE 4 PROCESSOR. ; EXECUTE LIST MODE. ; ; PROCESSOR ACTION: ; THIS MODE PROCESSOR MUST INSURE THAT TWO USER BUFFERS ; ARE LOCKED INTO PHYSICAL MEMORY FOR THE ENSUEING LIST ; MODE CAMAC TRANSACTION. LIST MODE ON THE KS 2050 REQUIRES ; THAT TWO BUFFERS BE ATTACHED. THE EXECUTE LIST CONTAINS CAMAC ; COMMAND PACKETS AND CAMAC WRITE DATA AND THE REPLY LIST RECEIVES ; CAMAC READ DATA FROM THE EXECUTION OF READ FUNCTION CODES FROM ; THE EXECUTE LIST. THE EXECUTE LIST IS CHECKED AND LOCKED FOR ; READ ACCESS AND THE REPLY LIST IS CHECKED AND LOCKED FOR WRITE ; ACCESS. ; BICW #,- ; IRP EXTENSION IRP$W_STS(R3) ; IN STATUS WORD CLRL IRP$L_SVAPTE(R3) ; CLEAR PTE PNTRS FOR EXECUTE LIST MOVL P2(AP),R0 ; GET EXECUTE LIST ADDRESS BEQL 10$ ; IF 0, BAD PARAMETER MOVZWL P3(AP),R1 ; AND EXECUTE LIST LENGTH BEQL 10$ ; IF 0 LENGTH, BAD PARAMETER BLBC R1,20$ ; IF INTEGRAL WORD COUNT, CONTINUE 10$: MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER STATUS BRB 90$ ; ABORT CALL 20$: ; EXE LIST PARAMETERS OK MOVL P4(AP),R0 ; GET REPLY LIST ADDRESS BEQL 40$ ; IF 0, SKIP REPLY LIST MOVZWL P5(AP),R1 ; GET REPLY LIST LENGTH BEQL 40$ ; IF 0, SKIP REPLY LIST BLBC R1,50$ ; CHECK FOR INTEGRAL WORD COUNT MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER STATUS BRB 90$ ; ABORT I/O 50$: JSB G^EXE$READLOCK ; CHECK/LOCK BUFFER FOR WRITE ACCESS ; ONLY RETURNS ON SUCCESS BSBW KS_ALOIRP ; ALLOCATE IRP EXTENSION BLBC R0,90$ ; IF FAILURE, ABORT BISW #IRP$M_EXTEND,- ; SET IRP EXTENSION BIT IRP$W_STS(R3) ; IN IRP STATUS WORD MOVL R2,IRP$L_EXTEND(R3) ; LINK EXTENSION INTO IRP CLRW IRPE$W_STS(R2) ; CLEAR EXTENSION STATUS MOVB #DYN$C_IRPE,- ; SET TYPE TO IRPE IRPE$B_TYPE(R2) MOVL IRP$L_SVAPTE(R3),- ; CROSS LOAD REPLY LIST IRPE$L_SVAPTE1(R2) ; SVA FOR FIRST PTE MOVW IRP$W_BOFF(R3),- ; AND BYTE OFFSET IRPE$W_BOFF1(R2) MOVZWL IRP$W_BCNT(R3),- ; AND BYTE COUNT IRPE$L_BCNT1(R2) CLRL IRPE$L_DPRMAP(R2) ; CLEAR DPR+MAP REG SAVE AREA CLRL IRPE$L_SVAPTE2(R2) ; CLEAR UNUSED SVAPTE FIELD 40$: MOVL P2(AP),R0 ; RESTORE EXE LIST ADDRESS MOVZWL P3(AP),R1 ; AND EXE LIST LENGTH ASHL #-1,R1,R2 ; CONVERT TO WORD COUNT MNEGW R2,IRP$W_WCR(R3) ; SAVE NEG EXE LIST WORD COUNT JSB G^EXE$WRITELOCK ; CHECK/LOCK LIST FOR READ ACCESS ; ONLY RETURNS ON SUCCESS CLRL IRP$L_DPRMAP(R3) ; CLEAR DPR+MAP FIELD JMP G^EXE$QIODRVPKT ; QUEUE IRP TO UNIT 90$: JMP G^EXE$ABORTIO ; ABORT THE REQUEST .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_ALOIRP, ALLOCATE IRP STRUC ;++ ; ; KS_ALOIRP: ALLOCATE IRP STRUCTURE, FIRST BY TRYING IRP ; LOOKASIDE LIST, THEN NONPAGED POOL ALLOCATION. ; ; Inputs: ; ; Outputs: ; R2 - address of IRP buffer, ; R0 - status of the request. ; R1 is destroyed by this call. ; ;-- KS_ALOIRP: MOVAL G^IOC$GL_IRPFL,R0 ; GET ADDR OF IRP LOOKASIDE LISTHEAD REMQUE @(R0),R2 ; GET NEXT IRP FROM LIST BVC 10$ ; SKIP IF REALLY HAVE ONE MOVZWL #IRP$C_LENGTH,R1 ; ELSE, ALLOCATE ONE FROM NPP PUSHL R3 ; SAVE R3 BEFORE CALL JSB G^EXE$ALONONPAGED ; ALLOCATE IRP SIZE BUFFER POPL R3 ; RESTORE R3 VALUE BLBC R0,90$ ; IF FAILURE, EXIT 10$: MOVW #IRP$C_LENGTH,- ; SET LENGTH IRP$W_SIZE(R2) MOVZBL #SS$_NORMAL,R0 ; RETURN NORMAL STATUS 90$: RSB ; RETURN TO CALLER .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_SETC ;++ ; KS_FDT_SETC: SET DEVICE CHARACTERISTICS FDT ROUTINE ; ; Functional description: ; ; This FDT routine provides a user with PHYS_IO privliege ; a means of exercising control over the entire CAMAC system ; to perform the following functions: ; Allocate Highway Support Block data structure. ; Enable LAM service for a CAMAC crate. ; Set Crate Support Unit 'ON-LINE'. ; Set Crate Support Unit 'OFF-LINE'. ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_SETC: ; SET DEVICE CHARACTERISTICS TSTW UCB$W_UNIT(R5) ; CHECK IF HIGHWAY SUPP UNIT BEQL 10$ ; IF 0, CONTINUE MOVZWL #SS$_ILLIOFUNC,R0 ; DECLARE ILLEGAL FUNCT IF NOT BRB 90$ ; ABORT THIS REQUEST 10$: BITW #IO$M_ENLAMS!- IO$M_DABLAMS,- IRP$W_FUNC(R3) ; ENABLE/DISABLE LAMS? BEQL 100$ ; IF NOT, CHECK OTHERS BSBW KS_SETC_LAMS ; HANDLE LAM SERVICE REQUEST BRB 90$ ; IF RETURNS, ABORT 100$: BITW #IO$M_CONLINE!- IO$M_COFFLINE,- IRP$W_FUNC(R3) ; SET CRATE ON/OFF LINE REQUEST? BEQL 900$ ; IF NOT, SET ERROR STATUS BSBW KS_SETC_CRATE ; HANDLE CRATE REQUEST BRB 90$ ; IF RETURNS, ABORT 900$: MOVZWL #SS$_ILLIOFUNC,R0 ; SET ILLEGAL FUNCTION 90$: JMP G^EXE$ABORTIO ; EXIT TO ABORT I/O .DSABL LSB .PAGE .ENABL LSB ;+++ ; ; KS_SETC_LAMS: ENABLE/DISABLE LAM MANAGEMENT SUPPORT FOR CRATE. ; ; Inputs: ; R5 - Highway Support Unit UCB address(UCB 0), ; P1(AP) -Crate number for which LAM support is requested. ; P2(AP) -Station number to reference LAM grader/encoder(ENABLE ONLY). ; ; Outputs: ; R0 - Status of the allocate request, ; ;--- KS_SETC_LAMS: ; ENABLE/DISABLE LAM MANAGEMENT MOVB P1(AP),- ; SAVE CAMAC CRATE NUMBER IRP$B_C(R3) MOVB P2(AP),IRP$B_N(R3) ; SAVE LAM GRADER STATION BRW KS_Q_TO_ACP ; QUEUE IRP TO CAMAC ACP .DSABL LSB .PAGE .ENABL LSB ;+++ ; ; KS_SETC_CRATE: SET CRATE UNIT ON/OFF LINE. ; ; Inputs: ; R5 - Highway Support Unit UCB address(UCB 0), ; P1(AP) - Crate address to be set 'ON-LINE'. ; ; Outputs: ; R0 - Status of the request, ; R1-R2 are destroyed. ; ;--- KS_SETC_CRATE: MOVB P1(AP),- ; SAVE CAMAC CRATE NUMBER IRP$B_C(R3) BRW KS_Q_TO_ACP ; QUEUE IRP TO CAMAC ACP .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_LAMAST ;++ ; KS_FDT_LAMAST: SET/CLEAR LAM ATTENTION AST FDT ROUTINE. ; ; Functional description: ; ; This FDT routine provides a means for a user to ; queue or cancel a LAM AST to a specific CAMAC crate and station ; address. The IRP is queued to the CAMAC ACP to actually ; perform the operation. ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; P1(AP) - CAMAC station number, ; P2(AP) - AST entry address(IO$V_SETLAM only), ; P3(AP) - AST parameter value(IO$V_SETLAM only). ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_LAMAST: ; CAMAC LAM MANAGEMENT FDT MOVZWL #SS$_ACCVIO,R0 ; ASSUME ACCESS VIOLATION BBS #IO$V_CANLAM,- ; CANCEL LAM AST REQUEST? IRP$W_FUNC(R3),30$ ; IF SO, SKIP CHECK IFNORD ADR=@P2(AP),- ; CHECK IF AST PROCEDURE SIZ=#2,- ; ENTRY MASK READABLE MODE=IRP$B_RMOD(R3),- ; AT REQUESTED ACCESS MODE DEST=90$ 30$: MOVB P1(AP),- ; SAVE CAMAC STATION IRP$B_N(R3) MOVL P2(AP),- ; SAVE LAM AST ADDR IRP$L_LAMAST(R3) MOVL P3(AP),- ; AND AST PARAMETER IRP$L_LAMASTP(R3) BRW KS_Q_TO_ACP ; GO QUEUE IRP TO ACP 90$: JMP G^EXE$ABORTIO ; ABORT LAM REQUEST .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_SENSM, SENSE CAMAC CRATE UNIT STATUS ;++ ; KS_FDT_SENSM: SENSE DEVICE MODE FDT ROUTINE ; ; Functional description: ; ; This routine provides a mechanism to allow a user with LOG_IO ; privilege to retrieve the unit status and device status ; fields from the associated UCB. ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_SENSM: ; SENSE DEVICE MODE FUNCTION MOVZWL #SS$_NORMAL,R0 ; SET NORMAL I/O STATUS MOVW UCB$W_STS(R5),R1 ; GET UNIT STATUS FIELD INSV #16,#16,- ; GET DEVICE STATUS FIELD UCB$W_DEVSTS(R5),R1 ; TOO JMP G^EXE$FINISHIO ; I/O REQUEST COMPLETE .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_MOUNT, MOUNT CAMAC ACP ;++ ; KS_FDT_MOUNT: MOUNT CAMAC ACP REQUEST. ; ; Functional description: ; ; This routine supports the 'IO$_MOUNT' function code to ; queue a mount IRP to the CAMAC ACP for it's initial ; processing in response to a request from the mount image. ; The mount request is only supported for the Highway Support ; Unit(UCB 0). If the unit is already mounted, the request ; is aborted. ; ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_MOUNT: ; MOUNT CAMAC ACP MOVZWL #SS$_ILLIOFUNC,R0 ; SET ILLEGAL I/O FUNCTION TSTW UCB$W_UNIT(R5) ; UNIT 0 REQUEST? BNEQ 90$ ; IF NOT, ABORT BBS #DEV$V_MNT,- ; ALREADY MOUNTED? UCB$L_DEVCHAR(R5),90$ ; IF SO, ABORT BBC #UCB$V_MOUNTING,- ; MOUNT IN PROGRESS? UCB$W_STS(R5),90$ ; IF NOT, ABORT MOVZWL #SS$_NOPRIV,R0 ; ASSUME NO 'MOUNT' PRIV IFNPRIV MOUNT,90$ ; IF NO 'MOUNT' PRIV, ABORT MOVL UCB$L_HSU(R5),R2 ; SET HSU ADDRESS FOR ALTERNATE ; ENTRY INTO Q_TO_ACP BRW KS_Q_TO_ACPA ; QUEUE IRP TO ACP 90$: JMP G^EXE$ABORTIO ; ABORT IRP .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_FDT_ACP, ACP CONTROL FDT ;++ ; KS_FDT_ACP: ACP CONTROL FDT ROUTINE ; ; Functional description: ; ; This FDT routine supports the ACPCONTROL function code. It's ; primary function is to provide a null action request to ; awaken the ACP. The subsequent action taken by the ACP ; once awakened is implementation dependent. Typically, the ; ACP will check if the associated UCB is marked for dismount ; and if so, will perform a dismount operation for that ; unit. ; ; ; ; Inputs: ; ; R0-R2 - scratch registers ; R3 - address of the IRP (I/O request packet) ; R4 - address of the PCB (process control block) ; R5 - address of the UCB (unit control block) ; R6 - address of the CCB (channel control block) ; R7 - bit number of the I/O function code ; R8 - address of the FDT table entry for this routine ; R9-R11 - scratch registers ; AP - address of the 1st function dependent QIO parameter ; ; Outputs: ; ; The routine must preserve all registers except R0-R2, and ; R9-R11. ; ;-- KS_FDT_ACP: ; ACP CONTROL REQUEST MOVZWL #SS$_DEVNOTMOUNT,R0 ; ASSUME FAILURE BBC #DEV$V_MNT,- ; DEVICE MOUNTED? UCB$L_DEVCHAR(R5),90$ ; IF NOT, ABORT MOVL UCB$L_HSU(R5),R2 ; GET HSU ADDRESS BRW KS_Q_TO_ACPA ; USE ALTERNATE Q_TO_ACP ; ENTRY 90$: JMP G^EXE$ABORTIO ; ABORT REQUEST .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_Q_TO_ACP, QUEUE IRP TO CAMAC ACP ;++ ; ; KS_Q_TO_ACP: QUEUE IRP TO CAMAC ACP. ; ; Inputs: ; R3 - address of IRP, ; R4 - address of current PCB, ; R5 - address of UCB. ; ; Outputs: ; Increments the VCB transaction count then exits ; to EXE$QIOACPPKT to queue the IRP to the ACP and ; return control from the QIO request. ; ;-- KS_Q_TO_ACP: ; QUEUE IRP TO ACP MOVL UCB$L_HSU(R5),R2 ; GET HSU ADDRESS MOVZWL #SS$_DEVNOTMOUNT,R0 ; ASSUME FAILURE BBC #DEV$V_MNT,- ; CAMAC ACP MOUNTED? UCB$L_DEVCHAR(R2),90$ ; IF NOT, ABORT BBS #DEV$V_DMT,- ; MARKED FOR DISMOUNT? UCB$L_DEVCHAR(R2),90$ ; IF SO, ABORT KS_Q_TO_ACPA: ; ALTERNATE ENTRY FOR MOUNT MOVL UCB$L_VCB(R2),R0 ; LOCATE VCB FROM UCB INCW VCB$W_TRANS(R0) ; INC VOL TRANS COUNT JSB G^IOC$WAKACP ; QUEUE IRP TO ACP JMP G^EXE$QIORETURN ; RETURN TO PROCESS 90$: JMP G^EXE$ABORTIO ; ABORT REQUEST .DSABL LSB .PAGE .SBTTL KS_START, START I/O ROUTINE ;++ ; KS_START: START A SERIAL CAMAC TRANSACTION USING THE CURRENT IRP. ; ; Functional description: ; ; This routine is called in driver fork context to ; initiate a CAMAC I/O transaction on the KS 2050 ; interface. The requested transfer mode is determined ; from the Register Data Block(RDB) in the IRP and ; driver I/O processing proceeds from there by case. ; ; Mode 0-Programmed I/O ; Disable interrupts to device IPL. ; Load KS 2050 CMR, CDH, DLR from the RDB. ; Check for POWER in UCB. If so, retry. If not, ; proceed. ; Set IPL to block POWER. ; Load KS 2050 CTR ! 'GO' ! 'INT ENABLE'. ; Wait for interrupt. ; Post interrupt analysis and terminate the IRP. ; ; ; Mode 1-Q Scan/Stop On Word Count ; Allocate UBA address window for DMA transfer to ; the KS 2050. ; Load the UBA mapping registers with the PTE's for ; the user's buffer. ; Disable interrupts to device IPL. ; Load the KS 2050 CMR, CDH, MAE, TMA/RMA and WCR ; registers. ; Check for POWER in UCB. If set, retry. If not, ; proceed. ; Set IPL to block POWER. ; Load KS 2050 CTR ! 'GO' ! 'INT ENABLE'. ; Wait for interupt. ; Post interrupt analysis and terminate IRP. ; ; Mode 2-Q Repeat/Stop On Word Count ; Allocate UBA address window for DMA transfer to ; the KS 2050. ; Load the UBA mapping registers with the PTE's for ; the user's buffer. ; Disable interrupts to device IPL. ; Load the KS 2050 CMR, CDH, MAE, TMA/RMA and WCR ; registers. ; Check for POWER in UCB. If set, retry. If not, ; proceed. ; Set IPL to block POWER. ; Load KS 2050 CTR ! 'GO' ! 'INT ENABLE'. ; Wait for interupt. ; Post interrupt analysis and terminate IRP. ; ; Mode 3-Stop On Word Count/Burst Transaction ; Allocate UBA address window for DMA transfer to ; the KS 2050. ; Load the UBA mapping registers with the PTE's for ; the user's buffer. ; Disable interrupts to device IPL. ; Load the KS 2050 CMR, CDH, MAE, TMA/RMA and WCR ; registers. ; Check for POWER in UCB. If set, retry. If not, ; proceed. ; Set IPL to block POWER. ; Load KS 2050 CTR ! 'GO' ! 'INT ENABLE'. ; Wait for interupt. ; Post interrupt analysis and terminate IRP. ; ; ; Mode 4-Execute List Mode ; Allocate UBA address window for DMA transfer to ; the KS 2050. ; Load the UBA mapping registers with the PTE's for ; the user's buffer. ; Disable interrupts to device IPL. ; Load the KS 2050 CMR, CDH, MAE, TMA and RMA and WCR ; registers. ; Check for POWER in UCB. If set, retry. If not, ; proceed. ; Set IPL to block POWER. ; Load KS 2050 CTR ! 'GO' ! 'INT ENABLE'. ; Wait for interupt. ; Post interrupt analysis and terminate IRP. ; ; ; Inputs: ; ; R3 - address of the IRP (I/O request packet) ; R5 - address of the UCB (unit control block) ; ; Implicit inputs: ; UCB$L_SVAPTE = IRP$L_SVAPTE ; UBC$W_BCNT = IRP$W_BCNT ; UCB$W_BOFF = IRP$W_BOFF ; ; ; Outputs: ; ; R0 - 1st longword of I/O status: contains status code and ; number of bytes transferred ; R1 - 2nd longword of I/O status: device-dependent ; ; The routine must preserve all registers except R0-R2 and R4. ; ;-- KS_START: ; Process an I/O packet BICW #,- ; CLEAR DMA OPERATION UCB$W_DEVSTS(R5) ; IN DEVICE STATUS MOVL UCB$L_CRB(R5),R4 ; GET CRB ADDRESS MOVL @CRB$L_INTD+VEC$L_IDB(R4),- R4 ; GET CTR ADDRESS IN R4 FOR DRIVER ; ; PROCESS THE CURRENT IRP ; DETERMINE KS 2050 MODE REQUESTED BY THE IRP REGISTER DATA ; BLOCK. PROCESS BY MODE 0 AS A CASE, MODES 1,2,3 AS A CASE AND ; MODE 4 AS A CASE. ; ASSUME SCT_M_M,EQ,PCT_M_M ; ASSUME SERIAL AND PARALLEL MODES SAME EXTZV #SCT_V_M,#SCT_S_M,- ; GET KS 2050 MODE IRP$W_CTR(R3),R0 ; FROM CTR IN IRP CASEB R0,#0,#KS_P_MAXM ; VECTOR TO MODE START PROCESSOR 10$: .WORD KS_START_PIO-10$ ; MODE 0(PROGRAMMED I/O) .WORD KS_START_DIO-10$ ; MODE 1(Q-SCAN; SINGLE DMA) .WORD KS_START_DIO-10$ ; MODE 2(Q-STOP; SINGLE DMA) .WORD KS_START_DIO-10$ ; MODE 3(STOP; SINGLE DMA) .WORD KS_START_LIO-10$ ; MODE 4(LIST; MULTIPLE DMA) .WORD KS_START_BADM-10$ ; MODE 5 INVALID .WORD KS_START_BADM-10$ ; MODE 6 INVALID .WORD KS_START_BADM-10$ ; MODE 7 INVALID .WORD KS_START_DIO-10$ ; MODE 8(Q-REP; SINGLE DMA) ; ; SAFETY VALVE FOR ILLEGAL MODES ; KS_START_BADM: MOVZWL #SS$_BADPARAM,R0 ; SET BAD PARAMETER STATUS MOVZWL IRP$W_CTR(R3),- ; RETURN CTR TEMPLATE TOO R1 ; AS IOSB VALUE BRW KS_REQCOM ; POST I/O PROCESSING ; ; CASE A: MODE 0-PROGRAMMED I/O OPERATION. ; KS_START_PIO: REQCAMAC ; REQUEST CONTROLLER BICW #UCB$M_POWER,- ; CLEAR PWR FAIL UCB$W_STS(R5) ; BEFORE CRITICAL SECTION KS_PWR_PIO: ; POWER FAIL RECOVERY POINT MOVW IRP$W_CMR(R3),- ; LOAD COMMAND REG(N,A,F) KS_W_CMR(R4) MOVW IRP$W_CDH(R3),- ; LOAD CRATE/DATA HIGH KS_W_CDH(R4) MOVW IRP$W_DLR(R3),- ; LOAD DATA LOW REG KS_W_DLR(R4) PUSHAB KS_PWR_PIO ; PWR FAIL RECOVERY ADDR BRW KS_START_COM ; START DEVICE AND WAIT ; ; CASE B: MODE 1-Q SCAN/STOP ON WORD COUNT OPERATION, ; MODE 2-Q REPEAT/STOP ON WORD COUNT OPERATION, ; MODE 3-STOP ON WORD COUNT/BURST MODE OPERATION. ; KS_START_DIO: BISW #DSTS_M_DMA,- ; SET DMA DEVICE STATUS UCB$W_DEVSTS(R5) ; IN DEVICE STATUS REQCAMAC ; REQUEST CONTROLLER REQDPR ; REQUEST BUFFERED DATA PATH REQMPR ; REQUEST UBA ADDRESS SPACE ; USING SVAPTE, BOFF, BCNT FROM ; UCB FIELDS MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS MOVL CRB$L_INTD+VEC$W_MAPREG(R1),- IRP$L_DPRMAP(R3) ; SAVE UBA PARAMETERS FOR ERR LOG GETUBA UCB$W_BOFF(R5),- ; COMPUTE UNIBUS MEM ADDRESS CRB$L_INTD+VEC$W_MAPREG(R1),- IRP$L_UBADDR(R3) ; AND SAVE FOR LATER BICW #UCB$M_POWER,- ; CLEAR PWR FAIL BEFORE UCB$W_STS(R5) ; CRITICAL SECTION KS_PWR_DIO: ; SINGLE DMA PFAIL RECOVERY POINT LOADUBA ; LOAD PTE'S INTO UBA MAP REGS ; ADDRESS FOR UBA WINDOW BICW #,- ; BITS FIRST KS_W_MAE(R4) MOVL IRP$L_UBADDR(R3),R0 ; GET UNIBUS MEM ADDRESS MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS BBS #IRP$V_FUNC,- ; CHECK IF CAMAC READ/WRITE IRP$W_STS(R3),30$ SETTMA ; LOAD TMA/MAE WITH TM ADDRESS NULLUBA CRB$L_INTD+VEC$W_MAPREG(R1),- CRB$L_INTD+VEC$B_NUMREG(R1),- R0 ; GET NULL UNIBUS ADDRESS SETRMA ; LOAD IT INTO RMA/MAE TO ; STOP ERRONEOUS OPERATION BRB 40$ ; CONTINUE 30$: SETRMA ; LOAD KS 2050 RMA/MAE REGS NULLUBA CRB$L_INTD+VEC$W_MAPREG(R1),- CRB$L_INTD+VEC$B_NUMREG(R1),- R0 ; GET INVALID UNIBUS MEM ADDRESS SETTMA ; INVALIDATE TMA ADDRESS 40$: MOVW IRP$W_WCR(R3),- ; LOAD DMA WORD COUNT KS_W_WCR(R4) MOVW IRP$W_CMR(R3),- ; LOAD COMMAND REG(N,A,F) KS_W_CMR(R4) MOVW IRP$W_CDH(R3),- ; CRATE AND MEM FORMAT KS_W_CDH(R4) PUSHAB KS_PWR_DIO ; PWR FAIL RECOVERY ENTRY BRW KS_START_COM ; START DEVICE AND WAIT ; ; CASE C: MODE 4-EXECUTE LIST MODE. ; KS_START_LIO: BISW #DSTS_M_DMA,- ; SET DMA OPERATION STATUS UCB$W_DEVSTS(R5) ; IN DEVICE STATUS REQCAMAC ; REQUEST CONTROLLER BICW #UCB$M_POWER,- ; CLEAR PWR FAIL INDICATOR UCB$W_STS(R5) KS_PWR_LIO: ; LIST I/O PWR FAIL RECOVERY POINT BICW #,- ; REGISTER KS_W_MAE(R4) BBS #VEC$V_MAPLOCK,- ; TEST FOR UBA RESOURCES IRP$L_DPRMAP(R3),- ; ALLOCATED AND SKIP IF DONE. 200$ REQDPR ; DATA PATH FOR EXECUTE LIST REQMPR ; GET UBA WINDOW FOR EXECUTE LIST ; USING UCB SVAPTE, BOFF, BCNT. MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS MOVL CRB$L_INTD+VEC$W_MAPREG(R1),- IRP$L_DPRMAP(R3) ; SAVE UBA PARAMETERS GETUBA UCB$W_BOFF(R5),- ; COMPUTE UNIBUS MEM ADDRESS CRB$L_INTD+VEC$W_MAPREG(R1),- IRP$L_UBADDR(R3) ; AND SAVE FOR LATER BISW #VEC$M_MAPLOCK,- ; INDICATE EXECUTE LIST RESOURCES IRP$L_DPRMAP(R3) ; ALLOCATED 200$: LOADUBA ; LOAD EXECUTE LIST PTE'S INTO MAP REGS MOVL IRP$L_UBADDR(R3),R0 ; GET TMA UNIBUS ADDRESS SETTMA ; SET TMA/MAE REGS TO ADDRESS BBC #IRP$V_EXTEND,- ; CHECK IF IRP EXTENSION IRP$W_STS(R3),210$ ; CLEAR. IF SO, SKIP ; REPLY LIST ALLOCATION MOVL IRP$L_EXTEND(R3),R2 ; GET EXTENSION ADDRESS MOVL IRPE$L_SVAPTE1(R2),- ; COPY REPLY LIST SVAPTE UCB$L_SVAPTE(R5) ; TO SAME UCB FIELD MOVW IRPE$W_BOFF1(R2),- ; AND BYTE OFFSET UCB$W_BOFF(R5) MOVW IRPE$L_BCNT1(R2),- ; AND BYTE COUNT UCB$W_BCNT(R5) BBS #VEC$V_MAPLOCK,- ; CHECK IF REPLY LIST UBA IRPE$L_DPRMAP(R2),- ; RESOURCES ALLOCATED. IF SO, 220$ ; GO LOAD UP REGS. REQDPR ; DATA PATH FOR REPLY LIST REQMPR ; REQUEST UBA WINDOW FOR REPLY LIST ; USING UCB SVAPTE, BOFF, BCNT. ; R2 GETS CLOBBERED ABOVE!!! MOVL IRP$L_EXTEND(R3),R2 ; GET IRP EXTENSION ADDRESS MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS MOVL CRB$L_INTD+VEC$W_MAPREG(R1),- IRPE$L_DPRMAP(R2) ; SAVE UBA PARAMETERS FOR REPLY LIST GETUBA UCB$W_BOFF(R5),- ; COMPUTE UNIBUS MEM ADDRESS CRB$L_INTD+VEC$W_MAPREG(R1),- IRPE$L_UBADDR(R2) ; AND SAVE FOR LATER BISW #VEC$M_MAPLOCK,- ; INDICATE REPLY LIST RESOURCES IRPE$L_DPRMAP(R2) ; ALLOCATED 220$: LOADUBA ; LOAD REPLY LIST PTE'S INTO MAP REGS MOVL IRP$L_EXTEND(R3),R2 ; RESTORE IRPE ADDRESS ; LOADUBA CLOBBERS IT!!! MOVL IRPE$L_UBADDR(R2),R0 ; GET RMA ADDRESS SETRMA ; SET KS 2050 RMA/MAE ADDRESS BRB 230$ ; CONTINUE WITH COMMON 210$: MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS NULLUBA CRB$L_INTD+VEC$W_MAPREG(R1),- CRB$L_INTD+VEC$B_NUMREG(R1),- R0 ; GET NULL UNIBUS MEM ADDRESS SETRMA ; FILL RMA ADDRESS TO STOP ; INVALID READ TRANSFER 230$: MOVW IRP$W_WCR(R3),- ; LOAD EXE LIST LENGTH TO WCR KS_W_WCR(R4) MOVW IRP$W_CDH(R3),- ; LOAD CDH FOR MEM FORMAT KS_W_CDH(R4) PUSHAB KS_PWR_LIO ; PWR FAIL ENTRY ADDRESS ; ; COMMON PROCESSING FOR ALL MODES FOLLOWING REGISTER ; INITIALIZATION. ; LOAD KS 2050 CTR FROM TEMPLATE AND PREPARE TO WAIT FOR ; I/O COMPLETION. ; KS_START_COM: ; COMMON START I/O PROCESSING POPL R0 ; GET PWR FAIL RETURN ADDR ; JUST IN CASE. ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME ASSUME SCT_M_GO,EQ,PCT_M_GO BISW #,- ; AND GO IN TEMPLATE CTR IRP$W_CTR(R3) DSBINT ; OLD IPL TO STACK, NEW=31 MOVW IRP$W_CTR(R3),- ; LOAD CONTROL REG TO START KS_W_CTR(R4) BBCC #UCB$V_POWER,- ; CHECK IF PWR FAIL DURING UCB$W_STS(R5),50$ ; CRITICAL PROCESSING ENBINT ; RESTORE OLD IPL JMP (R0) ; TRY AGAIN AT PWR FAIL ENTRY 50$: WFIKPCH KS_TIMEOUT,#KS_P_TOMAX ; WAIT FOR INTERRUPT HERE ; ; START_IO RESUMES HERE FOLOWING 'DONE'/'ERROR' INTERRUPT ; AT DEVICE IPL. IMMEDIATELY FORK TO DEVICE FORK IPL TO ; DISMISS THE INTERRUPT AND CONTINUE POST PROCESSING. ; IOFORK ; QUEUE DRIVER FORK PROCESS ; TO CONTINUE AND DISMISS THE INTERRUPT 70$: ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME BICW #SCT_M_IE,- ; DISABLE DONE/ERR INTERRUPTS KS_W_CTR(R4) .IF NE,KS_X_ERLS ; BEGIN 'ERLS' SWITCH BLOCK BITW #,- ; OR NON EXIST MEM KS_W_CTR(R4) BEQL 75$ ; IF NEITHER, SKIP ERROR LOG BBC #DEV$V_ELG,- ; ERR LOG ENABLED? UCB$L_DEVCHAR(R5),85$ ; IF NOT, GO INC ERR CNT JSB G^ERL$DEVICERR ; LOG ERROR FOR DEVICE BRB 75$ ; CONTINUE AFTER LOG 85$: INCW UCB$W_ERRCNT(R5) ; INCREMENT UNIT ERROR COUNT 75$: .ENDC ; END 'ERLS' SWITCH BLOCK BBCC #UCB$V_CANCEL,- ; CHECK IF CANCEL CLEAR UCB$W_STS(R5),80$ ; AND SKIP IF SO FOUND MOVZWL #SS$_CANCEL,R0 ; SET CANCEL TERMINATION BRB KS_POSTIO ; COMMON POST PROCESSOR 80$: MOVZWL #SS$_NORMAL,R0 ; SET NORMAL TERMINATION BRB KS_POSTIO ; COMMON POST PROCESSOR .DSABL LSB .ENABL LSB ;+++ ; ; KS_TIMEOUT: DEVICE TIMEOUT ROUTINE. ; ; KS_TIMEOUT is entered at device IPL with driver fork context. ; ; Inputs: ; R3 - UCB$L_FR3(IRP address) ; R4 - UCB$L_FR4(KS 2050 CTR address) ; R5 - UCB address. ; ; ;--- KS_TIMEOUT: ; DEVICE TIMEOUT ROUTINE ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME ASSUME SCT_M_SSP,EQ,PCT_M_SSP BICW #SCT_M_IE,KS_W_CTR(R4) ; CLEAR KS 2050 INT ENABLE BISW #SCT_M_SSP,KS_W_CTR(R4) ; SET KS 2050 SUSPEND BIT SETIPL UCB$B_FIPL(R5) ; LOWER TO DRIVER FORK IPL BBCC #UCB$V_TIMOUT,- ; CHECK FOR DEVICE TIMEOUT UCB$W_STS(R5),10$ ; AND SKIP IF CLEAR .IF NE,KS_X_ERLS ; BEGIN 'ERLS' SWITCH BLOCK BBC #DEV$V_ELG,- ; ERR LOG ENABLED? UCB$L_DEVCHAR(R5),80$ ; IF NOT, INC ERR COUNT JSB G^ERL$DEVICTMO ; LOG DEVICE TIMEOUT BRB 85$ ; CONTINUE AFTER LOG 80$: INCW UCB$W_ERRCNT(R5) ; INC UNIT ERROR COUNT 85$: .ENDC ; END 'ERLS' SWITCH BLOCK MOVZWL #SS$_TIMEOUT,R0 ; SET TIMEOUT STATUS BRB KS_POSTIO ; COMMON POST PROCESSOR 10$: BBCC #UCB$V_POWER,- ; CHECK PWR FAIL UCB$W_STS(R5),20$ ; AND SKIP IF CLEAR MOVZWL #SS$_POWERFAIL,R0 ; IF SET, DECLARE PWR FAIL BRB KS_POSTIO ; COMMON POST PROCESSOR 20$: MOVZWL #SS$_CANCEL,R0 ; SET CANCEL STATUS ; AS CATCH ALL .DSABL LSB .ENABL LSB ;+++ ; ; KS_POSTIO: COMMON POST I/O PROCESSING ; ; KS_POSTIO is entered at device fork IPL in ; device driver context. ; ;--- KS_POSTIO: ; COMMON I/O POST PROCESSOR ASSUME SCT_M_M,EQ,PCT_M_M ; ASSUME SERIAL AND PARALLEL SAME EXTZV #SCT_V_M,#SCT_S_M,- ; GET MODE FROM IRP CTR IRP$W_CTR(R3),R2 ; TEMPLATE REGISTER MOVL R0,IRP$L_IOST1(R3) ; SAVE TERMINATION STATUS CASEB R2,#0,#KS_P_MAXM ; VECTOR TO MODE POST PROCESSOR 10$: .WORD KS_POST_PIO-10$ ; MODE 0(PROGRAMMED I/O) .WORD KS_POST_DIO-10$ ; MODE 1(Q-SCAN; SINGLE DMA) .WORD KS_POST_DIO-10$ ; MODE 2(Q-STOP; SINGLE DMA) .WORD KS_POST_DIO-10$ ; MODE 3(STOP; SINGLE DMA) .WORD KS_POST_LIO-10$ ; MODE 4(LIST; MULTIPLE DMA) .WORD KS_POST_BUG-10$ ; MODE 5 INVALID .WORD KS_POST_BUG-10$ ; MODE 6 INVALID .WORD KS_POST_BUG-10$ ; MODE 7 INVALID .WORD KS_POST_DIO-10$ ; MODE 8(Q-REP; SINGLE DMA) ; ; SAFETY VALVE ; KS_POST_BUG: BUG_CHECK HALT,FATAL ; BUG CHECK HERE IF INVALID MODE KS_POST_PIO: ; PROG I/O POST PROCESSOR BLBS IRP$L_IOST1(R3),- ; IF SUCCESSFUL, CONTINUE 20$ CLRL IRP$L_IOST2(R3) ; CLEAR DEVICE INFO BRW KS_REQCOM ; DECLARE REQUEST COMPLETE 20$: BBC #IRP$V_FUNC,- ; CHECK IF PIO READ IRP$W_STS(R3),30$ ; AND SKIP IF NOT MOVW KS_W_DLR(R4),- ; SAVE DATA LOW TO IRP IRP$W_DLR(R3) MOVW KS_W_CDH(R4),- ; AND DATA HIGH TOO IRP$W_CDH(R3) CLRB IRP$W_CDH+1(R3) ; ZERO CRATE NUMBER MOVAB IRP$W_DLR(R3),R1 ; GET DATA BUFFER ADDRESS BSBW KS_MOVTOUSR ; MOVE DATA TO USER BUFFER 30$: MOVZWL KS_W_CTR(R4),- ; GET CONTROL REG IRP$L_IOST1(R3) ; FOR IOSB BISW #SS$_NORMAL,- ; SET SUCCESS BIT IRP$L_IOST1(R3) INSV IRP$W_BCNT(R3),- ; RETURN BYTE COUNT #16,#16,- ; FOR IOSB IRP$L_IOST1(R3) .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK MOVZWL KS_W_SES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK MOVZWL KS_W_PES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END PARALLEL BLOCK BRW KS_REQCOM ; PIO REQUEST COMPLETE KS_POST_DIO: ; MODE1,2,3 POST PROCESSOR PURDPR ; PURGE BUFFERED DATA PATH RELMPR ; RELEASE UBA MAP REGS RELDPR ; RELEASE DATA PATH MOVL UCB$L_IRP(R5),R3 ; GET ADDR OF IRP ; PURDPR CLOBBERS IT!!! BLBS IRP$L_IOST1(R3),- ; IF SUCCESS, CONTINUE 110$ CLRL IRP$L_IOST2(R3) ; CLEAR DEVICE INFO BRW KS_REQCOM ; COMPLETE CAMAC REQUEST 110$: MOVZWL KS_W_CTR(R4),- ; GET CONTROL REG FOR IRP$L_IOST1(R3) ; IOSB RETURN BISW #SS$_NORMAL,- ; SET SUCCESS BIT IRP$L_IOST1(R3) MOVW KS_W_WCR(R4),R0 ; GET NEG OF WORD COUNT REG SUBW IRP$W_WCR(R3),R0 ; CALC NET WORD XFER ASHL #1,R0,R0 ; CONVERT TO BYTE LENGTH INSV R0,#16,#16,- ; INSERT BYTE COUNT FOR IRP$L_IOST1(R3) ; IOSB RETURN .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK MOVZWL KS_W_SES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK MOVZWL KS_W_PES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END PARALLEL BLOCK BRW KS_REQCOM ; COMPLETE DIO OPERATION KS_POST_LIO: ; MODE 4 POST PROCESSOR MOVL UCB$L_CRB(R5),R1 ; LOCATE CRB BICW #VEC$M_MAPLOCK,- ; CLEAR ALLOCATION INDICATOR IRP$L_DPRMAP(R3) ; BEFORE LOADING TO CRB MOVL IRP$L_DPRMAP(R3),- ; RESTORE EXE LIST UBA PARMS CRB$L_INTD+VEC$W_MAPREG(R1) PURDPR ; PURGE EXE LIST DATA PATH RELMPR ; RELEASE EXE LIST MAP REGS RELDPR ; RELEASE EXE LIST DATA PATH MOVL UCB$L_IRP(R5),R3 ; GET CURRENT IRP ADDRESS BBC #IRP$V_EXTEND,- ; IF NO IRP EXTENSION, IRP$W_STS(R3),210$ ; SKIP REPLY LIST PROCESSING MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS MOVL IRP$L_EXTEND(R3),R2 ; GET EXTENSION ADDRESS BICW #VEC$M_MAPLOCK,- ; CLEAR ALLOCATION INDICATOR IRPE$L_DPRMAP(R2) ; BEFORE LOADING TO CRB MOVL IRPE$L_DPRMAP(R2),- ; RESTORE REPLY LIST UBA PARMS CRB$L_INTD+VEC$W_MAPREG(R1) PURDPR ; PURGE REPLY LIST DPR RELMPR ; RELEASE REPLY LIST MAP REGS RELDPR ; RELEASE REP LST DPR MOVL UCB$L_IRP(R5),R3 ; RESTORE IRP ADDRESS 210$: BLBS IRP$L_IOST1(R3),- ; IF SUCCESS, CONTINUE 230$ CLRL IRP$L_IOST2(R3) ; CLEAR DEVICE INFO BRW KS_REQCOM ; REQUEST COMPLETE 230$: MOVZWL KS_W_CTR(R4),- ; GET CONTROL REG IRP$L_IOST1(R3) ; FOR IOSB BISW #SS$_NORMAL,- ; SET SUCCESS BIT IRP$L_IOST1(R3) MOVZWL KS_W_WCR(R4),R0 ; FINAL WORD COUNT REG SUBW IRP$W_WCR(R3),R0 ; CALC NET XFER WORD COUNT ASHL #1,R0,R0 ; CONVERT TO BYTE COUNT INSV R2,#16,#16,- ; INSERT EXE LIST BYTE COUNT IRP$L_IOST1(R3) ; FOR IOSB .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK MOVZWL KS_W_SES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK MOVZWL KS_W_PES(R4),- ; GET ERR/STATUS REG FOR IRP$L_IOST2(R3) ; IOSB RETURN .ENDC ; END PARALLEL BLOCK BBC #IRP$V_EXTEND,- ; IF NO REPLY LIST, SKIP IRP$W_STS(R3),220$ ; LENGTH CALC MOVW KS_W_MAE(R4),R0 ; GET MAE REG FINAL STATE MOVZWL KS_W_RMA(R4),R1 ; AND RMA REG FINAL STATE EXTZV #MAE_V_RMA,#MAE_S_RMA,- ; GET RMA BITS FROM MAE R0,R0 INSV R0,#16,#MAE_S_RMA,R1 ; FORM UNIBUS RMA MOVL IRP$L_EXTEND(R3),R0 ; GET EXTENSION ADDRESS SUBL IRPE$L_UBADDR(R0),R1 ; CALC REPLY LIST XFER INSV R1,#16,#16,- ; INSERT REP LIST BYTE COUNT IRP$L_IOST2(R3) ; FOR IOSB 220$: .DSABL LSB .ENABL LSB ;+++ ; ; KS_REQCOM: CAMAC I/O REQUEST COMPLETE PROCESSING ; ;--- KS_REQCOM: RELCHAN ; RELEASE CONTROLLER MOVQ IRP$L_IOST1(R3),R0 ; GET IOSB IN R0,R1 FOR REQCOM BICW #KS_M_PH,R1 ; INDICATE SERIAL IOSB REQCOM ; I/O REQUEST COMPLETE .DSABL LSB .ENABL LSB ;++ ; KS_MOVTOUSR: MOVE DATA FROM SYSTEM ACCESSABLE BUFFER TO USER'S ; BUFFER. ; ; Inputs: ; R1 - address of data buffer to move from, ; R5 - address of UCB. ; Implicit inputs: ; UCB$L_SVAPTE- SVA of PTE for first page of user buffer, ; UCB$W_BOFF- byte offset in first page of buffer, ; UCB$W_BCNT- byte count to transfer, ; UCB$L_SVPN- system VPN to use to double map PTE's. ; ; Outputs: ; R1 points 1 beyond the end of the input buffer, ; R0 is destroyed. ; UCB$L_SVAPTE points to last PTE referrenced, ; UCB$W_BOFF consistent with last page referrenced. ;-- KS_MOVTOUSR: PUSHL R2 ; SAVE WORK REG MOVZWL UCB$W_BCNT(R5),R2 ; GET BYTE COUNT 10$: JSB G^IOC$FILSPT ; LOAD USER PTE FOR ACCESS ; FROM SVPN BISW UCB$W_BOFF(R5),R0 ; MASK IN BYTE OFFSET 20$: SOBGEQ R2,30$ ; LOOP UNTIL ALL TRANSFERRED POPL R2 ; RESTORE WORK REG RSB 30$: MOVB (R1)+,(R0)+ ; MOVE BYTE TO USER BUFFER BITW #^X1FF,R0 ; PAGE BOUNDARY? BNEQ 20$ ; IF NOT 0, NOT THE CASE ADDL #4,UCB$L_SVAPTE(R5) ; ADVANCE TO NEXT PAGE CLRW UCB$W_BOFF(R5) ; BYTE OFFSET=0 BRB 10$ ; RELOAD PTE FOR SVPN .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_ISRS KS 2050 INTERRUPT SERVICE ROUTINES ;++ ; KS_ISR_DONE: ISR FOR KS 2050 'DONE' INTERRUPT ; KS_ISR_ERR: ISR FOR KS 2050 'ERROR' INTERRUPT ; KS_ISR_DEMAND: ISR FOR KS 2050 'DEMAND' INTERRUPT ; ; Functional description: ; ; T.B.S. ; ; Inputs: ; ; 0(SP) - pointer to the address of the IDB (interrupt data ; block) ; 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 (program status longword) ; 32(SP) - saved PC ; ; The IDB contains the CSR address and the UCB address. ; ; Outputs: ; ; The routine must preserve all registers except R0-R5. ; ;-- KS_ISR_DONE: ; KS 2050 'DONE' ISR KS_ISR_ERR: ; KS 2050 'ERROR' ISR MOVL @(SP)+,R4 ; Get address of IDB and remove ; pointer from stack. MOVL IDB$L_OWNER(R4),R5 ; Get address of device owner's ; UCB. MOVL IDB$L_CSR(R4),R4 ; Get address of device's CSR. BBCC #UCB$V_INT,- ; If device does not expect UCB$W_STS(R5),- ; interrupt, dismiss it. DISMISS_INTERRUPT ; ; 'DONE'/'ERROR' INTERRUPT WAS EXPECTED. RETURN CONTROL TO ; DRIVER START_IO ROUTINE AT DEVICE IPL TO HANDLE DEVICE ; COMPLETION STATUS ANALYSIS. ; ; MOVL UCB$L_FR3(R5),R3 ; Restore driver's R3 (use a ; MOVQ to restore R3-R4). JSB @UCB$L_FPC(R5) ; Call driver at interrupt ; wait address. BRB DISMISS_INTERRUPT ; GO DISMISS THE INTERRUPT KS_ISR_DEMAND: MOVL @(SP)+,R4 ; GET IDB ADDRESS AND REMOVE ; POINTER FROM STACK MOVL IDB$L_CSR(R4),R1 ; GET CSR ADDRESS .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK BICW #DCR_M_SDIE,- ; DISABLE FURTHER DEMAND INTERRUPTS KS_W_DCR(R1) .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK BICW #PES_M_BDIE,- ; RESET BRANCH DEMAND INT ENABLE KS_W_PES(R1) .ENDC ; END PARALLEL BLOCK MOVL IDB$L_UCBLST(R4),R5 ; GET HIGHWAY UCB ADDRESS TSTL UCB$L_DMDAST(R5) ; DEMAND AST LIST VALID? BEQL DISMISS_INTERRUPT ; IF 0, NO ACB PRESENT MOVAL UCB$L_DMDAST(R5),R4 ; GET AST LISTHEAD ADDRESS JSB G^COM$DELATTNAST ; DELIVER DEMAND AST LIST BRB DISMISS_INTERRUPT ; GO DISMISS INTERRUPT KS_ISR_DISMISS: TSTL (SP)+ ; POP IDB ADDRESS FROM STACK ; ; Dismiss the interrupt. ; DISMISS_INTERRUPT: ; Dismiss interrupt. POPR #^M ; Restore R0-R5 REI ; Return from interrupt. .DSABL LSB .PAGE .ENABL LSB .SBTTL KS_CANCEL, Cancel I/O routine ;++ ; KS_CANCEL: Cancels an I/O operation in progress ; ; Functional description: ; ; This routine calls IOC$CANCELIO to set the cancel bit in the ; UCB status word if: ; ; the device is busy, ; the IRP's process ID matches the cancel process ID, ; the IRP channel matches the cancel channel. ; ; If IOC$CANCELIO sets the cancel bit, then this driver routine ; does device-dependent cancel I/O fixups. ; ; Inputs: ; ; R2 - negated value of the channel index number ; R3 - address of the current IRP (I/O request packet) ; R4 - address of the PCB (process control block) for the ; process canceling I/O ; R5 - address of the UCB (unit control block) ; ; Outputs: ; ; The routine must preserve all registers except R0-R3. ; ; The routine may set the UCB$M_CANCEL bit in UCB$W_STS. ; ;-- KS_CANCEL: ; Cancel an I/O operation JSB G^IOC$CANCELIO ; CHECK IF CURRENT IRP INCLUDED BBC #UCB$V_CANCEL,- ; IF NOT, RETURN UCB$W_STS(R5),10$ ; ELSE MOVL UCB$L_CRB(R5),R1 ; GET CRB ADDRESS MOVL @CRB$L_INTD+VEC$L_IDB(R1),- R1 ; GET CTR ADDRESS FOR KS 2050 ASSUME SCT_M_IE,EQ,PCT_M_IE ; ASSUME SERIAL AND PARALLEL SAME ASSUME SCT_M_SSP,EQ,PCT_M_SSP BICW #SCT_M_IE,KS_W_CTR(R1) ; CLEAR INT ENABLE BISW #SCT_M_SSP,KS_W_CTR(R1) ; SET SUSPEND BIT ; AND LET START I/O SORT IT OUT! 10$: MOVL UCB$L_HSU(R5),R1 ; GET HSU ADDRESS BEQL 20$ ; LINKED?? INVALID I/O DATA BASE IF NOT BBC #DEV$V_MNT,- ; CAMAC ACP MOUNTED? UCB$L_DEVCHAR(R1),20$ ; IF NOT, EXIT CANCEL I/O BBS #DEV$V_DMT,- ; MARKED FOR DISMOUNT? UCB$L_DEVCHAR(R1),20$ ; IF SO, EXIT CANCEL I/O BSBW KS_QCANIRP ; IF SO, QUEUE CANCEL IRP TO CAMAC ACP 20$: RSB ; RETURN .DSABL LSB .PAGE .SBTTL KS_QCANIRP, QUEUE CANCEL IRP TO CAMAC ACP .ENABL LSB ;++ ; ; KS_QCANIRP: QUEUE CANCEL IRP TO CAMAC ACP IF UNIT MOUNTED. ; ; Inputs: ; R2 - channel index(negated), ; R4 - current PCB address, ; R5 - address of UCB. ; ; ; Outputs: ; ;-- KS_QCANIRP: PUSHR #^M ; SAVE WORK REGS BSBW KS_ALOIRP ; ALLOCATE CANCEL IRP BLBC R0,90$ ; IF FAILURE, RETURN MOVL R2,R3 ; USE R3 TO REFERENCE IRP MOVB #DYN$C_IRP,- ; SET STRUC TYPE IRP$B_TYPE(R3) MOVB #IPL$_QUEUEAST,- ; SET FORK IPL IRP$B_RMOD(R3) MOVPSL R0 ; GET PSL VALUE EXTZV #PSL$V_PRVMOD,#PSL$S_PRVMOD,- R0,IRP$L_MEDIA(R3) ; SAVE FOR AFTER FORK MOVL PCB$L_PID(R4),- ; SAVE PCB PID FOR AFTER FORK IRP$L_MEDIA+4(R3) MOVW #IO$_DEACCESS,- IRP$W_FUNC(R3) ; SET FUNCTION CODE MOVB #31,IRP$B_EFN(R3) ; USE SYSTEM EVENT FLAG NUMBER MOVB PCB$B_PRIB(R4),- ; PROCESS BASE PRI IRP$B_PRI(R3) CLRL IRP$L_IOSB(R3) ; NO IOSB MOVW R2,IRP$W_CHAN(R3) ; SAVE CHANNEL INDEX CLRW IRP$W_STS(R3) ; CLEAR IRP STATUS MOVL R5,IRP$L_UCB(R3) ; SAVE UCB ADDRESS MOVL R3,R5 ; SET FORK BLOCK=IRP BSBB KS_FORKACP ; QUEUE FORK AT IPL$_QUEAST 90$: POPR #^M ; RESTORE WORK REGS RSB ; RETURN TO CANCEL I/O .DSABL LSB .ENABL LSB ;++ ; ; KS_FORKACP: FORK PROCESS TO QUEUE IRP TO ACP. ; ; Inputs: ; R3 - address of IRP, ; R5 - address of IRP(to be used as fork block first). ; ; Outputs: ; ;-- KS_FORKACP: FORK ; CREATE FORK PROCESS ; ; FORK PROCESS DISPATCHED HERE ; MOVB IRP$L_MEDIA,- ; SET UP IRP ACCESS MODE IRP$B_RMOD(R3) MOVL IRP$L_MEDIA+4(R3),- ; SET UP IRP PID IRP$L_PID(R3) CLRQ IRP$L_AST(R3) ; ZAP AST+AST PARM FIELDS MOVL IRP$L_UCB(R3),R2 ; GET UCB ADDRESS MOVL UCB$L_HSU(R2),R2 ; LOCATE HSU FROM UCB MOVL UCB$L_VCB(R2),R0 ; LOCATE VCB FROM UCB INCW VCB$W_TRANS(R0) ; INCREMENT TRANSACTION COUNT JSB G^IOC$WAKACP ; QUEUE IRP TO CAMAC ACP ; R2=UCB ADDRESS, ; R3=IRP ADDRESS RSB ; AND RETURN TO FORK DISPATCH .DSABL LSB .PAGE .IF NE,KS_X_ERLS ; BEGIN 'ERLS' SWITCH BLOCK .ENABL LSB .SBTTL KS_REG_DUMP, Device register dump routine ;++ ; KS_REG_DUMP: Dumps the contents of device registers to a buffer ; ; Functional description: ; ; Writes the number of device registers, and their current ; contents into a diagnostic or error buffer. ; ; Inputs: ; ; R0 - address of the output buffer ; R4 - address of the CSR (controller status register) ; R5 - address of the UCB (unit control block) ; ; Outputs: ; ; The routine must preserve all registers except R1-R3. ; ; The output buffer contains the current contents of the device ; registers. R0 contains the address of the next empty longword in ; the output buffer. ; ;-- KS_REG_DUMP: ; Dump device registers MOVZBL #KS_DUMP_CNT,(R0)+ ; Store device register count. MOVZWL KS_W_CTR(R4),(R0)+ ; DUMP CURRENT CTR STATE .IF DF,KS_X_SH ; BEGIN SERIAL BLOCK MOVZWL KS_W_SES(R4),(R0)+ ; DUMP CURRENT SES STATE .ENDC ; END SERIAL BLOCK .IF DF,KS_X_PH ; BEGIN PARALLEL BLOCK MOVZWL KS_W_PES(R4),(R0)+ ; DUMP CURRENT PES STATE .ENDC ; END PARALLEL BLOCK MOVZWL KS_W_CMR(R4),(R0)+ ; DUMP CURRENT CMR STATE MOVZWL KS_W_CDH(R4),(R0)+ ; DUMP CURRENT CDH STATE MOVZWL KS_W_DLR(R4),(R0)+ ; DUMP CURRENT DLR STATE MOVZWL KS_W_MAE(R4),(R0)+ ; DUMP CURRENT MAE STATE MOVZWL KS_W_TMA(R4),(R0)+ ; DUMP CURRENT TMA STATE MOVZWL KS_W_RMA(R4),(R0)+ ; DUMP CURRENT RMA STATE MOVZWL KS_W_WCR(R4),(R0)+ ; DUMP CURRENT WCR STATE MOVL UCB$L_IRP(R5),R3 ; GET CURRENT IRP BEQL 10$ ; IF NO CURRENT, BUG CHECK MOVL IRP$L_UBADDR(R3),(R0)+ ; COPY UBA ADDRESS FIELD MOVL IRP$L_DPRMAP(R3),(R0)+ ; AND UBA PARAMETERS BBC #IRP$V_EXTEND,- ; IF NO IRP EXTENSION, SKIP IRP$W_STS(R3),20$ MOVL IRP$L_EXTEND(R3),R2 ; LOCATE EXTENSION MOVL IRPE$L_UBADDR(R2),(R0)+ ; GET REPLY LIST UBA ADDRESS FIELD MOVL IRPE$L_DPRMAP(R2),(R0)+ ; AND REP LIST UBA PARAMETERS BRB 30$ ; GO TO RETURN 20$: CLRQ (R0)+ ; ZERO EXTENSION PARAMETERS 30$: RSB ; RETURN TO VMS ; ; INVALID IRP IN UCB THAT LOGGED ERROR ; 10$: BUG_CHECK HALT,FATAL ; ISSUE FATAL BUG CHECK .DSABL LSB .PAGE .ENDC ; END 'ERLS' SWITCH BLOCK .SBTTL KS_END, End of driver ;++ ; Label that marks the end of the driver ;-- KS_END: ; Last location in driver .END