home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / sigm / vol238 / level2.aqm / LEVEL2.ASM
Assembly Source File  |  1986-02-10  |  47KB  |  1,847 lines

  1. title 'LEVEL2.ASM'
  2. ;************************************************
  3. ;*                        *
  4. ;*        LEVEL2.ASM            *
  5. ;*                        *
  6. ;*  X.25 level 2 (HDLC) protocol handler    *
  7. ;*  (note that some level2 real time tasks,     *
  8. ;*   such as flag generation/detection, bit    *
  9. ;*   stuffing/stripping and CRC generation/    *
  10. ;*   checking are handled by the Level 1     *
  11. ;*   hardware (SIO))                *
  12. ;*                        *
  13. ;*  rev 1.52    08/08/84    E. Elizondo    *
  14. ;*                        *
  15. ;*  (c) 1984 E. Elizondo - all rights reserved. *
  16. ;*                        *
  17. ;*    This program may be used freely for non-  *
  18. ;*  commercial applications. It may not be sold *
  19. ;*  or used for commercial applications without *
  20. ;*  written permission of the author.           *
  21. ;*                         *
  22. ;************************************************
  23. ;    
  24.     maclib    Z80    ;DR Z80 macro library
  25.  
  26. ;    assembly time options
  27. false    equ    0
  28. true    equ    not false
  29. debug    equ    true        ;display V(s) of tx I frames
  30.  
  31.  
  32.  
  33. ;    design parameters
  34. kconst    equ    4        ;max # of unack. frames
  35. n2    equ    10        ;max # of re-transmissions
  36. kack    equ    10        ;acknowledgement delay count
  37.  
  38. ;    X.25 standard parameters:
  39.  
  40. ;    frame addresses (X.25 para 2.4.1)
  41. ;    bit #   8765$4321
  42. addra    equ    0000$0011b    ;address A
  43. addrb    equ    0000$0001b    ;address B
  44.  
  45. ;    frame control (id) bytes (table 3/X.25)
  46. ;    bit #   8765$4321
  47. ifid    equ    0000$0000b    ;I
  48. rrfid    equ    0000$0001b    ;RR
  49. rnrfid    equ    0000$0101b    ;RNR
  50. rejfid    equ    0000$1001b    ;REJ
  51. sarmfid    equ    0000$1111b    ;SARM (not used in LAPB)
  52. dmfid    equ    0000$1111b    ;DM
  53. sabmfid    equ    0010$1111b    ;SABM
  54. discfid    equ    0100$0011b    ;DISC
  55. uafid    equ    0110$0011b    ;UA
  56. cmdrfid    equ    1000$0111b    ;CMDR
  57. frmrfid    equ    1000$0111b    ;FRMR
  58. badfid    equ    1111$1111b    ;bad frame for testing
  59.  
  60. ;    misc constants
  61. cr    equ    0dh        ;carriage ret
  62. lf    equ    0ah        ;line feed
  63. tab    equ    09h        ;horizontal tab
  64.  
  65. ;    hooks for other modules
  66.  
  67. ;    subroutines
  68.     public    initl2        ;initialize level 2 parameters
  69.     public    rxfrm        ;process a received frame
  70.     public    txifrm        ;transmit I frame if avail
  71.     public    conlk        ;connect link
  72.     public    disclk        ;disconnect link
  73.     public    qlksta        ;query link status
  74.     public    gettxb        ;get address of free tx bcb
  75.     public    txbadf        ;transmit bad frame
  76.  
  77. ;    addresses
  78.     public    lkstat        ;level 2 link status bits
  79.     public    l2stat        ;level 2 status bits
  80.     public    dtemod        ;DTE/DCE mode flag
  81.  
  82. ;    level 2 parameters
  83.     public    vs        ;V(s)
  84.     public    vr        ;V(r)
  85.     public    lastnr        ;last received N(r)
  86.     public    lastvr        ;last transmitted V(r)
  87.     public    lastvs        ;last transmitted V(s)
  88.     public    maxvs        ;highest tx V(s)
  89.     public    pfbit        ;P/F bit
  90.  
  91. ;    diagnostic counters
  92.     public    rxifct        ;received I frame count
  93.     public    rxcfct        ;received cmd frames
  94.     public    rxrfct        ;received resp frames
  95.     public    rbafct        ;received bad addr frames
  96.     public    rxbcct        ;received bad cmd frames
  97.     public    rxbrct        ;received bad rsp frames
  98.     public    txfct        ;transmitted frame count
  99.     public    txifct        ;transmitted I frame count
  100.     public    txirct        ;tx I retransmission log
  101.  
  102. ;    definition of lkstat status bits
  103. ;    (note DTE busy comes from level1)
  104. ;    bit    set condition
  105. ;    0    link connect in process
  106. ;    1    link disconnect in process
  107. ;    2    link connected
  108. ;    3    DCE busy
  109. ;    4    DTE busy
  110. ;    5    unassigned
  111. ;    6    DTE REJ condition
  112. ;    7    DCE REJ condition
  113.  
  114.  
  115. ;    definition of l2stat status bits
  116. ;    bit    set condition
  117. ;    0    link query in process
  118. ;    1    DTE FRMR condition
  119. ;    2    DCE FRMR condition
  120. ;    3    unassigned
  121. ;    4    unassigned
  122. ;    5    unassigned
  123. ;    6    retransmit old I frame
  124. ;    7    timer recovery condition
  125.  
  126. ;    external subroutines
  127.  
  128. ;    from buffers module:
  129.     extrn    inibuf        ;initialize all buffers
  130.     extrn    putbuf        ;put char in buffer
  131.     extrn    getbuf        ;get char from buffer
  132.     extrn    dcrbuf        ;delete last char in buffer
  133.     extrn    bpoint        ;point to selected bcb
  134.     extrn    rlsrxb        ;release rx buffer
  135.     extrn    clrbuf        ;clear buffer for new use
  136.     extrn    clrtxb        ;clear all tx buffers
  137.     extrn    savbcb        ;save bcb pointers
  138.     extrn    getbct        ;get buffer count
  139.     extrn    getrdy        ;get state of buffer ready flag
  140.  
  141. ;    from level1 module:
  142.     extrn    txwake        ;wake up transmitter
  143.     extrn    t1on        ;turn on timer T1
  144.     extrn    t1off        ;turn off timer T1
  145.  
  146. ;    from level 3 module:
  147.     extrn    initl3        ;initialize level 3
  148.     extrn    txstar        ;transmit restart packet
  149. ;
  150. ;    from xutil module:
  151.     extrn    ilprt        ;in line print routine
  152.     extrn    pdec        ;print <hl> in decimal
  153.     extrn    phex        ;print <a> in hex
  154.     extrn    pbin        ;print <a> in binary
  155.     extrn    ctype        ;print ASCII char in <a>
  156.     extrn    poll        ;poll non-interrupt hardware
  157.  
  158. ;    from files module
  159.     extrn    fstat        ;file status flags
  160.     extrn    ctxfil        ;close transmit file
  161.     extrn    crxfil        ;close receive file
  162.     extrn    logdat        ;write byte to log file
  163.  
  164. ;    external addresses
  165.     
  166. ;    from level 1 module
  167.     extrn    tistat    ;timer status flags
  168.     extrn    txstat    ;transmit status flags
  169.     extrn    txaddr    ;transmit address byte
  170.     extrn    txctrl    ;transmit control byte
  171.  
  172. ;    from buffers module
  173.     extrn    rxfree    ;A(list of free rx buffer #'s)
  174.     extrn    rxflst    ;A(list of rx frame buffer #'s)
  175.     extrn    rxplst    ;A(list of rx packt buffer #'s)
  176.     extrn    rxbtab    ;A(table of rx bcb pointers)
  177.     extrn    txbtab    ;A(table of tx bcb pointers)
  178.     extrn    txbcbp    ;A(active tx bcb for I frames)
  179.     extrn    txubcb    ;A(tx bcb for CMDR frames)
  180.  
  181. ;    from files module
  182.     extrn    fstat    ;file status
  183.  
  184.  
  185.  
  186. ;    *********************************
  187. ;    *  initialization section    *
  188. ;    *********************************
  189.  
  190.     cseg        ;code section
  191.  
  192. ;    initialize level 2 parameters
  193. ;    (externally called)
  194. ;    on entry:    no parameters
  195. ;    on exit:    all flags, regs clobbered
  196.  
  197. initl2:    lda    dtemod        ;get mode flag
  198.     cpi    1        ;DTE mode?
  199.     jnz    init1        ;no, keep going
  200. ;
  201. ;    initialize in DTE mode
  202.     mvi    a,addra        ;yes, set up address=A 
  203.     sta    rxcaddr        ;for incoming commands
  204.     sta    txraddr        ;and outgoing responses
  205.     mvi    a,addrb        ;set up address=B
  206.     sta    txcaddr        ;for outgoing commands
  207.     sta    rxraddr        ;and incoming responses
  208.     jmp    init3        ;and continue
  209. ;
  210. init1:    cpi    2        ;DCE mode?
  211.     jnz    init2        ;no, keep going
  212. ;
  213. ;    initialize as DCE
  214.     mvi    a,addrb        ;set up address=B
  215.     sta    rxcaddr        ;for incoming commands
  216.     sta    txraddr        ;and outgoing responses
  217.     mvi    a,addra        ;set up address=A
  218.     sta    txcaddr        ;for outgoing commands
  219.     sta    rxraddr        ;and incoming responses
  220.     jmp    init3        ;and conitnue
  221. ;
  222. ;    initialize for self test (with loopback connector)
  223. init2:    mvi    a,addra        ;set up address=A
  224.     sta    rxcaddr        ;for incoming commands
  225.     sta    txcaddr        ;and outgoing commands
  226.     mvi    a,addrb        ;set up address=B
  227.     sta    txraddr        ;for outgoing responses
  228.     sta    rxraddr        ;and incoming responses
  229. ;
  230. init3:    call    reset        ;reset all variables
  231.     xra    a        ;reset p/f bit
  232.     sta    pfbit        ;p/f=0
  233.     ret
  234.  
  235.  
  236. ;    reset all flow control variables
  237. ;    (internally called)
  238. ;    on entry:    no parameters
  239. ;    on exit:    <a>,flags clobbered
  240.  
  241. reset:    xra    a        ;initialize variables
  242.     sta     vs        ;V(s)=0
  243.     sta    vr        ;V(r)=0
  244.     sta    l2stat        ;clear level 2 status flags
  245.     sta    lkstat        ;clear link status word
  246.     sta    tistat        ;clear all timeouts
  247.     sta    lastnr        ;last received N(r)
  248.     sta    lastvr        ;last transmitted V(r)
  249.     mvi    a,7        ;initialize...
  250.     sta    lastvs        ;last transmitted V(s)
  251.     sta    maxvs        ;max transmitted V(s)
  252.     call    clrtxb        ;clear all tx buffers
  253.     ret
  254.  
  255.  
  256.  
  257.  
  258. ;    *************************
  259. ;    *  link control section    *
  260. ;    *************************
  261.  
  262. ;    connect level 2 link
  263. ;    (externally called)
  264. ;    on entry:    no paramters
  265. ;    on exit:    all regs, flags clobbered
  266.     
  267. conlk:
  268.     call    reset        ;reset all flow control variables
  269.     call    initl3        ;initialize level 3
  270.     lxi    h,lkstat    ;point to link status word
  271.     setb    0,m        ;set link connect in process
  272.     mvi    a,n2        ;set retry counter=n2
  273.     sta    rtryct        ;    /
  274.     call    ilprt        ;tell what's doing
  275.     db    cr,lf,'L2: attempting link connect...',cr,lf,0
  276.     jmp    txsabm        ;and transmit SABM command
  277.  
  278.  
  279.  
  280. ;    disconnect level 2 link
  281. ;    (externally called)
  282. ;    on entry:    no paramters
  283. ;    on exit:    all regs, flags clobbered
  284.  
  285. disclk:
  286.     call    crxfil        ;close receive file if open
  287.     call    ctxfil        ;close receive file if open
  288.     call    clrtxb        ;clear all tx I buffers
  289.     lxi    h,lkstat    ;point to link status
  290.     res    1,m        ;clear disc in process
  291.     bit    2,m        ;is link connected?
  292.     jnz    disc1        ;yes, keep going
  293. ;
  294.     call    ilprt        ;else tell operator
  295.     db    'L2: link is already disconnected',cr,lf,0
  296.     ret
  297. ;
  298. disc1:    setb    1,m        ;signal disc in process
  299.     mvi    a,n2        ;set retry count= n2
  300.     sta    rtryct        ;    /
  301.     call    ilprt        ;and tell operator
  302.     db    cr,lf,'L2: attempting link disconnect...',cr,lf,0
  303.     jmp    txdisc        ;and transmit disconnect command
  304.  
  305.  
  306. ;    query link status
  307. ;    (externally called)
  308. ;    on entry:    no parameters
  309. ;    on exit:    all regs, flags clobbered
  310.  
  311. qlksta:    lxi    h,lkstat    ;point to link status word
  312.     bit    2,m        ;link connected?
  313.     jnz    qlk1        ;yes, keep going
  314. ;
  315.     call    ilprt        ;else tell operator
  316.     db    'L2: dte link is disconnected',cr,lf,0
  317.     ret
  318. ;
  319. ;    determine dte status
  320. qlk1:    push    h        ;save <hl>
  321.     lxi    h,l2stat    ;point to flow status word
  322.     bit    1,m        ;DTE FRMR/CMDR condition?
  323.     pop    h        ;restore <hl>
  324.     jz    qlk2        ;no, keep going
  325. ;
  326.     call    ilprt        ;else tell operator
  327.     db    'L2: dte in FRMR/CMDR condition',cr,lf,0
  328.     jmp    qlk5        ;and get dce status
  329. ;    
  330. qlk2:    bit    4,m        ;dte busy?
  331.     jz    qlk3        ;no, keep going
  332. ;
  333.     call    ilprt        ;else tell operator
  334.     db    'L2: dte busy',cr,lf,0
  335.     jmp    qlk5        ;and get dce status
  336. ;
  337. qlk3:    bit    6,m        ;dte reject condition?
  338.     jz    qlk4        ;no, keep going
  339. ;
  340.     call    ilprt        ;else tell operator
  341.     db    'L2: dte in REJ condition',cr,lf,0
  342.     jmp    qlk5        ;and get dce status
  343. ;
  344. qlk4:    call    ilprt        ;tell operator we are ready
  345.     db    'L2: dte ready',cr,lf,0
  346.  
  347. ;    interogate DCE status
  348. qlk5:    lxi    h,l2stat    ;point to level 2 status
  349.     setb    0,m        ;signal query in process
  350.     mvi    a,n2        ;set retry count =n2
  351.     sta    rtryct        ;    /
  352.     call    ilprt        ;tell operator
  353.     db    'L2: interrogating dce status...',cr,lf,0
  354. ;
  355. ;    return here for retries
  356. qdce:
  357.     lxi    h,pfbit        ;set p=1
  358.     setb    4,m        ;    /
  359.     lxi    h,lkstat    ;point to link status
  360.     bit    4,m        ;dte busy?
  361.     jnz    txrnrc        ;yes, transmit RNR command
  362. ;
  363.     bit    6,m        ;dte rej condition?
  364.     jnz    txrejc        ;yes, transmit REJ command
  365. ;
  366.     jmp    txrrc        ;else transmit RR command
  367.  
  368.  
  369.  
  370. ;    *************************
  371. ;    *  transmit section    *
  372. ;    *************************
  373.  
  374. ;    *** miscellaneous ***
  375.  
  376. ;    get address of free tx buffer bcb
  377. ;    (externally called)
  378. ;    on entry:    no parameters
  379. ;    on exit:    carry set if no free buffer avail
  380. ;            <hl>= bcb address if buffer avail
  381. ;            <a>, other flags clobbered
  382.  
  383. gettxb:    push    b        ;save regs
  384.     push    d        ;    /
  385.     lda    lastnr        ;get last acknowledged N(r)
  386.     dcr    a        ;back up two, mod 7
  387.     dcr    a        ;    /
  388.     ani    7        ;      /
  389.     mov    b,a        ;<b> is last possible bcb #
  390.     lda    maxvs        ;<a> is first possible bcb #
  391.     inr    a        ;    /
  392.     ani    7        ;      /
  393. gettx1:    cmp    b        ;are they equal?
  394.     stc            ;yes, return with carry set
  395.     jz    getxit        ;    /
  396. ;
  397.     lxi    h,txbtab    ;else, get bcb address
  398.     call    bpoint        ;    /
  399.     call    getrdy        ;is buffer empty?
  400.     jz    getxok        ;yes, got one
  401. ;
  402.     inr    a        ;else, look at next one
  403.     ani    7        ;mod 7, of course
  404.     jmp    gettx1        ;    /
  405. ;
  406. getxok:    stc            ;clear carry flag
  407.     cmc            ;    /
  408. getxit:    pop    d        ;restore regs
  409.     pop    b        ;    /
  410.     ret
  411.  
  412.  
  413. ;    *** outgoing commands ***
  414.  
  415.  
  416. ;    check for timeout condition and 
  417. ;    transmit I frame if available and
  418. ;        a) link connected
  419. ;        b) DCE not busy
  420. ;        c) level 1 (SIO) not already transmitting
  421. ;        d) not in FRMR condition
  422. ;        e) new frame within window
  423. ;        f) frame ready flag <>0
  424. ;    if I frame can't be transmitted, transmit
  425. ;    RR or RNR frame to acknowledge received I frames
  426. ;
  427. ;    (externally called)
  428. ;    on entry:    no parameters
  429. ;    on exit:    all regs, flags clobbered
  430.  
  431.  
  432. txifrm:    
  433. ;    check for level 1 ready
  434.     lxi    h,txstat    ;point to level 1 (SIO) status
  435.     bit    0,m        ;tx busy?
  436.     rnz            ;yes, try again later
  437. ;
  438. ;    check for timeout
  439.     lxi    h,tistat    ;point to timer status
  440.     bit    0,m        ;timer T1 timed out?
  441.     jnz    t1to        ;yes, service it
  442. ;
  443. ;    check for level 2 ready
  444.     lxi    h,lkstat    ;point to link status
  445.     bit    2,m        ;link connected?
  446.     rz            ;no, return
  447. ;
  448. ;    check if in timer recovery condition
  449.     lxi    h,l2stat    ;point to flow status
  450.     bit    7,m        ;timer recovery condition?
  451.     jz    txi1        ;no, keep going
  452. ;    
  453. ;    timer recovery condition
  454.     push    h        ;save flow status word
  455.     lxi    h,pfbit        ;set P=1
  456.     setb    4,m        ;   /
  457.     pop    h        ;restore flow status word
  458.     bit    6,m        ;time to transmit again?
  459.     jz    txack        ;no, see if we want to acknowledge
  460. ;
  461.     bit    2,m        ;DCE FRMR/CMDR condition?
  462.     jnz    qlksta        ;yes, verify again & restart
  463. ;
  464.     lxi    h,lkstat    ;point to link status
  465.     bit    3,m        ;DCE busy?
  466.     jnz    txack        ;yes, don't transmit I frame
  467. ;
  468.     lxi    h,l2stat    ;point to level 2 status
  469.     res    6,m        ;else reset restransmission flag
  470.     jmp    txi2        ;and retransmit I frame
  471. ;
  472. ;    not in timer recovery condition
  473. txi1:    bit    2,m        ;DCE FRMR/CMDR condition?
  474.     rnz            ;yes, don't transmit I frames
  475. ;
  476.     bit    0,m        ;link query in process?
  477.     rnz            ;yes, dont transmit yet
  478. ;
  479.     lxi    h,lkstat    ;point to link status
  480.     bit    3,m        ;DCE busy?
  481.     jnz    txack        ;yes, don't transmit I frame
  482. ;
  483. ;    did we transmit new frame already?
  484.     lda    lastvs        ;get last transmitted V(s)
  485.     mov    b,a        ;save in <b>
  486.     lda    vs        ;get present vs
  487.     cmp    b        ;same?
  488.     jz    txack        ;yes, don't transmit I frame
  489. ;
  490. ;    else set up retry counter for new frame
  491.     mvi    a,n2        ;else initialize retry count
  492.     sta    rtryct        ;    /
  493.     lxi    h,pfbit        ;and set p=0
  494.     res    4,m        ;    /
  495. ;
  496. ;    check that V(s) is within window
  497. txi2:    lda    lastnr        ;get last valid N(r)
  498.     adi    kconst+1    ;calculate just past top of window
  499.     ani    7        ;mod 7
  500.     mov    e,a        ;save in <e>
  501.     lda    vs        ;get V(s)
  502.     cmp    e        ;is V(s) past top of window?
  503.     jz    txack        ;yes, don't transmit it yet
  504. ;
  505. ;    is tx buffer ready?
  506. txi2a    lxi    h,txbtab    ;point to tx bcb table
  507.     lda    vs        ;get V(s)
  508.     call    bpoint        ;get address of bcb
  509.     call    getrdy        ;is buffer ready to tx?
  510.     jz    txack        ;no, some other time
  511. ;
  512. ;    transmit frame if not empty and ready
  513.     shld    txbcbp        ;make buffer active
  514.     call    savbcb        ;and save bcb pointers
  515.     lda    txcaddr        ;<d>=outgoing command address
  516.     mov    d,a        ;    /
  517. ;
  518.     lda    vs        ;get V(s)
  519.     sta    lastvs        ;update last tx V(s)
  520. ;
  521.     if    debug        ;if debug mode
  522.     push    psw        ;save V(s)
  523.     adi    '0'        ;convert to ASCII
  524.     call    ctype        ;display it
  525.     pop    psw        ;restore V(s)
  526.     endif            ;end of debug mode
  527. ;
  528.     mvi    b,ifid        ;<b>=I control byte
  529.     rlc            ;rotate V(s) into bits 1-3
  530.     ora    b        ;merge with control byte
  531.     mov    b,a        ;save result in <b>
  532.     lda    vr        ;get V(r) (outgoing N(r))
  533.     sta    lastvr        ;update last tx V(r)
  534.     mov    c,a        ;save in <c>
  535.     call    txframe        ;transmit frame
  536.     call    t1on        ;turn on timer T1
  537.     lhld    txifct        ;increment tx I frame count
  538.     inx    h        ;    /
  539.     shld    txifct        ;      /
  540.     mvi    a,kack        ;reset acknowledgement delay counter
  541.     sta    ackcnt        ;    /
  542. ;
  543. ;    timer recovery condition?
  544.     lxi    h,l2stat    ;point to level 2 status
  545.     bit    7,m        ;timer recovery condition?
  546.     rnz            ;yes, don't update V(s)
  547. ;
  548. ;    update V(s) to send next frame
  549.     lda    vs        ;get V(s)
  550.     mov    b,a        ;and save in <b>
  551.     inr    a        ;V(s)=V(s)+1 mod 7
  552.     ani    7        ;    /
  553.     sta    vs        ;update V(s) for next frame
  554. ;
  555. ;    update max V(s) for acknowledge routine
  556.     lda    maxvs        ;get current max V(s)
  557. txi4:    cmp    b        ;is max V(s)= last tx V(s)
  558.     jz    txi5        ;yes, exit
  559. ;    
  560.     cmp    e        ;past top of window?
  561.     rz            ;yes, maxvs was max
  562. ;
  563.     inr    a        ;else bump max V(s) mod(7)
  564.     ani    7        ;    /
  565.     jmp    txi4        ;and keep looping
  566. ;
  567. txi5:    sta    maxvs        ;update max V(s)
  568.     ret            ;and exit
  569. ;
  570. ;    transmit acknowledgement instead of I frame
  571. txack:    lda    lastvr        ;get last transmitted V(r)
  572.     mov    b,a        ;save in <b>
  573.     lda    vr        ;get V(r)
  574.     cmp    b        ;same?
  575.     rz            ;yes, nothing to acknowledge
  576. ;
  577. ;    wait a few tries to see if any I frames are coming
  578.     lda    ackcnt        ;get delay count
  579.     dcr    a        ;decrement count
  580.     sta    ackcnt        ;and update count
  581.     rnz            ;wait a little longer until 0
  582. ;
  583. ;    delay count is 0, transmit acknowledge frame
  584.     mvi    a,kack        ;reset delay count
  585.     sta    ackcnt        ;    /
  586.     lxi    h,lkstat    ;else point to link status
  587.     bit    4,m        ;DTE busy?
  588.     jnz    txrnrr        ;yes, transmit RNR frame
  589. ;
  590.     jmp    txrrr        ;else transmit RR frame
  591.  
  592.  
  593.  
  594.  
  595. ;    process timer T1 timeout condition
  596. ;    (internally called)
  597. ;    on entry:    no parameters
  598. ;    on exit:    all regs, flags clobbered
  599.  
  600. t1to:    
  601.     call    t1off        ;stop timer T1
  602.     lxi    h,rtryct    ;get retry count
  603.     dcr    m        ;last retry?
  604.     jz    t1to9        ;yes, other end is dead
  605. ;
  606.     lxi    h,lkstat    ;point to link status
  607.     bit    0,m        ;link connect in process?
  608.     jz    t1to1        ;no, keep going
  609. ;
  610. ;    link connect is in process
  611.     call    ilprt        ;print countdown
  612.     db    tab,'SABM tries to go =',0
  613.     lda    rtryct        ;print countdown
  614.     mov    l,a        ;    /
  615.     mvi    h,0        ;      /
  616.     call    pdec        ;     /
  617.     call    ilprt        ;    /
  618.     db    cr,lf,0        ;   /
  619.     jmp    txsabm        ;and transmit SABM
  620. ;
  621. t1to1:    bit    1,m        ;disconnect in process?
  622.     jz    t1to2        ;no, keep going
  623. ;
  624. ;    link disconnect is in process
  625.     call    ilprt        ;print countdown
  626.     db    tab,'DISC tries to go =',0
  627.     lda    rtryct        ;print countdown
  628.     mov    l,a        ;    /
  629.     mvi    h,0        ;      /
  630.     call    pdec        ;     /
  631.     call    ilprt        ;    /
  632.     db    cr,lf,0        ;   /
  633.     jmp    txdisc        ;and transmit DISC
  634. ;
  635. t1to2:    lxi    h,l2stat    ;point to level 2 status
  636.     bit    0,m        ;link query in process
  637.     jz    t1to3        ;no, keep going
  638. ;
  639. ;    link query is in process
  640.     call    ilprt        ;print countdown
  641.     db    tab,'query tries to go =',0
  642.     lda    rtryct        ;print countdown
  643.     mov    l,a        ;    /
  644.     mvi    h,0        ;      /
  645.     call    pdec        ;     /
  646.     call    ilprt        ;    /
  647.     db    cr,lf,0        ;   /
  648.     jmp    qdce        ;and query dce
  649. ;
  650. ;    check that link is connected
  651. t1to3:    lxi    h,lkstat    ;point to link status flags
  652.     bit    2,m        ;link connected?
  653.     rz            ;no, just return
  654.  
  655. ;    information flow is in process
  656. ;    timeout recovery (x.25 para 2.4.6.8)
  657.     lxi    h,l2stat    ;point to level 2 status
  658.     setb    7,m        ;indicate timer recovery condition
  659.     setb    6,m        ;set flag for retransmission
  660.     call    ilprt        ;tell what we're doing
  661.     db    cr,lf,'L2: T1 timed out - '
  662.     db    'retransmitting I frame',0
  663.     lda    lastnr        ;make V(s)=last received N(r)
  664.     sta    vs        ;    /
  665.     mov    l,a        ;print V(s)
  666.     mvi    h,0        ;    /
  667.     call    pdec        ;      /
  668.     call    ilprt        ;and try number
  669.     db    ' - tries to go =',0
  670.     lda    rtryct        ;      /
  671.     mov    l,a        ;     /
  672.     mvi    h,0        ;    /
  673.     call    pdec        ;   /
  674.     call    ilprt        ;terminate line
  675.     db    cr,lf,0        ;    /
  676.     lxi    h,pfbit        ;set p=1
  677.     setb    4,m        ;    /
  678.     lhld    txirct        ;increment retransmission log
  679.     inx    h        ;    /
  680.     shld    txirct        ;      /
  681.     ret
  682. ;
  683. ;    retry count exhausted
  684. t1to9:    call    ilprt
  685.     db    'L2: tx retry count exhausted - '
  686.     db    'no reply from DCE',cr,lf,0
  687.     lxi    h,lkstat    ;point to link status
  688.     bit    1,m        ;was disconnect in process?
  689.     jz    t1to10        ;no, keep going
  690. ;
  691. ;    disconnect was already in process
  692.     res    1,m        ;clear disconnect in process
  693.     res    2,m        ;and clear link connect flag
  694. ;
  695. t1to10:    bit    2,m        ;link connected?
  696.     rz            ;no, return
  697. ;
  698. ;    link was connected (?)
  699.     call    ilprt
  700.     db    'L2; disconnecting link',cr,lf,0
  701.     jmp    disclk        ;and disconnect
  702.  
  703.  
  704.  
  705. ;    transmit SABM command frame
  706. ;    (internally called)
  707. ;    on entry:    no paramters
  708. ;    on exit:    all flags, regs clobbered
  709.  
  710. txsabm:    lxi    h,lkstat    ;point to link status
  711.     setb    0,m        ;signal connect in process
  712.     lda    txcaddr        ;<d>=outgoing command address
  713.     mov    d,a        ;    /
  714.     mvi    b,sabmfid    ;<b>=SABM control byte
  715.     mvi    c,0        ;SABM is unnumbered
  716.     call    txframe        ;transmit frame
  717.     call    t1on        ;and turn on timer T1
  718.     ret
  719.  
  720. ;    transmit DISC command frame
  721. ;    on entry:    no paramters
  722. ;    on exit:    all flags, regs clobbered
  723.  
  724. txdisc:    lda    txcaddr        ;<d>=outgoing command address
  725.     mov    d,a        ;    /
  726.     mvi    b,discfid    ;<b>=DISC control byte
  727.     mvi    c,0        ;DISC is unnumbered
  728.     call    txframe        ;transmit frame
  729.     call    t1on        ;and turn on timer T1
  730.     ret
  731.  
  732. ;    transmit bad command frame
  733. ;    on entry:    no paramters
  734. ;    on exit:    all flags, regs clobbered
  735.  
  736. txbadf:    lda    txcaddr        ;<d>=outgoing command address
  737.     mov    d,a        ;    /
  738.     mvi    b,badfid    ;<b>=bad control byte
  739.     mvi    c,0        ;make it unnumbered
  740.     call    txframe        ;transmit frame
  741.     ret
  742.  
  743. ;    transmit RR command frame
  744. ;    on entry:    no paramters
  745. ;    on exit:    all flags, regs clobbered
  746.  
  747. txrrc:    lda    txcaddr        ;<d>=outgoing command address
  748.     mov    d,a        ;    /
  749.     mvi    b,rrfid        ;<b>=RR control byte
  750.     lda    vr        ;get V(r)
  751.     sta    lastvr        ;update last tx V(r)
  752.     mov    c,a        ;save in <c>
  753.     call    txframe        ;transmit frame
  754.     call    t1on        ;turn on timer T1
  755.     ret
  756.  
  757. ;    transmit RNR command frame
  758. ;    on entry:    no paramters
  759. ;    on exit:    all flags, regs clobbered
  760.  
  761. txrnrc:    lda    txcaddr        ;<d>=outgoing command address
  762.     mov    d,a        ;    /
  763.     mvi    b,rnrfid    ;<b>=RNR control byte
  764.     lda    vr        ;get V(r)
  765.     sta    lastvr        ;update last tx V(r)
  766.     mov    c,a        ;save in <c>
  767.     call    txframe        ;transmit frame
  768.     call    t1on        ;and turn on timer T1
  769.     ret
  770.  
  771. ;    transmit REJ command frame
  772. ;    on entry:    no paramters
  773. ;    on exit:    all flags, regs clobbered
  774.  
  775. txrejc:    lda    txcaddr        ;<d>=outgoing command address
  776.     mov    d,a        ;    /
  777.     mvi    b,rejfid    ;<b>=REJ control byte
  778.     lda    vr        ;get V(r)
  779.     sta    lastvr        ;update last tx V(r)
  780.     mov    c,a        ;save in <c>
  781.     call    txframe        ;transmit frame
  782.     call    t1on        ;and turn on timer T1
  783.     ret
  784.  
  785.  
  786. ;    *** outgoing responses ***
  787.  
  788.  
  789. ;    transmit RR response frame
  790. ;    on entry:    no paramters
  791. ;    on exit:    all flags, regs clobbered
  792.  
  793. txrrr:    lda    txraddr        ;<d>=outgoing response address
  794.     mov    d,a        ;    /
  795.     mvi    b,rrfid        ;<b>=RR control byte
  796.     lda    vr        ;get V(r)
  797.     sta    lastvr        ;update last tx V(r)
  798.     mov    c,a        ;save in <c>
  799.     call    txframe        ;transmit frame
  800.     ret
  801.  
  802. ;    transmit RNR response frame
  803. ;    on entry:    no paramters
  804. ;    on exit:    all flags, regs clobbered
  805.  
  806. txrnrr:    lda    txraddr        ;<d>=outgoing response address
  807.     mov    d,a        ;    /
  808.     mvi    b,rnrfid    ;<b>=RNR control byte
  809.     lda    vr        ;get V(r)
  810.     sta    lastvr        ;update last tx V(r)
  811.     mov    c,a        ;save in <c>
  812.     call    txframe        ;transmit frame
  813.     ret
  814.  
  815. ;    transmit REJ response frame
  816. ;    on entry:    no paramters
  817. ;    on exit:    all flags, regs clobbered
  818.  
  819. txrejr:    lda    txraddr        ;<d>=outgoing response address
  820.     mov    d,a        ;    /
  821.     mvi    b,rejfid    ;<b>=REJ control byte
  822.     lda    vr        ;get V(r)
  823.     sta    lastvr        ;update last tx V(r)
  824.     mov    c,a        ;save in <c>
  825.     call    txframe        ;transmit frame
  826.     ret
  827.  
  828. ;    transmit DM response frame
  829. ;    on entry:    no paramters
  830. ;    on exit:    all flags, regs clobbered
  831.  
  832. txdm:    lda    txraddr        ;<d>=outgoing response address
  833.     mov    d,a        ;    /
  834.     mvi    b,dmfid        ;get DM control byte
  835.     mvi    c,0        ;DM is unnumbered
  836.     call    txframe        ;transmit frame
  837.     ret
  838.  
  839. ;    transmit UA response frame
  840. ;    on entry:    no paramters
  841. ;    on exit:    all flags, regs clobbered
  842.  
  843. txua:    lda    txraddr        ;<d>=outgoing response address
  844.     mov    d,a        ;    /
  845.     mvi    b,uafid        ;get UA control byte
  846.     mvi    c,0        ;UA is unnumbered
  847.     call    txframe        ;transmit frame
  848.     ret
  849.  
  850.  
  851. ;    transmit CMDR/FRMR response frame
  852. ;    on entry:    no paramters
  853. ;    on exit:    all flags, regs clobbered
  854.  
  855. txfrmr:
  856. txcmdr:    lxi    h,txstat    ;point to link SIO status
  857.     bit    0,m        ;tx busy?
  858.     jnz    txcmdr        ;yes, wait
  859. ;
  860.     lxi    h,l2stat    ;point to flow status word
  861.     setb    1,m        ;set DTE FRMR condition flag
  862.     lxi    h,txubcb    ;point to CMDR frame buffer
  863.     shld    txbcbp        ;and make buffer active
  864.     lda    cmdrf1        ;get rejected cmd control byte
  865.     call    putbuf        ;put in buffer
  866.     lda    vs        ;get V(s)
  867.     rlc            ;rotate into bits 1-3
  868.     mov    b,a        ;save in <b>
  869.     lda    vr        ;get V(r)
  870.     rlc            ;rotate into bits 5-7
  871.     rlc            ;    /
  872.     rlc            ;      /
  873.     rlc            ;     /
  874.     rlc            ;    /
  875.     ora    b        ;merge with V(s)
  876.     call    putbuf        ;put in buffer
  877.     lda    cmdrf3        ;get error indicator byte
  878.     call    putbuf        ;put in buffer
  879.     lda    txraddr        ;<d>=outgoing response address
  880.     mov    d,a        ;    /
  881.     mvi    b,cmdrfid    ;<b>=CMDR control byte
  882.     mvi    c,0        ;CMDR is unnumbered
  883.     call    txframe        ;transmit frame
  884.     ret
  885.  
  886.     
  887. ;    ***  common routines ***
  888.  
  889.  
  890. ;    transmit frame
  891. ;    (internally called)
  892. ;    on entry:    <b>=frame control byte
  893. ;            <c>=0 if unnumbered, N(r) otherwise
  894. ;            <d>=frame address byte
  895. ;            pfbit=poll/final bit in pos 4
  896. ;    on exit:    flags, registers clobbered
  897. ;            txaddr= address byte
  898. ;            txctrl= control byte
  899.  
  900.  
  901. txframe:
  902.     lhld    txfct        ;increment tx frame counter
  903.     inx    h        ;    /
  904.     shld    txfct        ;      /
  905.     lxi    h,txstat    ;point to SIO status
  906. txf1:    bit    0,m        ;tx busy?
  907.     jnz    txf1        ;yes, wait
  908. ;
  909.     mov    a,d        ;get address byte
  910.     sta    txaddr        ;store address
  911.     mov    a,c        ;get N(r)
  912.     rlc            ;rotate into bits 5-7
  913.     rlc            ;    /
  914.     rlc            ;      /
  915.     rlc            ;     /
  916.     rlc            ;    /
  917.     ora    b        ;merge with control byte
  918.     mov    b,a        ;save result in <b>
  919.     lda    pfbit        ;get poll/final bit
  920.     ora    b        ;merge it into control byte
  921.     sta    txctrl        ;store control byte
  922.     call    logtx        ;log transmission
  923.     xra    a        ;clear p/f bit for next frame
  924.     sta    pfbit        ;    /
  925.     call    txwake        ;start transmission and T1 timer
  926.     ret
  927.  
  928.  
  929. ;    log transmitted frame
  930. ;    (internally called)
  931. ;    on entry:    txaddr= address byte
  932. ;            txctrl= control byte
  933. ;    on exit:    <a>, flags clobbered
  934. ;            all other regs unchanged
  935. logtx:    push    h        ;save <hl>
  936.     lxi    h,fstat        ;point to file status
  937.     bit    7,m        ;log file open?
  938.     pop    h        ;restore <hl>
  939.     rz            ;no, return with no action
  940. ;
  941.     mvi    a,1        ;else signal tx frame
  942.     call    logdat        ;put in file
  943.     lda    txaddr        ;get address
  944.     call    logdat        ;put in file
  945.     lda    txctrl        ;get control
  946.     call    logdat        ;put in file
  947.     xra    a        ;and put zeros in rest of block
  948.     call    logdat        ;        /
  949.     call    logdat        ;              /
  950.     call    logdat        ;             /
  951.     call    logdat        ;            /
  952.     call    logdat        ;           /
  953.     call    logdat        ;          /
  954.     call    logdat        ;         /
  955.     call    logdat        ;        /
  956.     call    logdat        ;    /
  957.     call    logdat        ;      /
  958.     call    logdat        ;     /
  959.     call    logdat        ;    /
  960.     call    logdat        ;   /
  961.     ret
  962.  
  963.  
  964.  
  965.  
  966. ;    *************************
  967. ;    *  receive section    *
  968. ;    *************************
  969.  
  970.  
  971. ;    process a received frame if available
  972. ;    (internally and externally called)
  973. ;    on entry:    no parameters
  974. ;    on exit:    <c>=buffer # if available
  975. ;            <hl>=bcb address if available
  976. ;            <d>=address byte
  977.  
  978. rxfrm:
  979.     lxi    h,rxflst    ;point to list of rx frames
  980.     call    getbuf        ;any waiting?
  981.     rc            ;no, return
  982. ;
  983.     mov    c,a        ;save buffer # in <c>
  984.     lxi    h,rxbtab    ;point to table of buffer addresses
  985.     call    bpoint        ;get address of bcb
  986.     call    dcrbuf        ;discard CRC-1 byte
  987.     call    getbuf        ;get address byte
  988.     jnc    rxfrm0        ;keep going if there
  989. ;
  990. ;    empty frame
  991.     mov    a,c        ;else release rx buffer
  992.     call    rlsrxb        ;    /
  993.     call    ilprt        ;and tell operator
  994.     db    'L2: rx empty frame (no control byte)',cr,lf,0
  995.     ret
  996. ;
  997. rxfrm0:    mov    d,a        ;save in <d>
  998.     lda    rxcaddr        ;incoming command?
  999.     cmp    d        ;    /
  1000.     jz    incmd        ;yes, process it
  1001. ;
  1002.     lda    rxraddr        ;incoming response?
  1003.     cmp    d        ;    /
  1004.     jz    inresp        ;yes, process it
  1005. ;
  1006. ;    process bad address
  1007.     call    ilprt
  1008.     db    cr,lf,'L2: bad rx address: ',0
  1009.     mov    a,d        ;get bad address byte
  1010.     call    phex        ;print address in hex
  1011. ;
  1012. ;***    dump entire frame in hex for debug
  1013.     if    debug
  1014.     call    ilprt
  1015.     db    cr,lf,'L2: frame contents: ',0
  1016. rxfrlp: call    getbuf        ;get next octet
  1017.     jc    rxfrm1        ;exit if no more
  1018.     call    phex        ;print it in hex
  1019.     mvi    a,' '        ;and a separator
  1020.     call    ctype        ;    /
  1021.     jmp    rxfrlp        ;and go back for more
  1022.     endif            ;end of debug option
  1023. ;
  1024. rxfrm1:
  1025.     call    ilprt        ;terminate error msg line
  1026.     db    cr,lf,0        ;    /
  1027.     mov    a,c        ;get rx buffer #
  1028.     call    rlsrxb        ;and release it
  1029.     lhld    rbafct        ;increment bad address counter
  1030.     inx    h        ;    /
  1031.     shld    rbafct        ;      /
  1032.     ret
  1033.  
  1034.  
  1035. ;    process incoming comand frame
  1036. ;    (internally called)
  1037. ;    on entry:    <hl>=bcb address
  1038. ;            <c>= rx buffer #
  1039. ;            <d>=address byte 
  1040. ;    on exit:    <b>=control byte
  1041. ;            <c>,<d>,<hl> unchanged
  1042.  
  1043. incmd:    call    getbuf        ;get control byte
  1044.     jnc    incmd1        ;if there is one
  1045. ;
  1046.     mov    a,c        ;else release rx buffer
  1047.     call    rlsrxb        ;    /
  1048.     lhld    rxbcct        ;increment bad command count
  1049.     inx    h        ;    /
  1050.     shld    rxbcct        ;      /
  1051.     ret
  1052. ;
  1053. incmd1:    mov    b,a        ;save control byte in <b>
  1054.     sta    cmdrf1        ;save it in case of CMDR
  1055.     ani    0001$0000b    ;extract P bit
  1056.     sta    pfbit        ;set F bit for reply
  1057.     push    h        ;save <hl>
  1058.     lhld    rxcfct        ;increment rx command count
  1059.     inx    h        ;    /
  1060.     shld    rxcfct        ;      /
  1061.     call    logrx        ;log received frame
  1062.     lxi    h,lkstat    ;point to link status word
  1063.     bit    2,m        ;link disconnected?
  1064.     pop    h        ;restore <hl>
  1065.     jz    dphase        ;yes, process disconnected phase 
  1066. ;
  1067. ;    link is connected
  1068. ;    branch to know frame id's
  1069.     mov    a,b        ;get control byte
  1070.     bit    0,a        ;I frame?
  1071.     jz    rxi        ;yes, process it
  1072. ;
  1073.     ani    1110$1111b    ;extract all bits except p/f
  1074.     cpi    sabmfid        ;SABM frame?
  1075.     jz    rxsabm        ;yes, process it
  1076. ;
  1077.     cpi    discfid        ;DISC frame?
  1078.     jz    rxdisc        ;yes, process it
  1079. ;
  1080. ;    branch to numbered frames
  1081.     ani    0000$1111b    ;discard N(r) sequence bits
  1082.     cpi    rrfid        ;RR command frame?
  1083.     jz    rxcrr        ;yes, process it
  1084. ;
  1085.     cpi    rnrfid        ;RNR command frame?
  1086.     jz    rxcrnr        ;yes, process it
  1087. ;
  1088.     cpi    rejfid        ;REJ command frame?
  1089.     jz    rxcrej        ;yes, process it
  1090. ;
  1091. ;    unrecognized frame identifier
  1092.     mov    a,c        ;else get buffer #
  1093.     call    rlsrxb        ;discard unknown rx frame
  1094.     lhld    rxbcct        ;increment bad cmd counter
  1095.     inx    h        ;    /
  1096.     shld    rxbcct        ;      /
  1097.     lxi    h,cmdrf2    ;clear CMDR bit 13 for cmd
  1098.     res    4,m        ;    /
  1099.     lxi    h,cmdrf3    ;set CMDR bit W
  1100.     setb    0,m        ;    /
  1101.     res    1,m        ;and reset bit X
  1102.     res    2,m        ;and bit Y
  1103.     res    3,m        ;and bit Z
  1104.     jmp    txcmdr        ;and transmit CMDR
  1105. ;
  1106. ;    process link disconnected phase
  1107. dphase:
  1108.     mov    a,c        ;get rx buffer #
  1109.     call    rlsrxb        ;and release buffer
  1110.     mov    a,b        ;get control byte
  1111.     ani    1110$1111b    ;strip p bit
  1112.     cpi    sabmfid        ;SABM frame?
  1113.     jz    rxsabm        ;yes, process it
  1114. ;
  1115. ;    reply DM to any other command frames with P=1
  1116.     bit    4,b        ;P=1?
  1117.     rz            ;no, exit
  1118. ;
  1119.     jmp    txdm        ;yes, send DM response
  1120.  
  1121.  
  1122.  
  1123. ;    log incoming frame
  1124. ;    (internally called)
  1125. ;    on entry:    <b>=control byte
  1126. ;            <d>=address byte
  1127. ;    on exit:    <a>,flags clobbered
  1128. ;            all other regs unchanged
  1129. logrx:    push    h        ;save <hl>
  1130.     lxi    h,fstat        ;point to file status
  1131.     bit    7,m        ;log file open?
  1132.     pop    h        ;restore <hl>
  1133.     rz            ;no, do nothing
  1134. ;
  1135.     mvi    a,0        ;else signal rx frame
  1136.     call    logdat        ;and put in file
  1137.     mov    a,d        ;get address
  1138.     call    logdat        ;and put in file
  1139.     mov    a,b        ;get control byte
  1140.     call    logdat        ;and put in file
  1141.     xra    a        ;put zeroes in rest of block
  1142.     call    logdat        ;        /
  1143.     call    logdat        ;           /
  1144.     call    logdat        ;          /
  1145.     call    logdat        ;         /
  1146.     call    logdat        ;        /
  1147.     call    logdat        ;       /
  1148.     call    logdat        ;      /
  1149.     call    logdat        ;     /
  1150.     call    logdat        ;    /
  1151.     call    logdat        ;      /
  1152.     call    logdat        ;     /
  1153.     call    logdat        ;    /
  1154.     call    logdat        ;   /
  1155.     ret    
  1156.  
  1157.  
  1158.  
  1159. ;    process received SABM command frame
  1160. ;    (internally called)
  1161. ;    on entry:    <hl>=bcb address
  1162. ;            <b>=control byte
  1163. ;            <c>=rx buffer #
  1164.  
  1165. rxsabm:    call    getbuf        ;check if any I bits
  1166.     jnc    cfmterr        ;yes, format error
  1167. ;
  1168.     mov    a,c        ;get rx buffer #
  1169.     call    rlsrxb        ;release buffer
  1170.     call    t1off        ;turn off timer T1
  1171.     call    reset        ;clear flow control variables
  1172.     lxi    h,lkstat    ;point to link status
  1173.     setb    2,m        ;set link active flag
  1174.     call    ilprt        ;tell operator link is ok
  1175.     db    'L2: rx SABM - link connected by dce',cr,lf,0
  1176.     jmp    txua        ;and transmit UA
  1177.  
  1178.  
  1179. ;    process received DISC command frame
  1180. ;    (internally called)
  1181. ;    on entry:    <hl>=bcb address
  1182. ;            <b>=control byte
  1183. ;            <c>=rx buffer #
  1184.  
  1185. rxdisc:    call    getbuf        ;check if any I bits
  1186.     jnc    cfmterr        ;yes, format error
  1187. ;
  1188.     mov    a,c        ;release rx buffer
  1189.     call    rlsrxb        ;    /
  1190.     call    t1off        ;turn off timer T1
  1191.     lxi    h,lkstat    ;point to link status
  1192.     mvi    m,0        ;clear everything
  1193.     setb    2,m        ;except link connected
  1194.     setb    1,m        ;and link disc in process
  1195.     call    ilprt        ;tell operator link is down
  1196.     db    'L2: rx DISC - link disconnected by dce',cr,lf,0
  1197.     call    txua        ;transmit UA
  1198.     lxi    h,lkstat    ;point to link status
  1199.     res    1,m        ;clear disc in process
  1200.     res    2,m        ;and link connected
  1201.     ret
  1202.  
  1203.  
  1204. ;    process received RR command frame
  1205. ;    (internally called)
  1206. ;    on entry:    <hl>=bcb address
  1207. ;            <b>=control byte
  1208. ;            <c>=rx buffer #
  1209.  
  1210. rxcrr:    call    ackdge        ;acknowledge pending frames
  1211.     jc    badnr        ;exit if invalid N(r)
  1212. ;
  1213.     call    getbuf        ;another byte in buffer?
  1214.     jnc    cfmterr        ;yes, format errer
  1215. ;
  1216.     lxi    h,lkstat    ;point to link status byte
  1217.     res    3,m        ;clear DCE busy
  1218.     res    7,m        ;clear DCE reject condition
  1219.     jmp    rxsc        ;and process supervisory cmd
  1220.  
  1221.     
  1222. ;    process received RNR command frame
  1223. ;    (internally called)
  1224. ;    on entry:    <hl>=bcb address
  1225. ;            <b>=control byte
  1226. ;            <c>=rx buffer #
  1227.  
  1228. rxcrnr:    call    ackdge        ;acknowledge pending frames
  1229.     jc    badnr        ;exit if invalid N(r)
  1230. ;
  1231.     call    getbuf        ;another byte in buffer?
  1232.     jnc    cfmterr        ;yes, format errer
  1233. ;
  1234.     mvi    a,n2        ;reset tx retry counter
  1235.     sta    rtryct        ;    /
  1236.     lxi    h,lkstat    ;point to link status byte
  1237.     setb    3,m        ;set DCE busy
  1238.     res    7,m        ;clear DCE reject condition
  1239.     jmp    rxsc        ;and process supervisory cmd
  1240.  
  1241.     
  1242. ;    process received REJ command frame
  1243. ;    (internally called)
  1244. ;    on entry:    <hl>=bcb address
  1245. ;            <b>=control byte
  1246. ;            <c>=rx buffer #
  1247.  
  1248. rxcrej:    call    ackdge        ;acknowledge pending frames
  1249.     jc    badnr        ;exit if invalid N(r)
  1250. ;
  1251.     call    getbuf        ;another byte in buffer?
  1252.     jnc    cfmterr        ;yes, format errer
  1253. ;
  1254.     lxi    h,lkstat    ;point to link status byte
  1255.     res    3,m        ;clear DCE busy
  1256.     setb    7,m        ;set DCE reject condition flag
  1257.     mvi    a,n2        ;initialize retry counter
  1258.     sta    rtryct        ;    /
  1259.     mov    a,b        ;get control byte
  1260.     call    getnr        ;extract valid N(r)
  1261.     sta    vs        ;set V(s)=N(r) for retransmission
  1262.     sta    maxvs        ;and update max V(s) for acknowledge
  1263. ;
  1264. rxsc:                ;process supervisory cmd
  1265.     mov    a,c        ;release rx buffer
  1266.     call    rlsrxb        ;    /
  1267.     bit    4,b        ;P=1?
  1268.     rz            ;no, do nothing here
  1269. ;
  1270.     lxi    h,lkstat    ;point to link status word
  1271.     bit    4,m        ;DTE busy?
  1272.     jz    txrrr        ;no, transmit RR response
  1273.     jmp    txrnrr        ;yes, transmit RNR response
  1274.  
  1275.  
  1276. ;    handle invalid received N(r)
  1277. ;    on entry:    <c>=rx buffer #
  1278. badnr:    mov    a,c        ;get rx buffer #
  1279.     call    rlsrxb        ;release it
  1280.  
  1281. ;*** below message added for diagnostic
  1282.     call    ilprt
  1283.     db    'L2: bad received N(r)',cr,lf,0
  1284.  
  1285. ;    set up FRMR information fields
  1286.     lxi    h,cmdrf3    ;point to CMDR field 3
  1287.     res    0,m        ;reset bits W, X and Y
  1288.     res    1,m        ;    /
  1289.     res    2,m        ;      /
  1290.     setb    3,m        ;set bit Z for invalid N(r)
  1291.     jmp    txfrmr        ;and transmit FRMR
  1292.  
  1293.  
  1294.  
  1295.  
  1296. ;    handle received frame format error
  1297. ;    (I field in a non I frame)
  1298. ;    (internally called)
  1299. ;    on entry:    <hl>=bcb address
  1300. ;            <c>=buffer #
  1301.  
  1302. cfmterr:            ;error in command frame
  1303.     lxi    h,cmdrf2    ;point to CMDR field 2
  1304.     res    4,m        ;reset bit 4 for commands
  1305.     jmp    fmterr        ;and continue
  1306. ;
  1307. rfmterr:            ;error in response frame
  1308.     lxi    h,cmdrf2    ;point to CMDR field 2
  1309.     setb    4,m        ;set bit 4 for responses
  1310. fmterr:    mov    a,c        ;get rx buffer #
  1311.     call    rlsrxb        ;release buffer
  1312.     lxi    h,cmdrf3    ;point to CMDR field 3
  1313.     setb    0,m        ;set bit W
  1314.     setb    1,m        ;and bit X
  1315.     res    2,m        ;reset bit Y
  1316.     res    3,m        ;and bit Z
  1317.     jmp    txcmdr        ;and transmit CMDR
  1318.  
  1319.  
  1320.  
  1321. ;    process received I frame
  1322. ;    (internally called)
  1323. ;    on entry:    <hl>=bcb address
  1324. ;            <b>=control byte
  1325. ;            <c>=rx buffer #
  1326. ;    on exit:    flags, regs clobbered
  1327.  
  1328. rxi:    call    ackdge        ;acknowledge tx frame
  1329.     jc    badnr        ;exit if invalid N(r)
  1330. ;
  1331. rxi1:    push    h        ;save bcb address
  1332.     lxi    h,lkstat    ;point to link status
  1333.     res    7,m        ;clear DCE REJ condition
  1334.     pop    h        ;restore bcb address
  1335.     mov    a,b        ;get control byte
  1336.     ani    0000$1110b    ;extract N(s)
  1337.     rrc            ;move to bits 0-2
  1338.     mov    b,a        ;and save in <b>
  1339.     lda    vr        ;get V(r)
  1340.     cmp    b        ;is N(s)=V(r)?
  1341.     jz    rxi2        ;yes, keep going
  1342. ;
  1343. ;    process invalid received N(s)
  1344.     mov    a,c        ;else get rx buffer #
  1345.     call    rlsrxb        ;release buffer
  1346.     lxi    h,lkstat    ;point to link status
  1347.     setb    6,m        ;set REJ condition
  1348.     jmp    txrejr        ;and transmit REJ response
  1349. ;
  1350. ;    process valid N(s) (update receive window
  1351. ;    and hand over packet to level 3)
  1352. rxi2:    inr    a        ;V(r)=V(r)+1 mod 7
  1353.     ani    7        ;    /
  1354.     sta    vr        ;update V(r)
  1355.     push    h        ;save bcb address
  1356.     lxi    h,lkstat    ;point to link status
  1357.     res    6,m        ;clear DTE REJ condition
  1358.     pop    h        ;restore bcb address
  1359.     call    getbct        ;empty frame?
  1360.     jnz    rxi3        ;no, keep going
  1361. ;
  1362. ;    empty frame
  1363.     mov    a,c        ;release rx buffer
  1364.     call    rlsrxb        ;    /
  1365.     call    ilprt        ;and tell operator
  1366.     db    'L3: rx empty I frame',cr,lf,0
  1367.     ret
  1368. ;
  1369. ;    frame is not empty
  1370. rxi3:    lxi    h,rxplst    ;point to list of rx packets
  1371.     mov    a,c        ;get buffer #
  1372.     call    putbuf        ;hand over buffer
  1373.     lhld    rxifct        ;update rx I frame counter
  1374.     inx    h        ;    /
  1375.     shld    rxifct        ;      /
  1376.     ret
  1377.  
  1378.  
  1379.  
  1380. ;    process received N(r) to acknowledge tx I frames
  1381. ;    (internally called)
  1382. ;    on entry:    <b>=control byte with N(r)
  1383. ;            <c>=buffer #
  1384. ;    on exit:    carry set if invalid N(r)
  1385. ;            <a>, other flags clobbered
  1386. ;            all other regs unchanged
  1387.  
  1388. ackdge:    push    b        ;save regs
  1389.     push    d        ;    /
  1390.     push    h        ;      /
  1391.     mov    a,b        ;get control byte
  1392.     call    getnr        ;extract N(r)
  1393.     mov    d,a        ;save N(r) in <d>
  1394.     lda    lastnr        ;get last rx N(r)
  1395.     cmp    d        ;same as this one?
  1396.     jz    ackexi        ;yes, nothing new
  1397. ;
  1398. ;    calculate top of receive window
  1399.     lda    maxvs        ;max V(s)+1 mod (7)
  1400.     inr    a        ;(=top edge of window)
  1401.     inr    a        ;bump just past top
  1402.     ani    7        ;      /
  1403.     mov    e,a        ;     /
  1404.  
  1405. ;    check for valid N(r)
  1406.     mvi    b,kconst+1    ;<b>=k+1
  1407.     lda    lastnr        ;<a>=last valid N(r)
  1408. ack1:    cmp    d        ;<a>=N(r)?
  1409.     jz    ack2        ;yes, valid N(r)
  1410. ;
  1411.     inr    a        ;bump <a> mod 7
  1412.     ani    7        ;    /
  1413.     cmp    e        ;<a>=past top of window?
  1414.     jz    ackerr        ;yes, invalid N(r)
  1415. ;
  1416.     dcr    b        ;decrement window count
  1417.     jz    ackerr        ;error, below lower edge
  1418. ;
  1419.     jmp    ack1        ;else keep looping
  1420. ;
  1421. ;    valid N(r), acknowledge all tx frames up to N(r)-1
  1422. ack2:    call    t1off        ;stop timer T1
  1423.     lxi    h,txbtab    ;point to tx bcb address table
  1424. acklp:    lda    lastnr        ;get last valid N(r)
  1425.     cmp    d        ;is N(r)=last valid N(r)?
  1426.     jz    allack        ;yes, all acknowledged
  1427. ;
  1428. ;    acknowledge a new frame
  1429.     dcr    a        ;calculate last N(r)-1
  1430.     ani    7        ;mod 7
  1431.     call    bpoint        ;point to bcb address of last N(r)-1
  1432.     call    clrbuf        ;clear tx buffer for new use
  1433.     lda    lastnr        ;get last valid N(r)
  1434.     inr    a        ;bump last valid N(r)
  1435.     ani    7        ;    /
  1436.     sta    lastnr        ;      /
  1437.     mvi    a,n2        ;reset tx retry counter
  1438.     sta    rtryct        ;    /
  1439.     jmp    acklp        ;and keep looping
  1440. ;
  1441. ;    no more frames to acknowledge this time
  1442. allack:    lda    maxvs        ;is N(r)=max V(s)+1?
  1443.     inr    a        ;    /
  1444.     ani    7        ;      /
  1445.     cmp    d        ;     /
  1446.     cnz    t1on        ;no, some frames still outstanding
  1447.     stc            ;reset carry flag
  1448.     cmc            ;    /
  1449.     jmp    ackexi        ;and exit
  1450. ;
  1451. ;    signal invalid N(r)
  1452. ackerr:    stc            ;set carry flag
  1453. ;
  1454. ;    common exit routine
  1455. ackexi:    pop    h        ;restore regs
  1456.     pop    d        ;    /
  1457.     pop    b        ;      /
  1458.     ret
  1459.  
  1460.  
  1461. ;    extract N(r) from control byte
  1462. ;    (internally called)
  1463. ;    on entry:    <a>=control byte
  1464. ;    on exit:    <a>=N(r)
  1465.  
  1466. getnr:    ani    1110$0000b    ;extract N(r)
  1467.     rrc            ;move to bits 0-2
  1468.     rrc            ;    /
  1469.     rrc            ;      /
  1470.     rrc            ;     /
  1471.     rrc            ;    /
  1472.     ret    
  1473.  
  1474.  
  1475. ;    process incoming response frame
  1476. ;    (internally called)
  1477. ;    on entry:    <hl>=bcb address
  1478. ;            <c>=rx buffer #
  1479. ;            <d>=address byte
  1480. ;    on exit:    <b>=control byte
  1481. ;            <c>,<d>,<hl> unchanged
  1482.  
  1483. inresp:
  1484.     call    getbuf        ;get control byte
  1485.     jnc    inrsp1        ;if there is one
  1486. ;
  1487.     mov    a,c        ;else release rx buffer
  1488.     call    rlsrxb        ;    /
  1489.     lhld    rxbrct        ;incr bad response frame count
  1490.     inx    h        ;    /
  1491.     shld    rxbrct        ;      /
  1492.     ret
  1493. ;
  1494. inrsp1:    mov    b,a        ;save control byte
  1495.     sta    cmdrf1        ;save it in case of FRMR
  1496.     push    h        ;save <hl>
  1497.     lhld    rxrfct        ;increment response count
  1498.     inx    h        ;    /
  1499.     shld    rxrfct        ;      /
  1500.     call    logrx        ;log received frame
  1501.     pop    h        ;restore <hl>
  1502.     mov    a,b        ;get control byte
  1503.     ani    1110$1111b    ;extract all bits except f
  1504.  
  1505. ;    now branch to known frame id's
  1506.     cpi    dmfid        ;DM frame?
  1507.     jz    rxdm        ;yes, process it
  1508. ;
  1509.     cpi    uafid        ;UA frame?
  1510.     jz    rxua        ;yes, process it
  1511. ;
  1512.     cpi    cmdrfid        ;CMDR/FRMR frame?
  1513.     jz    rxcmdr        ;yes, process it
  1514. ;
  1515. ;    branch to numbered frames
  1516.     ani    0000$1111b    ;discard N(r) sequence bits
  1517.     cpi    rrfid        ;RR response frame?
  1518.     jz    rxrrr        ;yes, process it
  1519. ;
  1520.     cpi    rnrfid        ;RNR response frame?
  1521.     jz    rxrrnr        ;yes, process it
  1522. ;
  1523.     cpi    rejfid        ;REJ response frame?
  1524.     jz    rxrrej        ;yes, process it
  1525. ;
  1526. ;    unknown frame id
  1527. badrsp:    mov    a,c        ;else get rx buffer #
  1528.     call    rlsrxb        ;and release buffer
  1529.     lhld    rxbrct        ;increment bad response counter
  1530.     inx    h        ;    /
  1531.     shld    rxbrct        ;      /
  1532.     lxi    h,cmdrf2    ;set FRMR bit 13
  1533.     setb    4,m        ;    /
  1534.     lxi    h,cmdrf3    ;and FRMR bit W
  1535.     setb    0,m        ;    /
  1536.     res    1,m        ;reset FRMR bits X,Y,Z
  1537.     res    2,m        ;    /
  1538.     res    3,m        ;      /
  1539.     jmp    txfrmr        ;and transmit FRMR
  1540.  
  1541.  
  1542. ;    process received RR response frame
  1543. ;    (internally called)
  1544. ;    on entry:    <hl>=bcb address
  1545. ;            <b>=control byte
  1546. ;            <c>=rx buffer #
  1547.  
  1548. rxrrr:    call    ackdge        ;acknowledge pending frames
  1549.     jc    badnr        ;process invalid N(r)
  1550. ;
  1551.     call    getbuf        ;another byte in buffer?
  1552.     jnc    rfmterr        ;yes, format errer
  1553. ;
  1554.     lxi    h,lkstat    ;point to link status byte
  1555.     res    3,m        ;clear DCE busy
  1556.     res    7,m        ;clear DCE reject condition
  1557.     lxi    h,l2stat    ;point to level 2 status
  1558.     bit    0,m        ;link query in process?
  1559.     jz    rxsr        ;no, do common stuff
  1560. ;    
  1561. ;    link query is in process
  1562.     bit    4,b        ;is response F=1?
  1563.     jz    rxsr        ;no, do common stuff
  1564. ;
  1565. ;    process reply to query
  1566.     res    0,m        ;reset link query flag
  1567.     call    t1off        ;turn off response timer
  1568.     call    ilprt
  1569.     db    'L2: dce ready',cr,lf,0
  1570.     jmp    rxsr        ;and do common stuff
  1571.  
  1572.  
  1573.     
  1574. ;    process received RNR response frame
  1575. ;    (internally called)
  1576. ;    on entry:    <hl>=bcb address
  1577. ;            <b>=control byte
  1578. ;            <c>=rx buffer #
  1579.  
  1580. rxrrnr:    call    ackdge        ;acknowledge pending frames
  1581.     jc    badnr        ;process invalid N(r)
  1582. ;
  1583.     call    getbuf        ;another byte in buffer?
  1584.     jnc    rfmterr        ;yes, format errer
  1585. ;
  1586.     mvi    a,n2        ;reset tx retry counter
  1587.     sta    rtryct        ;    /
  1588.     lxi    h,lkstat    ;point to link status byte
  1589.     setb    3,m        ;set DCE busy
  1590.     res    7,m        ;clear DCE reject condition
  1591.     lxi    h,l2stat    ;point to level 2 status
  1592.     bit    0,m        ;link query in process?
  1593.     jz    rxsr        ;no, do common stuff
  1594. ;    
  1595. ;    link query is in process
  1596.     bit    4,b        ;is response F=1?
  1597.     jz    rxsr        ;no, do common stuff
  1598. ;
  1599. ;    process reply to query
  1600.     res    0,m        ;reset link query flag
  1601.     call    t1off        ;turn off response timer
  1602.     call    ilprt
  1603.     db    'L2: dce busy',cr,lf,0
  1604.     jmp    rxsr        ;and do common stuff
  1605.  
  1606.  
  1607.     
  1608. ;    process received REJ response frame
  1609. ;    (internally called)
  1610. ;    on entry:    <hl>=bcb address
  1611. ;            <b>=control byte
  1612. ;            <c>=rx buffer #
  1613.  
  1614. rxrrej:    call    ackdge        ;acknowledge pending frames
  1615.     jc    badnr        ;process invalid N(r)
  1616. ;
  1617.     call    getbuf        ;another byte in buffer?
  1618.     jnc    rfmterr        ;yes, format errer
  1619. ;
  1620.     lxi    h,lkstat    ;point to link status byte
  1621.     res    3,m        ;clear DCE busy
  1622.     setb    7,m        ;set DCE reject condition flag
  1623.     mvi    a,n2        ;initialize retry counter
  1624.     sta    rtryct        ;    /
  1625.     mov    a,b        ;get control byte
  1626.     call    getnr        ;extract valid N(r)
  1627.     sta    vs        ;set V(s)=N(r) for retransmission
  1628.     sta    maxvs        ;and update max V(s) for acknowledge
  1629.     lxi    h,l2stat    ;point to level 2 status
  1630.     bit    0,m        ;link query in process?
  1631.     jz    rxsr        ;no, do common stuff
  1632. ;    
  1633. ;    link query is in process
  1634.     bit    4,b        ;is response F=1?
  1635.     jz    rxsr        ;no, do common stuff
  1636. ;
  1637. ;    process reply to query
  1638.     res    0,m        ;reset link query flag
  1639.     call    t1off        ;turn off response timer
  1640.     call    ilprt
  1641.     db    'L2: dce in REJ condition',cr,lf,0
  1642.     jmp    rxsr        ;and do common stuff
  1643.  
  1644. ;    
  1645. ;    common stuff for supervisory response frames
  1646. rxsr:
  1647.     mov    a,c        ;release rx buffer
  1648.     call    rlsrxb        ;    /
  1649.     lxi    h,l2stat    ;point to level 2 status flags
  1650.     bit    7,m        ;timer recovery condition?
  1651.     rz            ;no, exit
  1652. ;
  1653. ;    process timer recovery condition
  1654.     bit    4,b        ;is F=1?
  1655.     rz            ;no, exit
  1656. ;
  1657.     res    7,m        ;else clear timer recovery condition
  1658.     ret
  1659.     
  1660.  
  1661. ;    process received DM response frame
  1662. ;    (internally called)
  1663. ;    on entry:    <hl>=bcb address
  1664. ;            <b>=control byte
  1665. ;            <c>=rx buffer #
  1666.     
  1667. rxdm:    call    getbuf        ;get next byte
  1668.     jnc    rfmterr        ;process invalid format
  1669. ;
  1670.     mov    a,c        ;get rx buffer #
  1671.     call    rlsrxb        ;release buffer
  1672.     lxi    h,lkstat    ;link connect in process?
  1673.     bit    0,m        ;    /
  1674.     jz    rxdm1        ;no, keep going
  1675. ;
  1676.     call    ilprt        ;yes, tell operator
  1677.     db    'L2: rx DM - dce unable to connect',cr,lf,0
  1678.     ret
  1679. ;
  1680. rxdm1:    setb    0,m        ;set link conn in process
  1681.     res    2,m        ;clear link connected
  1682.     jmp    txsabm        ;and transmit SABM
  1683.  
  1684.  
  1685. ;    process received UA response frame
  1686. ;    (internally called)
  1687. ;    on entry:    <hl>=bcb address
  1688. ;            <b>=control byte
  1689. ;            <c>=rx buffer #
  1690.  
  1691. rxua:    call    getbuf        ;get next byte
  1692.     jnc    rfmterr        ;process invalid format
  1693. ;
  1694.     mov    a,c        ;release rx buffer
  1695.     call    rlsrxb        ;    /
  1696.     lxi    h,lkstat    ;point to link status word
  1697.     res    3,m        ;clear DCE busy
  1698.     bit    0,m        ;connect in process?
  1699.     jz    rxua1        ;no, keep going
  1700. ;
  1701.     res    0,m        ;else clear connect in process
  1702.     setb    2,m        ;and set connect flag
  1703.     call    ilprt        ;and tell operator
  1704.     db    'L2: rx UA - link connected',cr,lf,0
  1705.     call    t1off        ;turn off timer T1
  1706.     call    txstar        ;transmit level 3 restart packet
  1707.     ret
  1708. ;
  1709. rxua1:    bit    1,m        ;disconnect in process?
  1710.     rz            ;no, do nothing
  1711. ;
  1712.     res    1,m        ;else clear disc in process
  1713.     res    2,m        ;and clear connect flag
  1714.     call    ilprt        ;and tell operator
  1715.     db    'L2: rx UA - link disconnected',cr,lf,0
  1716.     call    t1off        ;turn off timer T1
  1717.     ret
  1718.  
  1719.  
  1720. ;    process received CMDR/FRMR response frame
  1721. ;    (internally called)
  1722. ;    on entry:    <hl>=bcb address
  1723. ;            <c>=rx buffer #
  1724.  
  1725. rxcmdr:    call    ilprt        ;display error msg
  1726.     db    cr,lf,'L2: rx CMDR/FRMR - frame rejected: ',cr,lf,0
  1727.     call    getbuf        ;get next byte
  1728.     jc    rcmdr3        ;error if not there
  1729. ;
  1730.     mov    b,a        ;save byte in <b>
  1731.     call    ilprt        ;print first I field
  1732.     db    tab,'rejected frame id = ',0
  1733.     mov    a,b        ;get back byte
  1734.     call    phex        ;else display first byte in hex
  1735.     call    ilprt        ;and terminate line
  1736.     db    cr,lf,0        ;    /
  1737. ;
  1738.     call    getbuf        ;get second error byte
  1739.     jc    rcmdr3        ;error if not there
  1740. ;
  1741.     mov    b,a        ;save byte in <b>
  1742.     call    ilprt        ;display second field parameters
  1743.     db    tab,'rej frame type    = ',0
  1744.     bit    4,b        ;command frame?
  1745.     jz    rcmdr1        ;yes, say so
  1746. ;
  1747.     call    ilprt        ;else was response
  1748.     db    'response',cr,lf,0
  1749.     jmp    rcmdr2
  1750. ;
  1751. rcmdr1:    call    ilprt        ;command frame
  1752.     db    'command',cr,lf,0
  1753. ;
  1754. rcmdr2:    call    ilprt        ;display other field paramters
  1755.     db    tab,'         dce V(s) = ',0
  1756.     push    h        ;save <hl>
  1757.     mov    a,b        ;get back byte
  1758.     ani    0000$1110b    ;extract V(s)
  1759.     rrc            ;    /
  1760.     mvi    h,0        ;print V(s)
  1761.     mov    l,a        ;    /
  1762.     call    pdec        ;      /
  1763.     call    ilprt        ;terminate line
  1764.     db    cr,lf
  1765.     db    tab,'         dce V(r) = ',0
  1766.     mov    a,b        ;get back byte
  1767.     call    getnr        ;extract V(r)
  1768.     mov    l,a        ;and print it
  1769.     call    pdec        ;    /
  1770.     call    ilprt        ;teminate line
  1771.     db    cr,lf,0
  1772.     pop    h        ;restore <hl>
  1773. ;
  1774.     call    getbuf        ;get last byte
  1775.     jc    rcmdr3        ;error if not there
  1776. ;
  1777.     mov    b,a        ;save byte in <b>
  1778.     call    ilprt        ;else print last field
  1779.     db    tab,'error bits ----zyxw=',0
  1780.     mov    a,b        ;get back byte
  1781.     call    pbin        ;in binary
  1782.     call    ilprt        ;and terminate line
  1783.     db    cr,lf,0        ;    /
  1784. ;
  1785.     call    getbuf        ;try for one more
  1786.     jc    rcmdr4        ;ok if not there
  1787. ;
  1788. rcmdr3:    call    ilprt
  1789.     db    'L2: format error in rx CMDR/FRMR frame',cr,lf,0
  1790. ;
  1791. rcmdr4:    mov    a,c        ;else release rx buffer
  1792.     call    rlsrxb        ;    /
  1793. ;    lxi    h,l2stat    ;point to flow status
  1794.     setb    2,m        ;set DCE FRMR condition
  1795.     jmp    conlk        ;and reconnect link
  1796.  
  1797.  
  1798.     
  1799. ;    *****************
  1800. ;    *   data area    *
  1801. ;    *****************
  1802.  
  1803.     dseg
  1804.  
  1805. ;    HDLC frame variables and sequence numbers
  1806.  
  1807. vr    db    0    ;V(r)=receive state variable (0-7)
  1808. vs    db    0    ;V(s)=send state variable (0-7)
  1809. lastnr    db    7    ;last valid received N(r) (0-7)
  1810. lastvr    db    0    ;last transmitted V(r)
  1811. lastvs    db    7    ;last transmitted V(s)
  1812. maxvs    db    0    ;max V(s) transmitted
  1813. pfbit    db    0    ;poll/final bit (in pos 4)
  1814. rxcaddr    db    0    ;address of received commands
  1815. rxraddr    db    0    ;address of received responses
  1816. txcaddr    db    0    ;address of transmitted commands
  1817. txraddr    db    0    ;address of transmitted responses
  1818.  
  1819. ;    outgoing CMDR information field template
  1820. ;    (table 4/X.25)
  1821.  
  1822. cmdrf1    db    0    ;rejected command control field
  1823. cmdrf2    db    0    ;sequence variables & addr indicator
  1824. cmdrf3    db    0    ;error indicator bits
  1825.  
  1826. ;    level 2 status indicators & local variables
  1827.  
  1828. lkstat    db    0    ;level 2 link status flags
  1829. l2stat    db    0    ;level 2 status flags
  1830. dtemod    db    true    ;0=DCE mode/0ffh=DTE mode
  1831. badadd    db    0    ;storage for bad address
  1832. ackcnt    db    kack    ;acknowledgement delay counter
  1833.  
  1834. ;    level 2 diagnostic counters
  1835.  
  1836. rtryct:    db    n2    ;tx retry counter
  1837. rbafct:    dw    0000h    ;bad rx address frames
  1838. rxbrct:    dw    0000h    ;bad rx response frames
  1839. rxbcct:    dw    0000h    ;bad rx command frames
  1840. rxcfct:    dw    0000h    ;rx command frames
  1841. rxrfct:    dw    0000h    ;rx response frames
  1842. rxifct:    dw    0000h    ;rx I frames
  1843. txifct:    dw    0000h    ;tx I frames
  1844. txfct:    dw    0000h    ;tx frames
  1845. txirct:    dw    0000h    ;tx I retransmission count
  1846.  
  1847.