! ! 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