|
|
researchv8 Dan Cross
/* * subroutine */ .org 3072 seg3: r_err_bus: /* * Unibus request fails to complete within 20 usec * currently is not tested */ mov %err_bus,brg mov brg,pcr jmp err_bus rcv: /* * copy packets from C_RQ to C_RADDR (from host to host for XBLK) * copy from C_RB to C_RADDR for ~XBLK * input : r9 is the chan #, r8/r10 point to LTE * Registers are used as follows: * r15 - repmode * r13(LSB), r12, r11 - ptr2 (RADDR) * r9 - chan # * r8/r10 - LTE address * r7 - RQ * r6(LSB), r5, r4(MSB) - stage 2 buffer * r3 - plen * r2 - len */ CHK(B5_ENT,5) /* mov repsave,mar mov %repsave,%mar mov r12,mem */ mov 0,brg mov brg,r15 mov repctl,mar mov %repctl,%mar mov 0,mem /* flag to indicate no CNTL rcv yet */ /* * set STIME if timer expires */ mov r8,%mar mov C_Y,brg add brg,r10,mar mov mem,r0 mov YEXPIRE,brg orn brg,r0,- brz 1f br 2f 1: mov STIME,brg or brg,r15 2: /* * put RADDR into r13, r12, r11 * put RQ/RB into r7 * RQ and RADDR will be restored with the new value after the while loop */ mov C_X1,brg add brg,r10,mar mov mem,r0 mov XBLK,brg orn brg,r0,- brz 1f mov C_RB,brg br 2f 1: /* block mode */ mov C_RQ,brg 2: add brg,r10,mar mov mem,r7 brz r_ex2 mov C_RADDR,brg add brg,r10,mar mov mem,r13|mar++ mov mem,r12|mar++ mov mem,r11 r_while: /* * while ((C_RLEN>0) && (C_RQ!=NULL)) */ mov r7,r7 brz r_endwhile mov C_RLEN,brg add brg,r10,mar mov mem,r0 mov mem,r2|mar++ mov mem,r1 or mem,r0 dec r0,- brz r_endwhile /* * len222 = len = min(plen,C_RLEN); */ QA(r7) mov mem,mem|mar++ mov mem,r3|mar++ /* plen */ mov mem,idl|mar++ /* *pdata */ dec r3,- /* test for rej packet */ brz r_rq /* * r2,r1 -= len222 */ mov r8,%mar mov C_RLEN,brg add brg,r10,mar mov r3,brg sub brg,r2 mov 0,brg subc brg,r1 brc 1f /* * case: plen > C_RLEN * len = C_RLEN (r2) * C_RLEN = 0 * plen (r3) = plen - len */ mov mem,r2 mov 0,mem|mar++ mov 0,mem CHK(B5_PLEN,5) mov r2,brg sub brg,r3 br 2f 1: /* * case: plen <= C_RLEN * C_RLEN is now in r2, r1 * len = plen (r3) * plen = 0; */ mov r2,mem|mar++ mov r1,mem mov r3,brg mov brg,r2 sub brg,r3 /* plen = 0 */ 2: /* * idl is the buffer index * let r6-r4 points to pdata */ mov idl,brg mov brg,r1 BITA(r1,r6,r5,r4) /* * while (len--) *ptr2++ = *ptr1++; * test 'r13' for even or odd first */ mov r13,brg br0 r_odd br r_even r_odd: /* * copy one byte */ CHK(B5_ODD,5) GETTWO(r6,r5,r4,r_err_bus) dec r2 mov idh,brg br0 1f br r_cnt1 /* cntl is rcv */ 1: mov idl,brg mov brg,odl mov brg,odh PUTONE(r13,r12,r11,r_err_bus) dec r2,- brz r_done r_even: /* * copy two bytes at a time */ mov 2,brg sub brg,r2,- /* len - 2 */ brc 1f brz r_odd br r_done 1: GETTWO(r6,r5,r4,r_err_bus) dec r2 mov idh,brg br0 1f br r_cnt1 /* cntl is rcv */ 1: mov idl,brg mov brg,odl GETTWO(r6,r5,r4,r_err_bus) dec r2 mov idh,brg br0 1f br r_cnt0 1: mov idl,brg mov brg,odh PUTTWO(r13,r12,r11,r_err_bus) br r_even r_done: /* * this is the end of copy * if (plen==0) ? */ dec r3,- brz r_rq /* * plen != 0, move data to the front of the buffer * while (plen--) *ptr2++ = *ptr1++ * ptr2 in r13-11 (pdata[0]), ptr1 in r6-r4 (pdata[plen]) */ CHK(B5_MOVE,5) mov tmp,mar mov %tmp,%mar mov r13,mem|mar++ mov r12,mem|mar++ mov r11,mem QA(r7) mov mem,mem|mar++ mov r3,mem /* store plen */ mov mem,idl|mar++ /* idl = plen */ mov mem,r3 /* points to pdata[0] */ BITA(r3,r13,r12,r11) mov idl,brg mov brg,r3 r_move: /* * while (plen--) .... */ dec r3,- brz r_ret GETTWO(r6,r5,r4,r_err_bus) mov idl,brg mov brg,odl mov idh,brg mov brg,odh PUTTWO(r13,r12,r11,r_err_bus) dec r3 /* move 2-bytes: 1 9-bit envelop */ br r_move r_ret: /* * restore r13, r12, r11 */ mov tmp,mar mov %tmp,%mar mov mem,r13|mar++ mov mem,r12|mar++ mov mem,r11 /* * now test if cntl was rcv */ mov repctl,mar mov %repctl,%mar mov mem,r0 dec r0,- brc r_cnt3 /* rcv cntl flag set */ br r_rp2 /* plen>0, then RLEN must be 0 */ r_rq: /* * RQ = Pnext; * release buffer and queue * send echo or rej if pseq!=0 */ mov r7,brg mov brg,r5 /* r5 = old RQ */ QA(r5) mov mem,r7|mar++ /* r7 = new RQ */ mov 0,mem|mar++ /* plen = 0 */ mov mem,r6 /* r6 = buf pointer */ mov NIL,mem|mar++ mov mem,r1 /* pseq */ mov mem,r2 mov 0,mem FREEQ(r5) IBEG(r6) dec r1,- brz r_rq2 /* * if pseq&0370 == I_SEQ: pseq += I_ECHO - I_SEQ; set SBLOCK */ mov ~WINDOW,brg and brg,r2 mov I_SEQ,brg xor brg,r2 dec r2,- brc r_rq1 mov WINDOW,brg and brg,r1 mov I_ECHO,brg or brg,r1 /* r1 = ECHO + seq */ /* * if YBLOCK is set, set SBLOCK */ mov r8,%mar mov C_Y,brg add brg,r10,mar mov mem,r0 mov YBLOCK,brg orn brg,r0,- brz 1f br r_rq1 1: mov SBLOCK,brg or brg,r15 /* reach end of a block */ r_rq1: CALL(send,s.send) mov r8,%mar mov C_C,brg add brg,r10,mar mov r1,mem r_rq2: mov repctl,mar mov %repctl,%mar mov mem,r0 dec r0,- brc r_cnt3 r_report: /* * if C_RLEN==0 report(KS_RDB,r9) */ mov r8,%mar mov C_RLEN,brg add brg,r10,mar mov mem,r0|mar++ or mem,r0 dec r0,- brz r_rp2 mov SBLOCK,brg orn brg,r15,- brz r_rp3 br r_while r_rp2: mov SFULL,brg or brg,r15 /* RLEN reaches 0 */ r_rp3: /* * save r7 and r13,r12, r11 here * report READ completion: code in r15. */ CHK(B5_REP,5) mov r8,%mar mov C_RLEN,brg add brg,r10,mar mov mem,r2 mov 0,mem|mar++ mov mem,r3 mov 0,mem mov %repinfo,%mar mov repinfo,mar mov KS_RDB,mem|mar++ mov r2,mem|mar++ mov r3,mem|mar++ mov mem,mem|mar++ /* cntl char */ mov r15,mem CALL(report,s.report) mov r8,%mar br r_ex0 r_endwhile: /* * Restore RADDR from r13, r12, r11 * Restore RQ or RB (if ~XBLK) from r7 */ dec r15,- brc r_rp3 mov r8,%mar mov C_RADDR,brg add brg,r10,mar mov r13,mem|mar++ mov r12,mem|mar++ mov r11,mem r_ex0: mov C_X1,brg add brg,r10,mar mov mem,r0 mov XBLK,brg orn brg,r0,- brz 1f mov C_RB,brg br 2f 1: /* block mode */ mov C_RQ,brg 2: add brg,r10,mar mov r7,mem r_exit: CHK(B5_EXIT,5) /* mov repsave,mar mov %repsave,%mar mov mem,r12 */ RETURN(s.rcv) r_ex2: dec r15,- brc r_rp3 br r_exit r_cnt0: /* * copy 1 byte to RADDR and report completion for SCNTL */ mov odl,brg mov brg,odh PUTONE(r13,r12,r11,r_err_bus) r_cnt1: /* * len (r2) may not be 0 * adjust RLEN and plen */ mov r2,brg add brg,r3 mov 0,r0 inc r2 mov r8,%mar mov C_RLEN,brg add brg,r10,mar add mem,r2,mem|mar++ addc mem,r0,mem mov repctl,mar mov %repctl,%mar mov idl,mem br r_done r_cnt3: /* * prepare for report */ mov SCNTL,brg or brg,r15 br r_rp3 clean: /* * r2 is a queue pointer: release all queues/buffers * using r0, r2, r3, brg, mar, %mar */ CHK(B5_AJAX,5) c_1: mov r2,brg brz c_exit mov brg,r0 QA(r0) mov mem,r2|mar++ /* pnext */ mov 0,mem|mar++ /* plen */ mov mem,r3 mov NIL,mem|mar++ /* *pdata */ mov 0,mem /* pseq */ FREEQ(r0) IBEG(r3) br c_1 c_exit: RETURN(s.clean) send: /* * This subroutine sends a 1-byte (in r1) meta packet on chan r9 */ SENDHEAD(r9) D422(4) SENDDATA(D_WCNTL,r1) D422(4) SENDPACK(r1) D422(4) SENDCMD(D_READ) RETURN(s.send) report: mov csr0,brg br0 report /* csr0==3, loop forever */ /* * kin is 12 bytes: KS_SEND info 4 bytes ==> INCA(8) * KS_RDB info 8 bytes ==> INCA(4) * KS_EOI, KS_ERR info 6 bytes ==> INCA(6) * r9 - channel # * repinfo: code, lenlo, lenhi, cntl, mode * r1, r12, r13 are saved and restored when exit * this implementation is fast but use 70 more instructions than: * have a loop to put info in repinfo to odl/odh for PUTTWO * Modify HS and sbhead * Interrupt cpu * using r0, r1, r2, r9, r11, r12, r13, npr, mar, %mar, odl, odh, oal, oah, brg */ mov repsave,mar mov %repsave,%mar mov r1,mem|mar++ mov r12,mem|mar++ mov r13,mem|mar++ mov sbhead,mar mov %sbhead,%mar mov mem,r13|mar++ mov mem,r12|mar++ mov mem,r11 mov %repinfo,%mar mov repinfo,mar mov mem,odl mov mem,r2 /* r2 = (repinfo) */ mov kseq,mar mov %kseq,%mar mov mem,odh /* for debugging */ mov mem,r0 inc r0,mem PUTTWO(r13,r12,r11,r_err_bus) mov r9,brg mov brg,odl /* chan# */ PUTTWO(r13,r12,r11,r_err_bus) mov KS_SEND,brg addn brg,r2,- brz rp2 /* * report is KS_RDB and others */ mov %replen,%mar mov replen,mar mov mem,odl|mar++ /* lenlo */ mov mem,odh /* lenhi */ PUTTWO(r13,r12,r11,r_err_bus) mov %repctl,%mar mov repctl,mar mov mem,odl|mar++ mov mem,odh PUTTWO(r13,r12,r11,r_err_bus) mov KS_RDB,brg addn brg,r2,- brz rp3 br rp4 rp2: /* * report is KS_SEND */ mov 8,brg br rpy rp2.5: /* * reset bit map for chan# in r9 */ mov 7,brg and brg,r9,brg mov brg,r0 mov %bitpatt,%mar mov bitpatt,brg add brg,r0,mar mov mem,r0 mov r9,brg mov 0,brg>> mov 0,brg>> mov 0,brg>> mov brg,r2 mov %timemap,%mar mov timemap,brg add brg,r2,mar or mem,r0,mem /* turn bit on */ xor mem,r0,mem /* turn bit off */ br rp4 rp3: /* * report was KS_RDB * reset C_Y and RULEN */ mov r8,%mar mov C_Y,brg add brg,r10,mar mov mem,r0 mov 0,mem /* reset READ mode */ mov C_RULEN,brg add brg,r10,mar mov 0,mem|mar++ mov 0,mem /* * if YTIMACT, reset bit in timemap */ mov YTIMACT,brg orn brg,r0,- brz rp2.5 rp4: mov 4,brg rpy: /* * brg: increment count * Now modify HS and sbhead * If HS==BUFSIZ-1, then HS=0 and sbhead=sbaddr */ mov brg,odl mov HS,r0 mov BUFSIZ-1,brg sub brg,r0,- /* HS-(BUFSIZ-1) */ brc 1f inc r0,HS INCA(r13,r12,r11,odl) br 2f 1: mov 0,brg /* reset HS */ mov brg,HS mov sbaddr,mar mov %sbaddr,%mar mov mem,r13|mar++ mov mem,r12|mar++ mov mem,r11 2: /* * Restore sbhead */ mov sbhead,mar mov %sbhead,%mar mov r13,mem|mar++ mov r12,mem|mar++ mov r11,mem|mar++ /* * Send interrupt 2 to the PDP-11 */ mov 0200,brg mov brg,csr2 /* RDYO to csr2 for kmc.c */ mov nprx,brg|r0 br7 1f mov BRQ|VEC4,brg mov brg,nprx 1: /* * restore r1, r12, r13 */ mov repsave,mar mov %repsave,%mar mov mem,r1|mar++ mov mem,r12|mar++ mov mem,r13|mar++ RETURN(s.report) copy1: /* * r13 is set to (1<<0) and bit 6 (block/char mode) unchanged because: * rblen == 0; c_ta0 == 0; rlen>0; raddr will become odd after copy1 * r12.0 is 1; reset r12 when exit * copy odl to raddr and restore r1 before return * raddr is in oal, oah, r11 * since rlen, raddr, rulen were changed for 2 bytes * adjustments are needed here */ mov (1<<6),brg and brg,r13 /* preserve block/char mode bit */ mov r1,brg mov brg,idh /* save r1 */ mov odl,brg mov brg,odh SPUTONE(r11,r_err_bus) mov r8,%mar mov C_RLEN,brg add brg,r10,mar mov 1,r1|brg or brg,r13 /* set bit 0 (radd odd) */ mov 0,r0|brg mov brg,r12 /* reset r12 */ add mem,r1,mem|mar++ /* inc rlen */ addc mem,r0,mem|mar++ mov mem,r11 dec r11,mem|mar++ /* dec raddr */ mov mem,r11 subc brg,r11,mem|mar++ mov mem,r11 subc brg,r11,mem|mar++ mov mem,r11 dec r11,mem|mar++ /* dec rulen */ mov mem,r11 subc brg,r11,mem|mar++ /* * restore r1 from idh and return */ mov idh,brg mov brg,r1 RETURN(s.copy1) cktimer: /* * check timer status: it is called from input routine: * if char mode and channel # is changed or fifo is empty; * if rulen>0 && rlen==0, reset rulen to 0, report SFULL, and return * if (c_rb==nil && c_rulen==0) return; * if (YTIME) set YEXPIRE or turn on timer * call 'rcv' * r1 has to be preserved * r9: channel number * using: r0, .... */ mov r8,%mar mov C_RULEN,brg add brg,r10,mar mov mem,r2|mar++ or mem,r2 dec r2,- brz ct_3 /* * if rlen==0, report SFULL */ mov C_RLEN,brg add brg,r10,mar mov mem,r0|mar++ or mem,r0 dec r0,- brc ct_4 mov %repinfo,%mar mov repinfo,mar mov KS_RDB,mem|mar++ mov 0,mem|mar++ /* residue length */ mov 0,mem|mar++ mov 0,mem|mar++ /* cntl char */ mov SFULL,mem /* mode */ CALL(report,s.report) br ct_9 ct_3: mov C_RB,brg add brg,r10,mar mov mem,brg brz ct_9 ct_4: /* * check if timeout mode */ mov C_Y,brg add brg,r10,mar mov mem,r0 mov YTIME,brg orn brg,r0,- brz 1f br ct_7 1: mov YEXPIRE,brg orn brg,r0,brg brz ct_7 /* timer already expires */ mov YTIMACT,brg orn brg,r0,- brz ct_7 /* timer already active */ /* * set timer active and load initial timer value */ or brg,r0,mem /* set YTIMACT */ mov C_INITIM,brg add brg,r10,mar mov mem,r0 mov C_ITIME,brg add brg,r10,mar dec r0,mem brc ct_10 /* * timer expires: INITIM is 0 */ mov 0,mem mov C_Y,brg add brg,r10,mar mov mem,r0 mov YEXPIRE,brg or brg,r0 mov ~YTIMACT,brg and brg,r0,mem ct_7: /* * timer expires, call rcv * save r1 here before calling 'rcv' */ mov %rcvsave,%mar mov rcvsave,mar mov r13,mem|mar++ mov r12,mem|mar++ mov r1,mem|mar++ CALL(rcv,s.rcv) mov %rcvsave,%mar mov rcvsave,mar mov mem,r13|mar++ mov mem,r12|mar++ mov mem,r1 ct_9: RETURN(s.cktimer) ct_10: /* * timer not expire: turn on bitmap and set YTIMACT */ mov r9,brg mov 7,r7 and brg,r7 mov 0,brg>> mov 0,brg>> mov 0,brg>> mov brg,r0 mov %bitpatt,%mar mov bitpatt,brg add brg,r7,mar mov mem,r7 mov %timemap,%mar mov timemap,brg add brg,r0,mar or mem,r7,mem br ct_7 strailer: /* * XNIL is set, send trailer-only on this channel * chan# is not on 'outq' * r9, r8/r10 is set up * using r0, r1, r2, ... */ mov r8,%mar mov C_S,brg add brg,r10,mar mov mem,r0 mov I_SEQ,brg or brg,r0,brg mov brg,r1 inc r0 mov WINDOW,brg and brg,r0,mem mov C_X1,brg add brg,r10,mar mov mem,r0 mov XBOTM,brg orn brg,r0,- brz 1f mov I_BOT,brg br 2f 1: mov I_BOTM,brg 2: mov brg,r2 SENDHEAD(r9) D422(4) SENDDATA(D_WCNTL,r2) D422(4) SENDDATA(D_WDATA,0) D422(4) SENDDATA(D_WDATA,0) D422(4) SENDDATA(D_WCNTL,r1) D422(4) SENDPACK(r0) D422(4) SENDCMD(D_READ) RETURN(s.strailer) /* * end of segment 3 */ endseg3:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.