! ! C.S. LINK HANDLER FOR KMC11 - GJB 28/06/78 ! ! ! KMC11 PROGRAM TO PERFORM BLOCK TRANSFERS BETWEEN PDP-11 AND ! C.S. DEPARTMENT NINE BIT LINK. BUFFERS ARE PASSED, USING THE ! CSRs AS FOLLOWS :- ! (1) PDP-11 -> KMC11 ! (A) PDP-11 SETS CSR0.4 (CSR REQUEST) ! (B) KMC11 SETS CSR2.1 (CSR GRANT) AFTER ARBITRARY DELAY ! (C) PDP-11 LOADS BUFFER INFO : ! CSR2.0 = 0 (RX BUFF), 1 (TX BUFF) ! CSR2.2/3 = BIT 16/17 OF ADDRESS ! CSR3 = LENGTH (IN WORDS) ! CSR2.7 = EXTRA BYTE MARKER ! CSR4/5 = BIT 0-15 OF ADDRESS ! (D) PDP-11 RESETS CSR0.4 ! (2) KMC11 -> PDP-11 ! (A) KMC11 LOADS BUFFER INFO, AS ABOVE ! (B) KMC11 SETS CSR2.4 (DATA READY) ! ! CSR0.0 AND CSR0.1 ENABLE TX AND RX INTERRUPTS, RESPECTIVELY ! ! THE FOLLOWING ERROR SITUATIONS CAN OCCUR :- ! (1) MORE THAN 16 RX OR TX BUFFERS SENT AHEAD BY PDP-11 ! ACTION : WRAP-AROUND, GENERALLY NON-FATAL, BUT ! RESULTS IN 16 'LOST' BUFFERS ! (2) INVALID MEMORY ADDRESS FOR BUFFER ! ACTION : KMC11 HANGS (NON-ONGOING) ! (3) TX ERROR ! ACTION : RETRY UNTIL SUCCESSFUL ! ! TWO VERSIONS OF LINK PROTOCOL ARE CATERED FOR : $DEF FANCY=1; ! TWO NULL BYTES PRECEDE MESSAGE, AND FINAL BYTE HAS BIT9 ! FOR PDP 11/34 <-> FEP $DEF SIMPLE=2; ! NO HEADER, EOT CHAR TERMINATES ! FOR PDP 11/40 <-> ISYS ! SELECTED BY :- $DEF LKTYPE=FANCY ! ! $DEF FLAG=SP0, HIGHB=SP1, LOWB=SP2, RXSTATE=SP3, TXSTATE=SP4 $DEF RXCOUNT=SP5, RXHIGH=SP6, RXMID=SP7, RXLOW=SP8 $DEF TXCOUNT=SP9, TXHIGH=SP10, TXMID=SP11, TXLOW=SP12 $DEF TEMP=SP13, TEMP1=SP14, LINK=SP15 $DEF NPRREQ=NPR.0, NONEXMEM=MISC.0, TIMEOUT=MISC.4 $DEF TXINTS=CSR0.0, RXINTS=CSR0.1, REQ11=CSR0.4 $DEF DEV=CSR2.0, GRANT=CSR2.1, READY=CSR2.4, READY1=BRG.4 $DEF BIT1617=16_0C, BBIT1617=16_8C, RX=0, TX=1 $DEF CRXRDY=16_10, CTXRDY=16_11, CGRANT=16_02, CREADY=16_80 $DEF RXRDY=ADR0.7, TXRDY=ADR0.7, RXEOT=ADR1.0, TXERR=ADR1.7 $DEF EXTRABYTE=TXHIGH.7, CEXTRA=16_80 $DEF NORMAL=0, EOT=1 $DEF IDLE=0, FIRST=1, SECOND=2, LOW=3, HIGH=4, TERM=5, SEVEN=7 $DEF RTOUT=16_11, RTIN=16_0D, CLOCK=16_10, INT=16_80, VECTOR=16_40 $DEF RTHIGH=16_0C, RTMID=16_FF $DEF RSLOW=16_68, RDLOW=16_6A, TSLOW=16_6C, TDLOW=16_6E $DEF BMASK=63, EOTCH=4 ! $DATA 0; !#RSW MUST = 0 RSW:0, RX1, RX2, RXLO, RXHI TSW:0, TX1, TX2, TXLO, TXHI, TXTERM RXGET:0; !RX BUFFER Q GET PTR RXPUT:0; !RX BUFFER Q PUT PTR TXGET:0; !TX BUFFER Q GET PTR TXPUT:0; !TX BUFFER Q PUT PTR RXBASE:0; !RX BUFFER DESC AREA $DATA @+BMASK TXBASE:0; !TX BUFFER DESC AREA $DATA @+BMASK ! ! ! POP BUFFER DESCRIPTOR FROM QUEUE $MACRO POP RT TEMP=RTGET MAR=TEMP+#RTBASE; !ADDR OF NEXT BUFF INFO RTHIGH=MEMORY, MAR=MAR+1; !LOAD BIT 16/17 RTMID=MEMORY, MAR=MAR+1; ! BIT 8-15 RTLOW=MEMORY, MAR=MAR+1; ! BIT 0-7 RTCOUNT=MEMORY; ! LENGTH $IF RTSTATE=TXSTATE TXCOUNT=TXCOUNT+1 IF EXTRABYTE $FINISH $END ! ! ! SET CSRs FOR MESSAGE TO 11, AND ADVANCE GET POINTER $MACRO ENDED RT TEMP=RTGET MAR=TEMP+#RTBASE TEMP1=MEMORY, MAR=MAR+1 CSR5=MEMORY, MAR=MAR+1 CSR4=MEMORY, MAR=MAR+1 $IF RTSTATE=RXSTATE IF RXSTATE=LOW RXCOUNT=RXCOUNT+1 TEMP1=TEMP1!CEXTRA FINISH RXLOW=MEMORY CSR3=RXLOW-RXCOUNT $FINISH CSR2=TEMP1!CRTRDY TEMP=TEMP+4 TEMP=TEMP&BMASK RTGET=TEMP IF TEMP=RTPUT RTSTATE=IDLE ELSE RTSTATE=FIRST FINISH $END ! ! ! UPDATE PUT POINTER FOR BUFFER DESCRIPTOR QUEUE $MACRO ACCEPT RT RTSTATE=RTSTATE+1 IF RTSTATE=IDLE TEMP=RTPUT TEMP1=TEMP+4 RTPUT=TEMP1&BMASK MAR=TEMP+#RTBASE $IF LKTYPE=FANCY TEMP=CSR2 $FINISH $END ! ! RXSTATE=0; TXSTATE=BRG; !RX AND TX IN IDLE STATE ADR3=BRG; ADR2=BRG MISC=RTHIGH ADR7=RTMID; ADR6=RSLOW NPR=RTOUT; !ZERO RX STATUS WORD CYCLE; REPEAT IF NPRREQ ADR6=TSLOW NPR=RTOUT; !ZERO TX STATUS WORD CYCLE; REPEAT IF NPRREQ CYCLE; REPEAT IF NONEXMEM; !RX OR TX GONE MISSING CYCLE; !MAIN POLLING LOOP TEMP=FLAG&VECTOR MISC=TEMP!CLOCK; !START CLOCK IF GRANT AND REQ11=0; !MESSAGE FROM ELEVEN LINK=3 JUMP FROM11 RTN3: FINISH IF RXSTATE#IDLE; !READ RX STATUS IF NOT IDLE ADR5=RTMID; ADR4=RSLOW NPR=RTIN FINISH CSR2=CGRANT IF REQ11 AND GRANT=0 AND READY1=0; !ELEVEN WANTS CSRs CYCLE; REPEAT IF NPRREQ IF RXSTATE#IDLE AND RXRDY; !RX HAS DATA READY ADR4=RDLOW NPR=RTIN; !READ IT MAR=RXSTATE CYCLE; REPEAT IF NPRREQ JUMP MEMORY; !SWITCH ON RX STATE RX1:POP RX RX2: $IF LKTYPE=FANCY TEMP=ADR0; TEMP1=ADR1; !FIRST TWO CHARS IF TEMP=0 AND TEMP1=0; !NULL CHAR RXSTATE=RXSTATE+1 JUMP ENDRX FINISH $FINISH RXSTATE=LOW RXLO:LOWB=ADR0; !LOW BYTE RECEIVED $IF LKTYPE=FANCY IF RXEOT=0; !NOT FINAL BYTE RXSTATE=RXSTATE+1 JUMP ENDRX FINISH $ELSE IF LOWB#EOTCH; !NOT FINAL BYTE RXSTATE=RXSTATE+1 JUMP ENDRX FINISH $FINISH RXHI:BRG=FLAG&VECTOR; !HIGH BYTE RECEIVED MISC=RXHIGH!BRG ADR7=RXMID; ADR6=RXLOW ADR3=ADR0; ADR2=LOWB NPR=RTOUT; !WRITE HIGH.LOW TO BUFFER RXCOUNT=RXCOUNT-1 RXLOW=RXLOW+2; !UPDATE BUFF GET PTR IF C RXMID=RXMID+1 RXHIGH=RXHIGH+4 IF C FINISH CYCLE; REPEAT IF NPRREQ CYCLE; REPEAT IF NONEXMEM; !NON-EXISTENT BUFFER $IF LKTYPE=FANCY IF RXEOT=0 AND RXCOUNT#0; !NOT FINAL BYTE RXSTATE=LOW JUMP ENDRX FINISH $ELSE TEMP=ADR0 IF TEMP#EOTCH AND RXCOUNT#0; !NOT FINAL BYTE RXSTATE=LOW JUMP ENDRX FINISH $FINISH IF GRANT; !ELEVEN HAS CSRs CYCLE; REPEAT IF REQ11; !WAIT FOR MESSAGE LINK=2 JUMP FROM11 FINISH CYCLE; REPEAT IF READY; !KMC HAS CSRs RTN2: ENDED RX IF RXINTS; !RX INTS ON MISC=INT FLAG=0 ELSE FLAG=2; !MARK NON-INT RX RDY FINISH ENDRX:FINISH ! ! IF TXSTATE#IDLE; !READ TX STATUS IF NOT IDLE ADR5=RTMID; ADR4=TSLOW NPR=RTIN FINISH IF READY; !CHECK IF READY ... BRG=FLAG&CSR0; ! ... AND INTS REENABLED IF BRG.0 MISC=INT!VECTOR FLAG=VECTOR ELSE IF BRG.1 MISC=INT FLAG=0 FINISH FINISH ! JUMP 256 IF NPRREQ=0; !JUMP TO PAGE ONE JUMP .-3 $CTRL 256; !MUST RESIDE IN PAGE 1 IF TXSTATE#IDLE AND TXRDY; !TX HAS SENT DATA IF TXERR; !TX ERROR ADR4=TDLOW ADR2=2 NPR=RTOUT; !RETRANSMIT CYCLE; REPEAT IF NPRREQ JUMP ENDTX FINISH MAR=TXSTATE+#TSW JUMP MEMORY; !SWITCH ON TX STATE TX1:POP TX TX2: $IF LKTYPE=FANCY ADR2=0; ADR3=BRG; !FIRST TWO (NULL) CHARS TXSTATE=TXSTATE+1 JUMP SEND $FINISH TXLO:ADR5=TXMID; ADR4=TXLOW; !LOW BYTE $IF LKTYPE=FANCY TEMP=TXHIGH&BIT1617 NPR=TEMP+1 $ELSE NPR=TXHIGH+1; !READ WORD FROM BUFFER $FINISH TXCOUNT=TXCOUNT-1 TXLOW=TXLOW+2; !UPDATE BUFF GET PTR IF C TXMID=TXMID+1 TXHIGH=TXHIGH+4 IF C FINISH CYCLE; REPEAT IF NPRREQ CYCLE; REPEAT IF NONEXMEM; !NON-EXISTENT BUFFER HIGHB=ADR1 ADR3=0; ADR2=ADR0 $IF LKTYPE=FANCY JUMP TXTST IF EXTRABYTE TXSTATE=HIGH $ELSE TEMP=BRG IF TEMP=EOTCH TXSTATE=TERM ELSE TXSTATE=HIGH FINISH $FINISH JUMP SEND TXHI:ADR2=HIGHB; !HIGH BYTE $IF LKTYPE=FANCY TXTST:IF TXCOUNT=0; !FINAL BYTE TXSTATE=TERM ADR3=EOT; !SET BIT NINE ELSE TXSTATE=TXSTATE!!SEVEN ADR3=NORMAL FINISH $ELSE IF TXCOUNT=0 OR HIGHB=EOTCH TXSTATE=TXSTATE+1 ELSE TXSTATE=TXSTATE-1 FINISH ADR3=NORMAL $FINISH SEND:TEMP=FLAG&VECTOR MISC=TEMP!RTHIGH ADR7=RTMID; ADR6=TDLOW NPR=RTOUT; !WRITE TO TX DATA WORD CYCLE; REPEAT IF NPRREQ JUMP ENDTX TXTERM:IF GRANT; !DONE - BUT ELEVEN HAS CSRs CYCLE; REPEAT IF REQ11; !WAIT FOR MESSAGE LINK=4 JUMP FROM11 FINISH CYCLE; REPEAT IF READY; !KMC HAS CSRs RTN4: ENDED TX IF TXINTS; !TX INTS ON MISC=INT!VECTOR FLAG=VECTOR ELSE FLAG=1; !MARK NON-INT TX RDY FINISH ENDTX: ! FINISH CYCLE; REPEAT IF TIMEOUT=0; !UNTIL 50 MICROSECS ELAPSED REPEAT ! ! FROM11:IF DEV=RX; !HANDLE ELEVEN'S MESSAGE ACCEPT RX $IF LKTYPE=FANCY MEMORY=TEMP&BIT1617, MAR=MAR+1 $FINISH ELSE ACCEPT TX $IF LKTYPE=FANCY MEMORY=TEMP&BBIT1617, MAR=MAR+1 $FINISH FINISH $IF LKTYPE=SIMPLE TEMP=CSR2 MEMORY=TEMP&BIT1617, MAR=MAR+1; !STORE BIT 16/17 $FINISH MEMORY=CSR5, MAR=MAR+1; ! BIT 8-15 MEMORY=CSR4, MAR=MAR+1; ! BIT 0-7 MEMORY=CSR3; ! COUNT CSR2=0 JUMP PAGE1:LINK+.; !RETURN (UGH !!) JUMP RTN2 JUMP RTN3 JUMP RTN4