.TITLE DIGITAL LOOPBACK TEST .PSECT DLTEST,Con .Ident /LVL51C/ .MCALL $LIST, $ALVIN, $SkipList, $IfTSX .GLOBL DLTEST ;COMMAND ENTRY POINT - INTERNAL .GLOBL DECPRT ;EXTERNAL ROUTINE TO CONVERT TO DECIMAL .Globl GetYN, CrLf, Receive, Send, ConsKB, GetByte .Globl BufD1, BufCount, Ldevice, DecPrt, GetDecimal .Globl AlvEnable, AlvDisable, AlvUpdate, AlvIdle ;;********************************************************************** .sbttl Loopback Command Handler ;; ;; Alvin command to do a digital loopback test. ;; Entered 3-FEB-82 DVJensen. ;; Updated 7-Apr-86 DJ for selection port to be tested. ;; Debugged 7-May-86 DJ. ;; $ALVIN ; ERRCNT=LWORK1 ;ERROR COUNT REGISTER OFFSET ; DLIN=2 ; Alvin logical unit of the receiver to be tested. ; DLOUT=3 ; Alvin logical unit of the transmitter to be tested. ;;********************************************************************** ;; DLTEST:: $LIST $SkipList $SkipList $SkipList $SkipList Jsr pc,crlf $SkipList < Unit# - The following ports are defined: > Jsr Pc,Crlf Mov #Ldevice,R1 ; Get the device table descriptor address. Mov (R1),R3 ; Get the start of the device table. Clr R4 Ploop: Mov R4,LUN ; The logical unit number. Jsr R5,DecPrt ; Print the logical unit number. .Word LUN Mov (R3)+,R2 ; Get the next device descriptor. Bne convert ; If non-zero it exists. $List < - is not a defined logical unit.> Jmp Next Convert: Mov DevAdr(R2),CSR ; Get the CSR address of the Port. Mov Vector(R2),Vect ; Get the Vector address of the LUN. Jsr R5,CnvOct ; Convert the CSR to octal char string. .Word CSR ; CSR value pointer. .Word CSRstr ; String storage pointer. Jsr R5,CnvOct ; Convert the Vector to octal char string. .Word Vect ; Vector value. .Word VecStr ; String Storage. Mov #VecStr+3,R5 ; Use only the last three digits. Mov #VecMsg,R0 ; Actual message. Movb (R5)+,(R0)+ Movb (R5)+,(R0)+ Movb (R5)+,(R0)+ $List ,PortMsg Bit #Output,Lctl(R2) ; Is this a receiver or transmitter? Beq Inmsg $List < - Transmitter.> Br RTChk InMsg: $list < - Receiver. > RTchk: Bit #RTctl,Lctl(R2) ; Is this the console? Beq ChkCL ; No, branch $List < - RT console.> Jmp Next ChkCL: Bit #CLctl,Lctl(R2) ; Is this a CL controlled device? Beq ChkCSR ; No, branch Movb CLunit(R2),Unit ; Get the CL unit number. Jsr R5,CnvOct ; Convert the CL unit to octal char string. .Word Unit ; CL unit pointer. .Word CLstr ; String storage pointer. Movb CLend,CLstr ; Move the CL unit number. $List ,CLmsg Movb TSXLINE(R2),Term ; Get the TSX line to be taken over by CL. Beq ChkCsr ; If zero, the CL unit must already be setup. $List <, line> Jsr R5,DecPrt ; List the decimal value of the terminal line. .Word Term ChkCsr: $IFtsx ,Next ; If not running under TSX check the CSR. Cmp CSR,#160000 ; Check validity of CSR. Bhi ChkVec ; Branch if in the I/O page. $list < - Bad CSR!> ChkVec: Cmp Vect,#500 ; Check validity of the Vector. Bhi BadVec ; Branch if vector too high. Cmp Vect,#60 Bhis Next ; Branch if vector above system vectors. BadVec: $list < - Bad Vector!> Next: Jsr Pc,crlf ; Go to a new line. Inc R4 ; Skip to next LUN. Cmp R3,2(R1) ; Is this all the LUN's in the table? Bhi Getit ; Leave print loop when done. Jmp PLoop ; Loop to print the next LUN if not done. Getit: Mov LUN,Rmax Mov LUN,Xmax SelR: Jsr R5,GetDecimal ; Get the receiver unit number. .Word GetRcv ; Prompt .Word 2 ; Minimum Rmax: .Word 16. ; Maximum Br Rexit ; Break exit. Br Selrgo Rexit: Jmp LBexit Selrgo: Mov R0,RecvU ; Save the unit number Asl R0 ; Multiply by two (Maybe should use GETDDA) Add (R1),R0 ; Get the unit entry in the table. Mov (R0),R2 ; Get the device descriptor address. Bne Rcvchk ; Branch if defined. BadRcv: $Skiplist Br SelR Rcvchk: Bit #Output,Lctl(R2) ; Is this actually allowed to receive? Bne BadRcv Mov RecvU,R3 ; Get the unit number Jsr Pc,AlvEnable ; Attempt to enable the unit. Bcc SelX ; Branch if no problem enabling. Mov R0,ErrCode ; Save the error code. $Skiplist Jsr R5,Decprt .Word ErrCode Br SelR SelX: Jsr R5,GetDecimal ; Get the Transmitter unit number. .Word GetXmit ; Prompt .Word 2 ; Minimum Xmax: .Word 16. ; Maximum Br Xexit ; Break exit. Should disable the rcvr. Br Selxgo Xexit: Jmp RClean Selxgo: Mov R0,XmitU ; Save the unit number Asl R0 ; Multiply by two Add (R1),R0 ; Get the unit entry in the table. Mov (R0),R2 ; Get the device descriptor address. Bne Xchk ; Branch if defined. BadX: $Skiplist Br SelX Xchk: Bit #Output,Lctl(R2) ; Is this actually allowed to transmit? Beq BadX Mov XmitU,R3 ; Get the unit number Jsr Pc,AlvEnable ; Attempt to enable the unit. Bcc Again ; Branch if no problem enabling. Mov R0,ErrCode ; Save the error code. $Skiplist Jsr R5,Decprt .Word ErrCode Br SelX .Sbttl Run Loopback Test AGAIN: JSR R5,GETYN ;GET THE OK TO GO ON .WORD OKSTRING Br Cleanup Br Cleanup ;IF BREAK OR NO, EXIT Br Doit ; If yes, do the loopback. Cleanup: Mov XmitU,R3 ; Disable the transmitter. Jsr Pc,AlvDisable Rclean: Mov RecvU,R3 Jsr Pc,AlvDisable ; Disable the receiver. LBexit: $SkipList Rts PC Doit: CLR BLKCNT ;INITIALIZE CLR BLKERS JSR PC,CRLF ;GO TO A NEW LINE CONSENA: JSR R5,RECEIVE ;SETUP A PENDING RECEIVE FROM THE CONSOLE .WORD KEYB!UseDB ; Use the default buffer. .WORD 0 Nop ; (Keyboard should be available) LOOP: Inc BlkCnt ; Count each block transmitted. ; First do a dummy receive to flush any junk which may be in a CL buffer. Mov RecvU,R3 ; Get the unit number of requested receiver. Bis #Reset,R3 ; Force the buffer to be reset. JSR R5,RECEIVE ; Enable the RECEIVER. .WORD -1 ; (The unit/function is in Reg 3.) .WORD INBUF ;BUFFER DESCRIPTOR Br Rcvfail ; (Unit should be available) error exit. Mov R0,Recver ; Save the Descriptor address of the Recver. Clr ERRCNT(R0) ; Clear ERROR COUNT in control block. ; The initial receive should have immediatly transmitted all remaining chars ; in the CL system buffers to the INBUF, presuming INBUF is large enough. ; Now, start over and get what is about to be transmitted: Mov RecvU,R3 ; Get the unit number of requested receiver. Bis #Reset,R3 ; Force the buffer to be reset. JSR R5,RECEIVE ; Enable the RECEIVER. .WORD -1 ; (The unit/function is in Reg 3.) .WORD INBUF ;BUFFER DESCRIPTOR Br Rcvfail ; (Unit should be available) error exit. Br RcvSet ; Go on if receive went OK. RcvFail: $SkipList Jmp Cleanup ; Exit RcvSet: Mov xmitU,R3 ; Get the TRANSMITTER unit number. Bis #String,R3 ; Force the function bit. JSR R5,SEND ; SEND the string .WORD -1 ; to the OUTPUT port set in R3. .WORD TESTRING ; The test string (static desc). Br XmitFail ; (The unit should not be seized.) error exit. Br XmitSet XmitFail: $SkipList Jmp Cleanup ; Exit. XmitSet: Mov R0,Xmiter ; Save the device desc adr of the transmitter. MOV #TESTRING,R3 MOV 2(R3),R1 ; Get end adr of string sent. SUB (R3),R1 ; Calc difference from begin adr. INC R1 ; Count of characters sent. MOV R1,NUMSENT ; Save number of chars sent. Mov #InBuf,R4 ; Put the buffer desc adr in Reg 4. Mov #1000.,R2 ; Maximum wait count. WAITLP: Jsr Pc,AlvIdle ; Due to TSX system buffering, we cannot ; presume that everything is sent yet. ;; AlvIdle will typically wait for 2-4 clock ticks for each call. ;; Rather than wait an arbitrary long length of time, it would be better ;; to count the chars buffered, and if all received, proceed: JSR PC,BUFCOUNT ; Count the characters received in InBuf. Cmp R0,NumSent ; Is this the same as what was sent? Bhis Matchup ; Yes, then presume we have it all. Dec R2 ; Give last char(s) a chance to loopback. BNE WAITLP ; Count down for maximum wait period. ;; (1000 waits of 2 clock ticks each will delay ~30 seconds.) Matchup: JSR PC,BUFCOUNT ; Count the characters received in InBuf (R4). MOV R0,NUMRECEIVED ; COUNT RETURNED IN R0 CMP R0,NumSent ; SAME NUMBER OF CHARS RECEIVED AS SENT? BEQ DLT60 ;YES, BRANCH JSR R5,DECPRT ;PRINT DIFFERENT NUM CHARS MSG .WORD NUMRECEIVED $LIST JSR R5,DECPRT ;"12345 OF 12345 CHARS RECEIVED BACK. " .WORD NUMSENT $LIST BR PRTBLK DLT60: Mov Recver,R2 ; Get the address of the receiver desc. MOV ERRCNT(R2),ERRORS ;WERE THERE RECEIVER ERRORS? BEQ DLT70 ;NO, BRANCH JSR R5,DECPRT ;PRINT THE NUMBER OF CHARARACTERS IN ERROR .WORD ERRORS $LIST PRTBLK: JSR R5,DECPRT ;PRINT THE BLOCK NUMBER IN ERROR .WORD BLKCNT INC BLKERS ;INCREMENT BLOCKS IN ERROR COUNT JSR PC,CRLF ;GO TO A NEW LINE BR DLT100 DLT70: MOV TESTRING,R3 CLR R2 ; Clear error count accummulator. Mov NumSent,R1 ; Count of characters sent. CMPLP: Jsr R5,GetByte ; Get a byte from .Word InBuf ; the input buffer. Br CmpError ; Buffer empty exit. CMPB (R3)+,R0 ; Char same as sent? BEQ CMPNXT ; Yes, branch. INC R2 ; Count characters which do not compare CMPNXT: DEC R1 ; Have all chars in block been compared? BGT CMPLP ; Loop for entire block CmpError: Add R1,R2 ; For all characters not compared, count. MOV R2,ERRORS ;WERE THERE ANY ERRORS BEQ DLT100 ;NO, BRANCH JSR R5,DECPRT ;PRINT NUMBER OF ERRORS .WORD ERRORS $LIST JSR R5,DECPRT ;PRINT SIZE OF BLOCK .WORD NUMSENT $LIST BR PRTBLK DLT100: TST CONSKB ;CHECK IF OPERATOR WANTS TO STOP BMI DLT200 JMP LOOP DLT200: JSR R5,DECPRT ;UPDATE OPERATOR ON TOTAL BLOCKS IN ERROR .WORD BLKERS ;NUMBER OF BLOCKS IN ERROR $LIST JSR R5,DECPRT .WORD BLKCNT ;NUMBER OF BLOCKS SENT $LIST JSR R5,GETYN .WORD CONTINUE ;"DO YOU WANT TO CONTINUE? " BR DLEXIT BR DLEXIT $SkipLIST JSR PC,CRLF JMP CONSENA DLEXIT: Jmp Cleanup ; Revert devices and return. ;;********************************************************************* .Sbttl Loopback Data ;; BLKCNT: .WORD 0 ;COUNT OF BLOCKS PROCESSED BLKERS: .WORD 0 ;COUNT OF BLOCKS IN ERROR ERRORS: .WORD 0 ;ERROR COUNT REGISTER NUMSENT: .WORD 0 ;NUMBER OF CHARS SENT PER BLOCK (CALC'D) NUMRECEIVED: .WORD 0 ;NUMBER OF CHARS RECEIVED/BLOCK (CALC'D) ;; OKSTRING: .WORD OKST1 ;STRING DESC "OK TO PROCEED" .WORD OKST1END OKST1: .ASCII 'OK to proceed with the loopback test' OKST1END=.-1 .EVEN CONTINUE: .WORD CONST1 ;STRING DESC "CONTINUE WITH TEST" .WORD CONSTEND CONST1: .ASCII 'Continue with test' CONSTEND=.-1 .EVEN TESTRING: .WORD STR1 ;TEST STRING (STATIC STRING DESCRIPTOR)\ .WORD STR1END STR1: .ASCII 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' .ASCII 'zyxwvutsrqponmlkjihgfedcba' .ASCII ' <>,./?;:"{}[]!@#$%^&*()_-+=~`|\' STR1END: .ASCII "'" .EVEN ;; INBUF: .WORD BUFBEGIN ;INPUT BUFFER DESCRIPTOR .WORD BUFBEGIN .WORD BUFBEGIN .WORD BUFEND BUFBEGIN: .BLKB STR1END-STR1+64. BUFEND=.-1 .EVEN ;;********************************************************* CSR: .Word 0 ; Temporary storage for CSR. Vect: .Word 0 ; Temporary storage for Vector. Unit: .Word 0 ; Temporary storage for CL unit. Term: .Word 0 ; Temporary storage for the TSX terminal. LUN: .Word 0 ; Logical unit number of last port. Min: .Word 2 ; Lowest unit number for loopback. Recvu: .Word 0 ; Unit number selected for receiver. XmitU: .Word 0 ; Unit number selected for transmitter. Recver: .Word 0 ; Receiver logical unit number. Xmiter: .Word 0 ; Transmitter logical unit number. ErrCode:.Word 0 ; Error code. AREA: .BLKW 10 ;EMT scratch area. Portmsg: .Word Lunchr ; String descriptor of port message. .Word Portend CLmsg: .Word CLstart ; String desc of CL message. .Word Clstr Getrcv: .Word GRstart .Word GRend GetXmit: .Word GXstart .Word GXend GRstart: .Ascii /Enter desired receiver unit number/ GRend=.-1 GXstart: .Ascii /Enter desired transmitter unit number/ GXend=.-1 ;; LunChr: .Ascii / - CSR / CSRStr: .Ascii /177560, Vector at / VecMsg: .Ascii /060; / Portend=.-1 VecStr: .Ascii /000060/ CLstart: .Ascii / TSX CL/ CLstr: .Ascii /000000/ CLend=.-1 .Even ;;**************************************************************************** .SbTTL OCTAL Convert routine - 16 bits to 6 octal characters. ;;*********************************************************************: ;; SUBROUTINE TO CONVERT A WORD TO SIX OCTAL CHARACTERS. ;; THE CHARACTERS ARE MOVED FROM LEFT TO RIGHT INTO A STRING. ;; EXPECTS CALLS OF THE FORM: ;; JSR R5,CNVOCT ;; .WORD (ADDRESS OF THE DATA WORD) ;; .WORD (STRING ADDRESS OF MOST SIGNIFICANT OCTAL DIGIT) ;; CNVOCT:: MOV R4,-(SP) ;SAVE REGISTERS USED MOV R3,-(SP) MOV R2,-(SP) MOV R1,-(SP) MOV R0,-(SP) MOV @(R5)+,R2 ;GET THE DATA WORD TO REG 2 MOV (R5)+,R0 ;GET THE STRING ADDRESS FO REG 0 MOV #6,R4 ;PUT THE DIGIT COUNTER IN REG 4 MOV #-2,R1 ;MOST SIGNIFICANT DIGIT IS A SPECIAL CASE CNVO10: ADD #3,R1 ;SET BIT PER DIGIT COUNTER CLR R3 ;CLEAR DIGIT BUILD REGISTER CNVO20: ROL R2 ;ROTATE NEXT BIT INTO CARRY ROL R3 ;RATAOE CARRY INTO REG 3 DEC R1 ;IS THERE A CHARACTER'S WORTH YET? BNE CNVO20 ;NO, LOOP ADD #60,R3 ;CONVERT TO ASCII MOVB R3,(R0)+ ;PUT CHAR IN STRING DEC R4 ;COUNT DOWN # DIGITS BNE CNVO10 ;LOOP UNTIL DONE MOV (SP)+,R0 ;RESTORE REGISTERS USED MOV (SP)+,R1 MOV (SP)+,R2 MOV (SP)+,R3 MOV (SP)+,R4 RTS R5 ;RETURN ;;*********************************************************************: .END