.TITLE YRDRV .IDENT /12.2XB/ ; RECEIVER DL11 DRIVER ; RECEIVE HALF ONLY (1ST CSR/DATA REG OF PAIR) LD$YR=0 ;REMOVE IF RESIDENT ; DL11 ASYNCHRONOUS COMMUNICATIONS DRIVER ACTING LIKE TT PORT ; ; INPUT TERMINATION ON HEX FF (377 OCTAL) CHARACTER. ALSO ON ; BYTE COUNT... ; ; MACRO LIBRARY CALLS ; .MCALL HWDDF$,PKTDF$ HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET OFFSETS .MCALL UCBDF$,CUCDF$ UCBDF$ ; DEFINE UCB OFFSETS CUCDF$ ;COMMUNICATIONS UCB LABELS ; ; CONFIGURATION DEPENDENT PARAMETERS ; ; ; EQUATED SYMBOLS ; ; ; RXCSR BIT ASSIGNMENTS ; DTSTCH= 100000 ;DATA SET CHANGE RING= 40000 ;RING LINE ASSERTED CTS= 20000 ;CLEAR TO SEND CRRIER= 10000 ;CARRIER STATE RECACT= 4000 ;RECEIVER ACTIVE RXDONE= 200 ;RECEIVER DONE RCVENB= 100 ;RECEIVER INTERRUPT ENABLE DSINTE= 40 ;DATA SET CHANGE INTERRUPT ENABLE RTS= 4 ;REQUEST TO SEND TRMRDY= 2 ;DATA TERMINAL READY ; ; RXDBUF BIT ASSIGNMENTS ; RXERR= 100000 ;RECEIVER ERROR "OR" BIT OVRNER= 40000 ;RECEIVER OVERRUN ERROR IF SET FRMERR= 20000 ;RECEIVER FRAMING ERROR ; ; TXCSR BIT ASSIGNMENTS ; TXRDY= 200 ;TRANSMITTER DONE BIT TXINTE= 100 ;TRANSMITTER INTERRUPT ENABLE BIT BREAK= 1 ;CLAMP OUTPUT TO SPACE ; ; LOCAL DATA ; ; ; UNIT IMPURE DATA TABLE (INDEXED BY UNIT, POINTS TO UCB) ; D$$E11=1 CNTBL: ;REF LABEL UNITBL: ;UCB ADDRESSES .REPT D$$E11 .WORD 0 ;ENSURE SET TO ZERO .ENDM .IF GT D$$E11-1 TEMP: ;REF LABEL UNIT: .BLKW 1 ;TEMPORARY STORAGE FOR UNIT NUMBER .ENDC .ENABL LSB ; ; DRIVER DISPATCH TABLE ; $YRTBL::.WORD DLINIT ;DEVICE INITIALIZATION .WORD DLCANC ;DEVICE I/O CANCELLATION .WORD DLTMO ;TIMEOUT ENTRY POINT .WORD DLPWRF ;POWER FAIL ROUTINE ;+ ;**- DLINIT - DL-11 SYNCHRONOUS COMMUNICATION CONTROLLER I/O INITIATOR ; ; DLINIT IS ENTERED WHEN AN I/O REQUEST IS QUEUED ON THE DEVICE, ; AND AT THE END OF EACH QIO REQUEST WHICH OBEYS THE ; NORMAL RSX-11M INPUT/OUTPUT LOGIC FLOW. IF THE DEVICE IS ; AVAILABLE AND A REQUEST IS IN THE QUEUE FOR THAT UNIT, ; THE REQUEST IS INITIATED. ; IF NO REQUEST EXISTS FOR THAT UNIT OR IF IT IS ; BUSY, AN EXIT IS TAKEN TO THE CALLER. NOTE THAT BECAUSE OF ; THE NATURE OF THE DL-11, EACH UNIT IS A CONTROLLER ITSELF, ; HAS ITS OWN SCB, AND THEREFORE ITS OWN QUEUE. ; EACH TIME DLINIT IS CALLED, IT IS CALLED TO SERVICE ONLY ; THE UNIT SPECIFIED IN THE CALL. NOTE ALSO THAT ONLY ; 8-BIT, NO PARITY DATA IS SUPPORTED. ; ; INPUTS: ; ; R4 = STATUS CONTROL BLOCK ADDRESS ; R5 = ADDRESS OF THE UCB TO BE INITIATED. ; ; OUTPUTS: ; ; IF A REQUEST IS SUCCESSFULLY DEQUEUED, THE ; DEVICE IS INITIATED APPROPRIATELY. ;- .IIF NDF,$$XDT,NRM$YD=0 ; ASSEMBLE WITHOUT XDT NORMALLY DLINIT: .IF DF,NRM$YD ; NOP .IFF BPT ;DEBUG XDT CALL .ENDC CALL $GTPKT ;GET AN I/O PACKET TO PROCESS BCS 140$ ;NO REQUEST OR UNIT BUSY ; ; SAVE UCB ADDRESS MOV R5,UNITBL ; NOTE MUST USE UNITBL(R3) IF MULTI-UNIT DRIVER ; (CHECK IF R3 IS BYTE OR WORD OFFSET ALSO...) ; ; THE FOLLOWING ARGUMENTS ARE RETURNED BY $GTPKT: ; ; R1 = ADDRESS OF THE I/O REQUEST PACKET. ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3 = CONTROLLER INDEX ; R4 = ADDRESS OF THE STATUS CONTROL BLOCK. ; R5 = ADDRESS OF THE UCB SPECIFIED IN THE ; DLINIT CALL. ; ; DL11 I/O REQUEST PACKET FORMAT ; ; WORD CONTENT ; ; 0 I/O QUEUE THREAD WORD ; 1 REQUEST PRIORITY, EVENT FLAG NUMBER ; 2 ADDRESS OF THE TCB OF THE REQUESTER TASK ; 3 POINTER TO SECOND LUN WORD IN TASK HEADER ; 4 CONTENTS OF FIRST LUN WORD (UCB) ; 5 I/O FUNCTION CODE ; 6 VIRTUAL ADDRESS OF I/O STATUS BLOCK ; 7 RELOCATION BIAS OF I/O STATUS BLOCK ; 10 I/O STATUS BLOCK ADDRESS (REAL OR DISPLACEMENT +140000) ; 11 VIRTUAL ADDRESS OF AST SERVICE ROUTINE ; 12 RELOCATION BIAS OF I/O BUFFER ; 13 BUFFER ADDRESS FOR TRANSFER ; 14 TOTAL BYTE COUNT TO TRANSFER ; 15 BYTE COUNT FOR SECOND PART OF TRANSMISSION OR 0 ; 16 NOT USED ; 17 NOT USED ; 20 NOT USED ; MOV S.CSR(R4),R2 ;GET RECEIVER CSR ADDRESS ADD #I.FCN+1,R1 ;POINT TO I/O FUNCTION CODE CMPB #IO.RVB/256.,(R1);READ VIRTUAL? BEQ 20$ ; IF SO TREAT LIKE READ LOGICAL CMPB #IO.WVB/256.,(R1);WRITE VIRT? BEQ 24$ ;IF SO GO HANDLE CMPB #IO.INL/256.,(R1) ;CHECK IF TRANSFER FUNCTION BLOS 40$ ;BRANCH ON CONTROL FUNCTION CMPB #IO.RLB/256.,(R1) ;READ LOGICAL? BEQ 20$ ;YES, SERVICE READ REQUEST ; ; FALL THROUGH ON TRANSMIT (WRITE LOGICAL) ; 24$: BR DLSUCC ;TRANSMIT...RETURN ALL WELL ;(REALLY NOTHING TO DO...) ; ; RECEIVE FUNCTION INITIATION ; 20$: ;REFERENCE LABEL 30$: ;REF LABEL ; SET UP TIMEOUT MOVB S.ITM(R4),S.CTM(R4) ;INIT TIMER... MOV R5,R0 ;SET UP TRANSFER VECTOR ADD #U.RBUF,R0 ;RECEIVE TRANSFER INFORMATION HERE MOV U.BUF(R5),(R0)+ ;TRANSFER BIAS MOV U.BUF+2(R5),(R0)+ ;AND VIRTUAL ADDRESS MOV U.CNT(R5),(R0) ;AND COUNT TSTB 2(R2) ; CLEAR RECEIVE BUFFER STATUS BIS #RCVENB,(R2) ; ENABLE RECEIVER BR 140$ ;RETURN - INTERRUPT CODE PROPAGATES RECEIVE ; ; CONTROL FUNCTION INITIATION (INITIATE OR TERMINATE CONTROLLER, ; OR CHANGE OPERATING MODE) ; 40$: BNE 70$ ;IF NOT EQUAL, MODE CHANGE REQUEST ;WMG015 CLR (R2) ;CLEAR RXCSR ; ; DO START FUNCTION INITIATION ; MOV R5,UNITBL(R3) ;INITIALIZE UCB ADDRESS IN UNIT TABLE BR 120$ ;RETURN SUCCESSFUL ; ; SERVICE DEVICE MODE CHANGE REQUEST ; 70$: ; DLSUCC: ;REFERENCE LABEL 120$: MOV #IS.SUC&377,R0 ;RETURN SUCCESSFUL STATUS DLFIN: ;REFERENCE LABEL 130$: CLRB S.STS(R4) ;CLEAR CONTROLLER STATUS BICB #US.BSY,U.STS(R5) ;CLEAR UNIT STATUS MOV R0,-(SP) ;SAVE STATUS WORD 1 MOV S.PKT(R4),R1 ;GET I/O PKT ADDRESS MOV R1,-(SP) ;SAVE PKT ADDRESS TO STASH IN R3 FOR $IOFIN ; HERE TRY AND COMPUTE THE REAL COUNT READ... ; DO SO BY SUBTRACTING U.RCNT FIELD FROM R1 TO GET ; NUMBER OF BYTES ACTUALLY SENT... MOV I.PRM+4(R1),R1 ;AND REQUESTED BYTE COUNT SUB U.RCNT(R5),R1 ;SUBTRACT BYTES NOT TRANSFERRED (IF ANY) MOV R1,-(SP) ;SAVE ON STACK FOR A CALL TO DLINIT... CALL DLINIT ;ATTEMPT TO INITIATE SOMETHING ; WITH A HARD CODED TERMINATOR POSSIBLE, GOTTA RETURN WHAT WE ; ACTUALLY READ... MOV (SP)+,R1 ;GET BYTES TRANSFERRED AS STATUS WORD MOV (SP)+,R3 ;GET I/O PKT ADDRESS TO FINISH ON... MOV (SP)+,R0 ;RESTORE STATUS WORD 1 CALLR $IOFIN ;TERMINATE LAST PACKET 140$: RETURN ; ; POWER FAIL SERVICE ; DLPWRF: ;REFERENCE LABEL CLRB S.CTM(R4) ;DISABLE TIMEOUTS MOV #IE.DNR$377,R0 ;NOT RDY BR 130$ ;FINISH I/O ; ; I/O CANCELLATION ; DLCANC: ;;;REFERENCE LABEL CMP R1,I.TCB(R0) ;;;CANCEL FOR THIS TASK? BNE 140$ ;;;JUST RETURN IF NOT CMPB #IO.WLB/256.,I.FCN+1(R0) ;;;WAS FUNCTION TRANSMIT? BEQ 140$ ;;;JUST LET FINISH IF YES TST U.RCNT(R5) ;;;RECEIVE FINISHED? BLE 140$ ;;;BR IF YES BIC #RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER MOV #IE.ABO&377,R0 ;;;PUT ERROR CODE IN R0 CLR U.RCNT(R5) ;;;MARK COUNT SATISFIED BR 150$ ;;;FINISH OFF I/O ; ; TIMEOUT SERVICE ROUTINE ; ; INPUTS: ; ; R0 = DEVICE TIMEOUT STATUS 'IE.DNR' ; R3 = CONTROLLER INDEX ; R4 = ADDRESS OF SCB ; R5 = ADDRESS OF UCB ; DLTMO: ;;;TIMEOUT ENTRY POINT ; MOV S.CSR(R4),R3 ;;;GET RECEIVER CSR ;;; FORCE RECEIVER NOT TO HAVE ANY MORE INTERRUPTS... BIC #RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER 150$: ;;;REFERENCE LABEL MTPS #0 ;;;ALLOW INTERRUPTS MOV U.SCB(R5),R4 JMP DLFIN ;;;WAIT FOR SOFTWARE TIMEOUT TO FINISH .DSABL LSB ; ; **- $YRINT - DL-11 INPUT INTERRUPT SERVICE ; $YRINT:: ;;;REFERENCE LABEL INTSV$ YR,PR5,D$$E11 ;;;GENERATE INTERRUPT SAVE CODE CALL DLSET ;;;SET CSR IN R4, UCB IN R5 MOV (R4),-(SP) ;;;SAVE CSR, TEST DATA SET CHANGE 10$: MOV 2(R4),R4 ;;;CAPTURE BUFFER REGISTER IN R4 20$: TSTB (SP)+ ;;;RECEIVER DONE? BPL 70$ ;;;IF NOT, DISMISS INTERRUPT TST U.RCNT(R5) ;;;COUNT ALREADY SATISFIED? BLE 70$ ;;;IF SO, DISMISS INTERRUPT 60$: ;;;REFERENCE LABEL .IF DF M$$MGE MOV KISAR6,-(SP) ;;;SAVE CURRENT MAPPING MOV U.RBUF(R5),KISAR6 ;;;MAP TO USER BUFFER MOVB R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER MOV (SP)+,KISAR6 ;;;RESTORE CURRENT MAPPING .IFF MOVB R4,@U.RBUF+2(R5) ;;;STORE BYTE IN USER BUFFER .IFTF DEC U.RCNT(R5) ;;;SEE IF COUNT SATISFIED BLE 80$ ;;;YES, IF EQUAL INC U.RBUF+2(R5) ;;;BUMP BYTE ADDRESS .IFT BIT #20000,U.RBUF+2(R5) ;;;OVERFLOWED 4K BOUNDARY? BEQ 73$ ;;;NO, IF ZERO BIC #20000,U.RBUF+2(R5) ;;;CLEAR OVERFLOW BIT ADD #200,U.RBUF(R5) ;;;BUMP BIAS .ENDC 73$: ;;; CHECK FOR TERMINATOR CHARACTER AND END RIGHT NOW IF WE GOT IT. ;;; HARDCODED TERMINATOR IS 377 OCTAL CMPB R4,(PC)+ ;;; COMPARE TO BYTE IN NEXT WORD YRTRM==. .WORD 177777 ;;; BYTE OF FF HEX (DUPLICATED FOR ;;; THE HECK OF IT...) IN GLOBAL. ;;; ;;; REVERSE THE SENSE OF THE CONDITIONAL "INCLTR" TO EXCLUDE ;;; THE TERMINATOR OR INCLUDE IT IN THE BUFFER. IF THE PARAMETER ;;; IS DEFINED, THE TERMINATOR CHARACTER IS INCLUDED IN THE COUNT ;;; BUT OTHERWISE IT IS EXCLUDED. ;;; .IF DF,INCLTR ;THIS CODE IF TERMINATOR CHARACTER IS TO BE INCLUDED IN BUFFER BEQ 80$ ;;; IF EQ THEN FINISH RIGHT NOW... .IFF BNE 70$ INC U.RCNT(R5) ;;;COUNT BACK THE TERMINATOR BR 80$ .ENDC 70$: ;;;REFERENCE LABEL RETURN ;;;EXIT INTERRUPT ; ; REQUEST SATISFIED ; 80$: ;;;REFERENCE LABEL MOV U.SCB(R5),R4 ;;;GET SCB ADDRESS BIC #RCVENB,@S.CSR(R4) ;;;DISABLE RECEIVER CALL $FORK ;;;GO TO FORK LEVEL JMP DLSUCC ;FINISH I/O SUCESSFUL ; ; ; DLSET - SET UP REGISTER R4 WITH CSR ADDRESS, R5 WITH ; UCB ADDRESS. UNIT NUMBER IN LOW ORDER 4 BITS OF UNIT. ; DLSET: ;;;REFERENCE LABEL TST R5 ;;;CHECK FOR UCB ADDRESS BEQ 10$ ;;;IF NO UCB, TROUBLE MOV U.SCB(R5),R4 ;;;FIRST GET SCB ADDRESS MOVB S.ITM(R4),S.CTM(R4) ;;;RESET TIMEOUT. MOV S.CSR(R4),R4 ;;;NOW DEVICE CSR ADDRESS RETURN ;;;AND NOW RETURN 10$: TST (SP)+ ;;;CLEAR STACK OF RETURN ADDRESS DLSXT: JMP $INTXT ;;;DISMISS INTERRUPT .END