home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / MODEMS / MODEM / X25.ARK / LEVEL3.ASM next >
Assembly Source File  |  1986-07-28  |  55KB  |  2,218 lines

  1. title 'LEVEL3.ASM'
  2. ;************************************************
  3. ;*                        *
  4. ;*        LEVEL3.ASM            *
  5. ;*                        *
  6. ;*  X.25 level 3 (packet) protocol handler    *
  7. ;*  (implements single logical channel DTE      *
  8. ;*   for use in a Virtual Call circuit (VC)    *
  9. ;*   or Permanent Virtual Circuit (PVC))    *
  10. ;*                        *
  11. ;*  rev 1.30    08/21/84    E. Elizondo    *
  12. ;*                        *
  13. ;*  (c) 1984 E. Elizondo - all rights reserved. *
  14. ;*                        *
  15. ;*    This program may be used freely for non-  *
  16. ;*  commercial applications. It may not be sold *
  17. ;*  or used for commercial applications without *
  18. ;*  written permission of the author.           *
  19. ;*                         *
  20. ;************************************************
  21. ;    
  22.     maclib    Z80    ;DR Z80 macro library
  23.  
  24. ;    assembly time options
  25. false    equ    0
  26. true    equ    not false
  27. debug    equ    false        ;display P(s) value
  28.  
  29. ;    design parameters
  30.     
  31. n3    equ    2    ;retry count for level 3 timeout
  32. kpack    equ    4    ;acknowledgement delay count
  33.  
  34. ;    X.25 standard parameters:
  35.  
  36. ;    logical group & channel number (para 2.4.1)
  37. lchan    equ    1        ;logical channel 1
  38. lgroup    equ    0        ;logical group 0
  39.  
  40. ;    flow control parameters:
  41. wsize    equ    2        ;window size (para 4.4.1.2)
  42.  
  43. ;    packet type identifiers (table 8/X.25)
  44. ;    bit #   8765$4321
  45. calrid:    equ    0000$1011b    ;call request
  46. calaid:    equ    0000$1111b    ;call accepted
  47. clrrid:    equ    0001$0011b    ;clear request
  48. clrcid:    equ    0001$0111b    ;clear confirmation
  49. intid:    equ    0010$0011b    ;interrupt
  50. intcid:    equ    0010$0111b    ;interrupt confirmation
  51. rrid:    equ    0000$0001b    ;RR
  52. rnrid:    equ    0000$0101b    ;RNR
  53. rstrid:    equ    0001$1011b    ;reset request
  54. rstcid:    equ    0001$1111b    ;reset confirmation
  55. starid:    equ    1111$1011b    ;restart request
  56. stacid:    equ    1111$1111b    ;restart confirmation
  57. diagid:    equ    1111$0001b    ;diagnostic
  58.  
  59. ;    misc constants
  60. cr    equ    0dh        ;carriage ret
  61. lf    equ    0ah        ;line feed
  62.  
  63. ;    hooks for main program
  64. ;    subroutines
  65.  
  66.     public    initl3        ;initialize level 3 parameters
  67.     public    txdpk        ;transmit data packet if avail
  68.     public    rxpk        ;receive packet if available
  69.     public    txintp        ;transmit interrupt packet
  70.     public    txstar        ;transmit restart packet
  71.     public    txclrr        ;transmit clear request packet
  72.  
  73. ;    addresses
  74.     public    chstat        ;level 3 logical channel state
  75.     public    l3stat        ;level 3 flow control flags
  76.  
  77. ;    level 3 parameters
  78.     public    ps        ;P(s)
  79.     public    pr        ;P(r)
  80.     public    lastpr        ;last rx P(r)
  81.     public    ltxpr        ;last tx P(r)
  82.     public    lrxps        ;last rx P(s)
  83.     public    ltxps        ;last tx P(s)
  84.     public    pvcmod        ;PVC mode flag
  85.     public    laddr        ;local DTE address
  86.     public    raddr        ;remote DTE address
  87.     public    caddr        ;rx calling DTE address 
  88.     public    laddrl        ;local DTE address length
  89.     public    raddrl        ;remote DTE address length
  90.     public    caddrl        ;rx calling DTE address length
  91.     public    qbit        ;Q bit
  92.     public    dbit        ;D bit
  93.     public    chan        ;logical channel #
  94.     public    group        ;logical group #
  95.  
  96. ;    diagnostic counters
  97.     public    txpct        ;total tx packets
  98.     public    txfpct        ;total tx file data packets
  99.     public    txcpct        ;total tx console data packets
  100.     public    ntxbct        ;errors due to no free tx buffer
  101. ;
  102.     public    rxpct        ;total rx packets
  103.     public    rxdpct        ;total rx data packets
  104.     public    rbfpct        ;total rx bad format packets
  105.     public    rbcpct        ;total rx bad channel packets
  106.     public    rbapct        ;total rx bad address packets
  107.     public    rbipct        ;total rx bad id packets
  108.     public    rbgpct        ;total rx bad group packets
  109.     public    rxxpct        ;total discarded rx packets
  110.  
  111.  
  112. ;    definition of channel status (chstat) bits
  113. ;    (note that state r1 (packet level ready)
  114. ;     corresponds to level 2 link conn)
  115. ;    bit    set condition
  116. ;    0    flow control ready state (d1)
  117. ;    1    DTE restart request state (r2)
  118. ;    2    DTE waiting state (p2)
  119. ;    3    DTE reset request state (d2)
  120. ;    4    DTE clear request state (p6)
  121. ;    5    ready (p1)
  122. ;    6    undefined
  123. ;    7    undefined
  124.  
  125. ;    definition of flow control (l3stat) status bits
  126. ;    bit    set condition
  127. ;    0    DTE busy
  128. ;    1    DCE busy
  129. ;    2    DTE interrupt pending confirmation
  130. ;    3    undefined
  131. ;    4    undefined
  132. ;    5    ualled DTE address error semaphore (internal)
  133. ;    6    transmission completed - ready to clear
  134. ;    7    outgoing message waiting for call setup
  135.  
  136.  
  137. ;    external subroutines
  138.  
  139. ;    from buffers module:
  140.     extrn    inibuf        ;initialize all buffers
  141.     extrn    putbuf        ;put char in buffer
  142.     extrn    getbuf        ;get char from buffer
  143.     extrn    topbuf        ;put char at beginning of buffer
  144.     extrn    bpoint        ;point to selected bcb
  145.     extrn    rlsrxb        ;release rx buffer
  146.     extrn    clrbuf        ;clear buffer for new use
  147.     extrn    getbct        ;get buffer count
  148.     extrn    getrdy        ;get state of buffer ready flag
  149.     extrn    setrdy        ;set buffer ready flag
  150.     extrn    clrrdy        ;clear ready flag
  151.  
  152. ;    from level1 module:
  153.     extrn    t20on        ;turn on timer T20
  154.     extrn    t20off        ;turn off timer T20
  155.     extrn    t21on        ;turn on timer T21
  156.     extrn    t21off        ;turn off timer T21
  157.     extrn    t22on        ;turn on timer T22
  158.     extrn    t22off        ;turn off timer T22
  159.     extrn    t23on        ;turn on timer T23
  160.     extrn    t23off        ;turn off timer T23
  161.  
  162.  
  163. ;    from level2 module:
  164.     extrn    gettxb        ;get address of free tx bcb
  165.  
  166. ;    from files module
  167.     extrn    gfdata        ;get byte from transmit file
  168.     extrn    pfdata        ;write file to receive file
  169.     extrn    ctxfil        ;close transmit file
  170.     extrn    crxfil        ;close receive file
  171.  
  172. ;    from xutil module:
  173.     extrn    ilprt        ;in line print routine
  174.     extrn    ctype        ;print char in <a>
  175.     extrn    pdec        ;print <hl> in decimal
  176.     extrn    phex        ;print <a> in hex
  177.     extrn    phex1        ;print nibble in <a> in hex
  178.     extrn    delay        ;wait a bit
  179.  
  180. ;    external addresses
  181.     
  182. ;    from level 1 module
  183.     extrn    tistat        ;timer status flags
  184.     extrn    rxstat        ;receive status
  185.  
  186. ;    from level 2 module
  187.     extrn    lkstat        ;level 2 status flags
  188.  
  189. ;    from buffers module
  190.     extrn    rxplst    ;A(list of rx packt buffer #'s)
  191.     extrn    rxbtab    ;A(table of rx bcb pointers)
  192.     extrn    txbtab    ;A(table of tx bcb pointers)
  193.     extrn    ctbcb    ;A(bcb for console transmit)
  194.     extrn    crbcb    ;A(bcb for console receive)
  195.  
  196. ;    from files module
  197.     extrn    fstat        ;file status flags
  198.  
  199. ;    from x25 module
  200.     extrn    l4stat        ;level 4 status flags
  201.  
  202.     cseg        ;code section
  203.  
  204.  
  205. ;    **************************
  206. ;    * initialization section *
  207. ;    **************************
  208.  
  209.  
  210. ;    initialize level 3 parameters
  211. ;    (externally and internally called)
  212. ;    on entry:    no parameters
  213. ;    on exit:    all regs, flags clobbered
  214.  
  215. initl3:
  216.     mvi    a,lchan        ;get default channel number
  217.     sta    chan        ;and initialize logical channel #
  218.     mvi    a,lgroup    ;get default group number
  219.     sta    group        ;and initialize logical group #
  220.     mvi    a,0000$0001b    ;get modulo 8 general format id
  221.     sta    gfi        ;initialize gfi
  222.     call    reset        ;reset flow control variables
  223.     xra    a
  224.     sta    qbit        ;clear Q bit
  225.     sta    dbit        ;clear D bit
  226.     sta    chstat        ;clear logical channel state
  227.     sta    l3stat        ;channel in ready (p1) state
  228.     ret
  229.  
  230.  
  231.  
  232. ;    reset flow control variables
  233. ;    (internally called)
  234. ;    on entry:    no parameters
  235. ;    on exit:    <a>,flags clobbered
  236. ;            all other regs unchanged
  237. reset:    xra    a
  238.     sta    pr        ;clear P(r)
  239.     sta    ps        ;clear P(s)
  240.     sta    lastpr        ;clear last rx P(r)
  241.     sta    ltxpr        ;and last tx P(r)
  242.     mvi    a,7        ;initialize last rx P(s)
  243.     sta    lrxps        ;    /
  244.     sta    ltxps        ;and last tx P(s)
  245.     ret
  246.  
  247.  
  248.  
  249.      ****************************
  250. ;    *  packet transmit section *
  251. ;    ****************************
  252.  
  253. ;    check and process timeout condition or
  254. ;    transmit data packet if available and
  255. ;        a) Level 3 timers not timed out
  256. ;        b) level 2 link is connected
  257. ;        c) level 3 in data transfer ready state
  258. ;        d) DCE not busy
  259. ;        e) new frame P(s) is within window
  260. ;        f) free tx buffer available
  261. ;    and either    g) transmit file is open
  262. ;    or        h) console transmit buffer is ready
  263. ;        (file data takes precedence, as it's
  264. ;         transmitted as a continuous sequence)
  265. ;    if no I is available, transmit RR or RNR if any
  266. ;    received I packets need acknowledgement
  267. ;    (externally called)
  268. ;    on entry:    no parameters
  269. ;    on exit:    all regs, flags clobbered
  270. ;
  271.  
  272. txdpk:
  273.     lxi    h,tistat    ;point to timer status flags
  274.     bit    1,m        ;timer T20 timed out?
  275.     jnz    t20to        ;yes, service it
  276. ;
  277.     bit    2,m        ;timer T21 timed out?
  278.     jnz    t21to        ;yes, service it
  279. ;
  280.     bit    3,m        ;timer T22 timed out?
  281.     jnz    t22to        ;yes, service it
  282. ;
  283.     bit    4,m        ;timer T23 timed out?
  284.     jnz    t23to        ;yes, service it
  285. ;
  286.     lxi    h,lkstat    ;point to level 2 status
  287.     bit    2,m        ;link connected?
  288.     rz            ;no, return
  289. ;
  290.     lxi    h,chstat    ;point back to channel status
  291.     bit    5,m        ;ready state (p1)?
  292.     jnz    setup        ;yes, see if we want to call
  293. ;
  294.     bit    0,m        ;flow control ready state (d1)?
  295.     rz            ;no, return
  296. ;
  297.     lxi    h,l3stat    ;point to level 3 status
  298.     bit    1,m        ;DCE busy?
  299.     rnz            ;yes, return
  300. ;
  301.     bit    6,m        ;message complete?
  302.     jnz    clear        ;yes, see if we want to clear
  303. ;
  304. ;
  305. ;    did we transmit data packet already?
  306.     lda    ltxps        ;get last tx P(s)
  307.     mov    b,a        ;save in <b>
  308.     lda    ps        ;get current ps
  309.     cmp    b        ;same?
  310.     jz    txackp        ;yes, we did
  311. ;
  312. ;    check that P(s) is within window
  313.     lda    lastpr        ;get last rx P(r)
  314.     adi    wsize+1        ;calculate just past window
  315.     ani    7        ;..mod 7
  316.     mov    b,a        ;save in <b>
  317.     lda    ps        ;get P(s)
  318.     cmp    b        ;is P(s)=past top of window?
  319.     jz    txackp        ;yes, don't transmit it yet
  320. ;
  321. txdp0:    lxi    h,fstat        ;point to file status
  322.     bit    1,m        ;tx file open?
  323.     jz    txcdpk        ;no, see if console packet avail
  324. ;
  325. ;    transmit disk file data packet
  326. ;    (default to category A packet)
  327.     call    gettxb        ;else get free tx bcb
  328.     rc            ;return if none avail
  329. ;
  330.     xra    a        ;clear <a>
  331.     sta    qbit        ;clear Q bit
  332.     sta    dbit        ;clear D bit
  333.     call    octet1        ;assemble octet 1 in <a>
  334.     call    putbuf        ;put octet 1 in tx buffer
  335.     lda    chan        ;get logical channel #
  336.     call    putbuf        ;put octet 2 in tx buffer
  337.     call    octet3        ;assemble octet 3 in <a>
  338.     setb    4,a        ;set M=1 for now
  339.     call    putbuf        ;store octet 3 in tx buffer
  340.  
  341. ;    fill up user data field in packet
  342.     mvi    b,128        ;max user data octets in packet
  343. txdp1:    
  344.     call    gfdata        ;get data byte from file
  345.     jz    txdp2        ;exit if end of file
  346.     call    putbuf        ;else put in buffer
  347.     dcr    b        ;is packet full?
  348.     jnz    txdp1        ;no, keep going
  349. ;
  350.     jmp    txdp3        ;else exit
  351. ;
  352. ;    end of file - make into category B packet
  353. txdp2:
  354.     call    getbuf        ;get octet 1
  355.     rc            ;exit if not there
  356. ;
  357.     mov    b,a        ;save in <b>
  358.     call    getbuf        ;get octet 2
  359.     rc            ;exit if not there
  360. ;
  361.     mov    c,a        ;save in <c>
  362.     call    getbuf        ;get octet 3
  363.     rc            ;exit if not there
  364. ;
  365.     res    4,a        ;set M=0
  366.     call    topbuf        ;put back octet 3
  367.     mov    a,c        ;get octet 2
  368.     call    topbuf        ;and put it back
  369.     mov    a,b        ;get octet 1
  370.     setb    6,a        ;set D=1
  371.     call    topbuf        ;and put it back
  372.     call    ctxfil        ;close tx file
  373.  
  374. ;    common exit routine
  375. txdp3:
  376.     call    txgo        ;transmit packet
  377.     lda    ps        ;P(s)=P(s)+1 mod 7
  378. ;    
  379.     if    debug        ;if debug mode
  380.     call    prtps        ;print P(s)
  381.     endif
  382. ;
  383.     sta    ltxps        ;update last tx P(s)
  384.     inr    a        ;increment P(s)
  385.     ani    7        ;      /
  386.     sta    ps        ;update P(s)
  387.     lhld    txfpct        ;increment tx file packet count
  388.     inx    h        ;    /
  389.     shld    txfpct        ;      /
  390.     mvi    a,kpack        ;initiaize ack delay count
  391.     sta    packct        ;    /
  392.     call    delay        ;and wait a bit
  393.     ret
  394.  
  395.  
  396.  
  397. ;    transmit console data packet if available
  398. ;    (internally called)
  399. ;    on entry:    no parameters
  400. ;    on exit:    all regs, flags clobbered
  401. ;
  402. txcdpk:
  403.     lxi    h,ctbcb        ;point to console transmit bcb
  404.     call    getrdy        ;is it ready?
  405.     jz    txackp        ;no, see if we want to acknowledge
  406. ;
  407.     call    gettxb        ;else get free tx bcb
  408.     rc            ;return if none avail
  409. ;
  410. ;    this is a category B packet
  411.     push    h        ;save bcb address
  412.     lxi    h,qbit        ;point to Q bit
  413.     res    7,m        ;set Q=0
  414.     lxi    h,dbit        ;point to D bit
  415. ;***    setb    6,m        ;set D=1  (if desired)
  416.     pop    h        ;restore bcb address
  417.     call    octet1        ;assemble octet 1 in <a>
  418.     call    putbuf        ;put octet 1 in tx buffer
  419.     lda    chan        ;get logical channel #
  420.     call    putbuf        ;put octet 2 in tx buffer
  421.     call    octet3        ;build octet 3 in <a> with M=0
  422.     call    putbuf        ;store in tx buffer
  423.     mvi    b,128        ;max user data octets in packet
  424.  
  425. ;    fill user data fields from console tx buffer
  426.     xchg            ;save <hl> in <de>
  427.     lxi    h,ctbcb        ;point to console transmit bcb
  428. txcdp1:    
  429.     call    getbuf        ;get data byte from console buffer
  430.     jc    txcdp2        ;exit if end of buffer
  431.     xchg            ;restore tx buffer bcb address
  432.     call    putbuf        ;else put into tx buffer
  433.     xchg            ;point back to console xmit bcb
  434.     dcr    b        ;is packet full?
  435.     jnz    txcdp1        ;no, keep going
  436. ;
  437. ;    common exit routine
  438. txcdp2:
  439.     call    clrrdy        ;clear console xmit buffer flag
  440.     xchg            ;point back to tx buffer bcb
  441.     call    txgo        ;transmit packet
  442.     lda    ps        ;P(s)=P(s)+1 mod 7
  443. ;
  444.     if debug
  445.     call    prtps        ;print P(s)
  446.     endif
  447. ;
  448.     sta    ltxps        ;update last tx P(s)
  449.     inr    a        ;incrment P(s)
  450.     ani    7        ;      /
  451.     sta    ps        ;update P(s)
  452.     lxi    h,l4stat    ;point to level 4 status
  453.     setb    0,m        ;signal prompt for next packet
  454.     lhld    txcpct        ;increment tx console packet count
  455.     inx    h        ;    /
  456.     shld    txcpct        ;      /
  457.     lxi    h,l3stat    ;point to flow status
  458.     res    7,m        ;reset message waiting flag
  459.     mvi    a,kpack        ;initialize ack delay count
  460.     sta    packct        ;    /
  461.     ret
  462.  
  463.  
  464. ;    transmit acknowledgement (RR or RNR) packet 
  465. ;    (internally called)
  466. ;    on entry:    no parameters
  467. ;    on exit:    all flags, regs clobbered
  468. txackp:
  469.     lda    ltxpr        ;get last tx P(r)
  470.     mov    b,a        ;save in <b>
  471.     lda    pr        ;get current P(r)
  472.     cmp    b        ;same?
  473.     rz            ;yes, nothing to acknowledge
  474. ;
  475. ;    check delay count to see if any data packets are coming
  476.     lda    packct        ;get delay count
  477.     dcr    a        ;decrement it
  478.     sta    packct        ;    /
  479.     rnz            ;wait a bit till it's 0
  480. ;
  481. ;    delay completed, transmit acknowledge packet
  482.     mvi    a,kpack        ;initialize delay count
  483.     sta    packct        ;    /
  484.     lxi    h,l3stat    ;point to level 3 flow status
  485.     bit    0,m        ;DTE busy?
  486.     jnz    txrnr        ;yes, transmit RNR packet
  487. ;
  488.     jmp    txrr        ;else transmit RR packet
  489.  
  490.  
  491.  
  492. ;    print P(s)
  493. ;    (internally called)
  494. ;    on entry:    <a>=P(s)
  495. ;    on exit:    all flags, regs unchanged
  496.  
  497. prtps:    push    psw        ;save P(s)
  498.     mvi    a,'['
  499.     call    ctype
  500.     pop    psw        ;restore P(s)
  501.     push    psw        ;and save it again
  502.     adi    '0'        ;convert to ASCII
  503.     call    ctype        ;display it
  504.     mvi    a,']'
  505.     call    ctype
  506.     pop    psw        ;restore P(s)
  507.     ret
  508.  
  509.  
  510. ;    set up call if in VC mode
  511. ;    (internally called)
  512. ;    on entry:    no parameters
  513. ;    on exit:    all flags, regs clobbered
  514.  
  515. setup:
  516.     lxi    h,chstat    ;point to channel status
  517.     bit    2,m        ;DTE waiting state (p2)?
  518.     rnz            ;yes, do nothing
  519. ;
  520.     lxi    h,l3stat    ;point to flow status
  521.     bit    7,m        ;message ready?
  522.     rz            ;no, return
  523. ;
  524. ;    ready to set up call
  525.     res    7,m        ;reset message waiting flag
  526.     lxi    h,chstat    ;point back to channel status
  527.     bit    0,m        ;flow control ready state (d1)?
  528.     rnz            ;yes, no setup needed
  529. ;
  530.     jmp    txcr        ;else transmit call request packet
  531.  
  532.  
  533.  
  534. ;    clear call if in VC mode
  535. ;    (internally called)
  536.  
  537. clear:
  538.     lxi    h,l3stat    ;point to level 3 status
  539.     res    6,m        ;reset message complete flag
  540.     lda    pvcmod        ;get VC/PVC mode flag
  541.     cpi    2        ;PVC?
  542.     rz            ;yes, do nothing if PVC
  543. ;
  544.     jmp    txclrr        ;else transmit clear request packet
  545.  
  546.  
  547. ;    transmit call request packet
  548. ;    (internally called)
  549. ;    on entry:    no parameters
  550. ;    on exit:    all flags, regs clobbered
  551.  
  552. txcr:    
  553.     call    gettxb        ;get free tx bcb
  554.     jc    enotxb        ;error if none available
  555. ;
  556.     mvi    c,calrid    ;get call request id
  557.     call    put3oct        ;put octets 1-3 in tx buffer
  558.     call    putaddr        ;put address octets in tx buffer
  559.  
  560. ;***    (no facilities or call user data implemented)
  561.     mvi    a,0        ;facilities length=0
  562.     call    putbuf        ;put octet in tx buffer
  563.     call    txgo        ;transmit packet
  564.     call    reset        ;reset flow control variables
  565.     call    t21on        ;start timer T21
  566.     lxi    h,chstat    ;point to channel status
  567.     bit    0,m        ;flow control ready state?
  568.     rnz            ;yes, all done
  569. ;
  570.     setb    2,m        ;else signal DTE waiting state (p2)
  571.     ret
  572.  
  573.  
  574.  
  575. ;    transmit call accepted packet
  576. ;    (internally called)
  577. ;    on entry:    no parameters
  578. ;    on exit:    all flags, regs clobbered
  579.  
  580. txca:    
  581.     call    gettxb        ;get free tx bcb
  582.     jc    enotxb        ;error if none available
  583. ;
  584.     mvi    c,calaid    ;get call accepted id
  585.     call    put3oct        ;put octets 1-3 in tx buffer
  586.     call    putaddr        ;put address octets in tx buffer
  587. ;***    (no facilities implemented)
  588.     call    txgo        ;transmit packet
  589.     ret
  590.  
  591.  
  592.  
  593. ;    transmit clear request packet
  594. ;    (internally called)
  595. ;    on entry:    no parameters
  596. ;    on exit:    all flags, regs clobbered
  597.  
  598. txclrr:
  599.     call    gettxb        ;get free tx bcb
  600.     jc    enotxb        ;error if none available
  601. ;
  602.     mvi    c,clrrid    ;get clear request id
  603.     call    put3oct        ;put octets 1-3 in tx buffer
  604.     mvi    a,0        ;clearing cause=0 for DTE
  605.     call    putbuf        ;put octet 4 in tx buffer
  606.     call    txgo        ;transmit packet
  607.     call    reset        ;reset flow control variables
  608.     call    t23on        ;start timer T23
  609.     lxi    h,chstat    ;indicate DTE clear reqest state (P6)
  610.     setb    4,m
  611.     call    ctxfil        ;close transmit file
  612.     call    crxfil        ;and receive file
  613.     ret        
  614.  
  615.  
  616.  
  617. ;    transmit clear confirmation packet
  618. ;    (internally called)
  619. ;    on entry:    no parameters
  620. ;    on exit:    all flags, regs clobbered
  621.  
  622. txclrc:
  623.     call    gettxb        ;get free tx bcb
  624.     jc    enotxb        ;error if none available
  625. ;
  626.     mvi    c,clrcid    ;get clear confirmation id
  627.     call    put3oct        ;put octets 1-3 in tx buffer
  628.     call    txgo        ;transmit packet
  629.     ret        
  630.  
  631.  
  632.  
  633. ;    transmit interrupt packet
  634. ;    (externally called)
  635. ;    on entry:    <b>=interupt user data for octet 4
  636. ;    on exit:    all flags, regs clobbered
  637.  
  638. txintp:    lxi    h,lkstat    ;point to level 2 status
  639.     bit    2,m        ;link connected?
  640.     jnz    txint1        ;yes, keep going
  641. ;
  642.     call    ilprt        ;else tell operator
  643.     db    'L3: link not connected - ',0
  644.     jmp    txint5        ;and exit
  645. ;
  646. txint1:    lxi    h,chstat    ;point to channel status
  647.     bit    0,m        ;flow control ready state?
  648.     jnz    txint2        ;yes, keep going
  649. ;
  650.     call    ilprt        ;else tell operator
  651.     db    'L3: link not in data xfer state - ',0
  652.     jmp    txint5        ;and exit
  653.  
  654. txint2:    lxi    h,l3stat    ;point to level 3 flow status
  655.     bit    2,m        ;interrupt already pending
  656.     jz    txint3        ;no, keep going
  657. ;
  658.     call    ilprt        ;else tell operator
  659.     db    'L3: DTE interrupt is pending - ',0
  660. txint5:    call    ilprt
  661.     db    'cannot send interrupt',cr,lf,0
  662.     ret
  663.  
  664. txint3:    call    gettxb        ;get free tx bcb
  665.     jc    enotxb        ;error if none available
  666. ;
  667.     mvi    c,intid        ;get interrupt id
  668.     call    put3oct        ;put octets 1-3 in tx buffer
  669.     mov    a,b        ;get interrupt user data
  670.     call    putbuf        ;put octet 4 in tx buffer
  671.     call    txgo        ;transmit packet
  672.     lxi    h,l3stat    ;point to level 3 flow status
  673.     setb    2,m        ;set interrupt pending flag
  674.     ret        
  675.  
  676.  
  677.  
  678. ;    transmit interrupt confirmation packet
  679. ;    (internally called)
  680. ;    on entry:    no parameters
  681. ;    on exit:    all flags, regs clobbered
  682.  
  683. txintc:
  684.     call    gettxb        ;get free tx bcb
  685.     jc    enotxb        ;error if none available
  686. ;
  687.     mvi    c,intcid    ;get interrupt confirmation id 
  688.     call    put3oct        ;put octets 1- 3 in tx buffer
  689.     call    txgo        ;transmit packet
  690.     ret        
  691.  
  692.  
  693.  
  694. ;    transmit RR packet
  695. ;    (internally called)
  696. ;    on entry:    no parameters
  697. ;    on exit:    all flags, regs clobbered
  698.  
  699. txrr:
  700.     mvi    c,rrid        ;<c>=RR packet identifier
  701.     jmp    txrcom        ;and do common stuff
  702.  
  703.  
  704.  
  705. ;    transmit RNR packet
  706. ;    (internally called)
  707. ;    on entry:    no parameters
  708. ;    on exit:    all flags, regs clobbered
  709.  
  710. txrnr:
  711.     mvi    c,rnrid        ;<c>=RNR packet identifier
  712. ;
  713. ;    common stuff for RR and RNR
  714. ;    on entry:    <c>=packet identifier
  715. txrcom:    call    gettxb        ;get free tx bcb
  716.     jc    enotxb        ;error if none available
  717. ;
  718.     xra    a        ;clear Q and D bits
  719.     sta    qbit        ;    /
  720.     sta    dbit        ;      /
  721.     call    octet1        ;assemble octet 1 in <a>
  722.     call    putbuf        ;put octet 1 in tx buffer
  723.     lda    chan        ;get logical channel #
  724.     call    putbuf        ;put octet 2 in tx buffer
  725.     lda    pr        ;get P(r)
  726.     sta    ltxpr        ;update last tx P(r)
  727.     rlc            ;move to bits 8-6
  728.     rlc            ;    /
  729.     rlc            ;      /
  730.     rlc            ;     /
  731.     rlc            ;    /
  732.     ani    1110$0000b    ;zero other bits
  733.     ora    c        ;merge with P(r)
  734.     call    putbuf        ;put octet 3 in tx buffer
  735.     call    txgo        ;transmit packet
  736.     ret        
  737.  
  738.  
  739.  
  740. ;    transmit reset request packet
  741. ;    (internally called)
  742. ;    on entry:    no parameters
  743. ;    on exit:    all flags, regs clobbered
  744.  
  745. txrstr:    call    gettxb        ;get free tx bcb
  746.     jc    enotxb        ;error if none available
  747. ;
  748.     mvi    c,rstrid    ;get reset request id
  749.     call    put3oct        ;put octets 1-3 in tx buffer
  750.     mvi    a,0        ;resetting cause=0 for DTE
  751.     call    putbuf        ;put octet 4 in tx buffer
  752.     call    txgo        ;transmit packet
  753.     call    reset        ;reset flow control variables
  754.     call    t22on        ;start timer T22
  755.     lxi    h,chstat    ;point to channel status
  756.     setb    3,m        ;signal reset request state
  757.     ret        
  758.  
  759.  
  760.  
  761. ;    transmit reset confirmation packet
  762. ;    (internally called)
  763. ;    on entry:    no parameters
  764. ;    on exit:    all flags, regs clobbered
  765.  
  766. txrstc:    call    gettxb        ;get free tx bcb
  767.     jc    enotxb        ;error if none available
  768. ;
  769.     mvi    c,rstcid    ;get reset confirmation id
  770.     call    put3oct        ;put octets 1-3 in tx buffer
  771.     call    txgo        ;and transmit packet
  772.     ret
  773.  
  774.  
  775.  
  776. ;    transmit restart request packet
  777. ;    (internally & externally called)
  778. ;    on entry:    no parameters
  779. ;    on exit:    all flags, regs clobbered
  780.  
  781. txstar:    lxi    h,lkstat    ;point to level 2 status
  782.     bit    2,m        ;link connected?
  783.     jnz    txstar1        ;yes, keep going
  784. ;
  785.     call    ilprt        ;else tell operator
  786.     db    'L3: link not connected',cr,lf,0
  787.     ret
  788. ;
  789. txstar1:
  790.     call    gettxb        ;get free tx bcb
  791.     jc    enotxb        ;error if none available
  792. ;
  793.     mvi    c,starid    ;get restart request packet id
  794.     call    txscom        ;do common stuff
  795.     mvi    a,0        ;set restarting cause=0 for DTE
  796.     call    putbuf        ;    /
  797.     call    txgo        ;transmit packet
  798.     call    reset        ;reset flow control variables
  799.     lxi    h,chstat    ;point to channel status
  800.     setb    1,m        ;indicate restart request state
  801.     call    t20on        ;start timer T20
  802.     call    t21off        ;and stop all others
  803.     call    t22off        ;    /
  804.     call    t23off        ;      /
  805.     ret
  806.  
  807.  
  808. ;    transmit restart confirmation packet
  809. ;    (internally called)
  810. ;    on entry:    no parameters
  811. ;    on exit:    all flags, regs clobbered
  812.  
  813. txstac:    call    gettxb        ;get free tx bcb
  814.     jc    enotxb        ;error if none available
  815. ;
  816.     mvi    c,stacid    ;get restart confirmation id
  817.     call    txscom        ;do common stuff
  818.     call    txgo        ;transmit packet
  819.     ret
  820.  
  821. ;    common stuff for restart request/confirmation
  822. ;    on entry:    <c>=packet id
  823. txscom:    lda    gfi        ;get general format identifier
  824.     rlc            ;move to bits 8-5
  825.     rlc            ;    /
  826.     rlc            ;      /
  827.     rlc            ;     /
  828.     ani    1111$0000b    ;make sure lower bits are all 0
  829.     call    putbuf        ;put octet 1 in tx buffer
  830.     xra    a        ;next octet is all 0's
  831.     call    putbuf        ;put octet 2 in tx buffer
  832.     mov    a,c        ;get packet identifier
  833.     call    putbuf        ;put octet 3 in tx buffer
  834.     ret        
  835.  
  836.  
  837.  
  838. ;    error handling routine for no available free tx buffer
  839. ;    (internally called)
  840.  
  841. enotxb:
  842.     lhld    ntxbct        ;increment error count
  843.     inx    h        ;    /
  844.     shld    ntxbct        ;      /
  845.     ret
  846.  
  847.  
  848. ;    *****************************************
  849. ;    * utility routines for tx section    *
  850. ;    *****************************************
  851.  
  852. ;    transmit packet
  853. ;    (internally called)
  854. ;    on entry:    <hl>=address of tx buffer bcb
  855. ;    on exit:    all regs, flags clobbered
  856.  
  857. txgo:    call    setrdy        ;set tx buffer ready flag
  858.     lhld    txpct        ;increment total tx packet count
  859.     inx    h        ;    /
  860.     shld    txpct        ;      /
  861.     ret
  862.  
  863.  
  864. ;    put octets 1-3 in tx buffer
  865. ;    (internally called)
  866. ;    on entry:    <hl>=bcb address of tx buffer
  867. ;            <c>=packet identifier
  868. ;    on exit:    <a>,flags clobbered
  869. ;            all other regs unchanged
  870. put3oct:
  871.     xra    a        ;clear Q and D bits
  872.     sta    qbit        ;    /
  873.     sta    dbit        ;      /
  874.     call    octet1        ;assemble octet 1 in <a>
  875.     call    putbuf        ;put octet 1 in tx buffer
  876.     lda    chan        ;get logical channel #
  877.     call    putbuf        ;put octet 2 in tx buffer
  878.     mov    a,c        ;get packet identifier
  879.     call    putbuf        ;put octet 3 in tx buffer
  880.     ret        
  881.  
  882.  
  883. ;    build octet 1
  884. ;    (internally called)
  885. ;    on entry:    no parameters
  886. ;    on exit:    <a>=octet 1
  887. ;            flags clobbered
  888. ;            all other regs unchanged
  889.  
  890. octet1:    push    b        ;save <bc>
  891.     lda    gfi        ;get general format identifier
  892.     rlc            ;move to bits 8-5
  893.     rlc            ;    /
  894.     rlc            ;      /
  895.     rlc            ;     /
  896.     mov    b,a        ;save result in <b>
  897.     lda    qbit        ;get q bit
  898.     ora    b        ;merge with gfi
  899.     mov    b,a        ;and save result in <b>
  900.     lda    dbit        ;get d bit
  901.     ora    b        ;merge with gfi
  902.     ani    0f0h        ;make sure lower 4 bits are 0
  903.     mov    b,a        ;and save result in <b>
  904.     lda    group        ;get logical group #
  905.     ani    0fh        ;zero upper 4 bits
  906.     ora    b        ;merge with gfi
  907.     pop    b        ;restore <bc>
  908.     ret        
  909.  
  910.  
  911.  
  912. ;    build octet 3 of data packet
  913. ;    (internally called)
  914. ;    on entry:    no parameters
  915. ;    on exit:    <a>= octet 3
  916. ;            all other regs unchanged
  917.  
  918. octet3:
  919.     push    b        ;save <bc>
  920.     lda    pr        ;get P(r)
  921.     sta    ltxpr        ;update last tx P(r)
  922.     rlc            ;move to bits 8-6
  923.     rlc            ;    /
  924.     rlc            ;      /
  925.     rlc            ;     /
  926.     rlc            ;    /
  927.     ani    1110$0000b    ;zero other bits
  928.     mov    b,a        ;save result in <b>
  929.     lda    ps        ;get P(s)
  930.     rlc            ;move to bits 4-2
  931.     ani    0000$1110b    ;zero other bits
  932.     ora    b        ;merge with P(r) and M
  933.     pop    b        ;restore <bc>
  934.     ret
  935.  
  936.  
  937. ;    put address octets in tx buffer
  938. ;    (internally called)
  939. ;    on entry:    <hl>=tx bcb address
  940. ;    on exit:    <a>,flags clobbered
  941. ;            all other regs unchanged
  942.  
  943. putaddr:
  944.     push    b        ;save <bc>
  945.     push    d        ;save <de>
  946. ;
  947. ;    build octet 4 in tx buffer
  948.     lda    laddrl        ;get local address length
  949.     rlc            ;move to bits 8-5
  950.     rlc            ;    /
  951.     rlc            ;      /
  952.     rlc            ;     /
  953.     ani    1111$0000b    ;make sure lower 4 bits are 0
  954.     mov    b,a        ;save result in <b>
  955.     lda    raddrl        ;get remote address length
  956.     ani    0000$1111b    ;make sure upper 4 bits are 0
  957.     ora    b        ;merge with local address length
  958.     call    putbuf        ;put octet 4 in tx buffer
  959. ;
  960. ;    now build called DTE address, if present
  961.     lda    raddrl        ;get remote address length
  962.     ora    a        ;length=0?
  963.     jz    putad2        ;yes, skip remote address
  964. ;
  965.     mov    b,a        ;save length in <b>
  966.     lxi    d,raddr        ;point <de> to remote address
  967. putad1:    ldax    d        ;get first char
  968.     rlc            ;move to bits 8-5
  969.     rlc            ;    /
  970.     rlc            ;      /
  971.     rlc            ;     /
  972.     ani    1111$0000b    ;make sure lower bits are 0
  973.     mov    c,a        ;save result in <c>
  974.     inx    d        ;point to next address digit
  975.     dcr    b        ;last digit?
  976.     jz    putad3        ;yes, get local address
  977. ;
  978.     ldax    d        ;else get next char
  979.     ani    0000$1111b    ;make sure upper bits are 0
  980.     ora    c        ;merge with last digit
  981.     call    putbuf        ;and put in tx buffer
  982.     inx    d        ;point to next address digit
  983.     dcr    b        ;last digit
  984.     jnz    putad1        ;no, get another
  985. ;
  986. ;    
  987. ;    build calling DTE address, if present
  988. ;    entry point if called DTE address is even # of digits
  989. putad2:    lda    laddrl        ;get local address length
  990.     ora     a        ;length=0?
  991.     jz    putadexi    ;yes, exit
  992. ;
  993.     mov    b,a        ;else save length in <b>
  994.     lxi    d,laddr        ;point <de> to local address
  995.     jmp    putad4        ;and keep going
  996. ;
  997. ;    entry point if called DTE address is odd # of digits
  998. putad3:    lda    laddrl        ;get local address length
  999.     ora    a        ;length=0?
  1000.     jz    putadexi    ;yes, exit
  1001. ;
  1002.     mov    b,a        ;else save length in <b>
  1003.     lxi    d,laddr        ;point <de> to local address
  1004.     jmp    putad5        ;and keep going
  1005. ;
  1006. ;    build msb digit
  1007. putad4:    ldax    d        ;get first char
  1008.     rlc            ;move to bits 8-5
  1009.     rlc            ;    /
  1010.     rlc            ;      /
  1011.     rlc            ;     /
  1012.     ani    1111$0000b    ;make sure lower bits are 0
  1013.     mov    c,a        ;save result in <c>
  1014.     inx    d        ;point to next address digit
  1015.     dcr    b        ;last digit?
  1016.     jnz    putad5        ;no, get next character
  1017. ;
  1018.     call    putbuf        ;else put last octet in tx buffer
  1019.     jmp    putadexi    ;and exit
  1020. ;
  1021. ;    build lsb digit
  1022. putad5:    ldax    d        ;get next char
  1023.     ani    0000$1111b    ;make sure upper bits are 0
  1024.     ora    c        ;merge with last digit
  1025.     call    putbuf        ;and put in tx buffer
  1026.     inx    d        ;point to next address digit
  1027.     dcr    b        ;last digit
  1028.     jnz    putad4        ;no, get another
  1029. ;
  1030. ;    common exit
  1031. putadexi:
  1032.     pop    d        ;restore <de>
  1033.     pop    b        ;restore <bc>
  1034.     ret
  1035.  
  1036.  
  1037.  
  1038. ;    *************************
  1039. ;    *  process timeouts    *
  1040. ;    *************************
  1041.  
  1042.  
  1043.  
  1044. ;    process timeout of DTE timer T20
  1045. ;    (internally called)
  1046. ;    on entry:    no parameters
  1047. ;    on exit:    all flags, regs clobbered
  1048.  
  1049. t20to:    
  1050.     call    t20off        ;turn off timer
  1051.     lxi    h,rtryct    ;get retry count
  1052.     dcr    m        ;last retry?
  1053.     jz    t20to1        ;yes, other end is dead
  1054. ;
  1055.     call    ilprt        ;else try once more
  1056.     db    'L3: T20 timed out - '
  1057.     db    'retransmitting restart request packet',cr,lf,0
  1058.     call    t20on        ;restart timer T20
  1059.     jmp    txstar        ;and transmit restart
  1060. ;
  1061. t20to1:    call    ilprt
  1062.     db    'L3: tx retry count exhausted - '
  1063.     db    'no reply from DCE',cr,lf,0
  1064.     ret            
  1065.  
  1066.  
  1067.  
  1068. ;    process timeout of DTE timer T21
  1069. ;    (internally called)
  1070. ;    on entry:    no parameters
  1071. ;    on exit:    all flags, regs clobbered
  1072.  
  1073. t21to:    
  1074.     call    t21off        ;turn off timer
  1075.     call    ilprt        ;and tell operator
  1076.     db    'L3: T21 timed out - '
  1077.     db    'transmitting clear request packet',cr,lf,0
  1078.     jmp    txclrr        ;and transmit clear request
  1079.  
  1080.  
  1081.  
  1082. ;    process timeout of DTE timer T22
  1083. ;    (internally called)
  1084. ;    on entry:    no parameters
  1085. ;    on exit:    all flags, regs clobbered
  1086.  
  1087. t22to:    
  1088.     call    t22off        ;turn off timer
  1089.     lxi    h,rtryct    ;get retry count
  1090.     dcr    m        ;last retry?
  1091.     jz    t22to1        ;yes, other end is dead
  1092. ;
  1093.     call    ilprt        ;else try once more
  1094.     db    'L3: T22 timed out - '
  1095.     db    'retransmitting reset request packet',cr,lf,0
  1096.     call    t22on        ;restart timer T22
  1097.     jmp    txrstr        ;and transmit reset request
  1098. ;
  1099. t22to1:    call    ilprt
  1100.     db    'L3: tx retry count exhausted - '
  1101.     db    'logical channel out of order',cr,lf,0
  1102.     ret            
  1103.  
  1104.  
  1105.  
  1106. ;    process timeout of DTE timer T23
  1107. ;    (internally called)
  1108. ;    on entry:    no parameters
  1109. ;    on exit:    all flags, regs clobbered
  1110.  
  1111. t23to:    
  1112.     call    t23off        ;turn off timer
  1113.     lxi    h,rtryct    ;get retry count
  1114.     dcr    m        ;last retry?
  1115.     jz    t23to1        ;yes, other end is dead
  1116. ;
  1117.     call    ilprt        ;else try once more
  1118.     db    'L3: T23 timed out - '
  1119.     db    'retransmitting clear request packet',cr,lf,0
  1120.     call    t23on        ;restart timer T23
  1121.     jmp    txclrr        ;transmit clear request
  1122. ;
  1123. t23to1:    call    ilprt
  1124.     db    'L3: tx retry count exhausted - '
  1125.     db    'logical channel out of order',cr,lf,0
  1126.     ret            
  1127.  
  1128.  
  1129.  
  1130. ;    ***************************
  1131. ;    *  packet receive section *
  1132. ;    ***************************
  1133.  
  1134. ;    receive packet if available
  1135. ;    on entry:    no parameters
  1136. ;    on exit:    <hl>=bcb address if packet avail
  1137. ;            <b>= packet octet # 3 (packet id)
  1138. ;            <c>= rx buffer #
  1139.  
  1140.  
  1141. rxpk:    lxi    h,rxplst    ;point to received packet list
  1142.     call    getbuf        ;any there?
  1143.     rc            ;no, exit
  1144. ;
  1145.     lhld    rxpct        ;increment rx packet count
  1146.     inx    h        ;    /
  1147.     shld    rxpct        ;      /
  1148. ;
  1149.     mov    c,a        ;else save rx buffer # in <c>
  1150.     lxi    h,rxbtab    ;get buffer bcb address
  1151.     call    bpoint        ;    /
  1152.     call    getbuf        ;get octet 1
  1153.     jc    rxfmer        ;format error if not there
  1154. ;
  1155.     mov    d,a        ;save octet 1 in <d>
  1156.     call    getbuf        ;get octet 2
  1157.     jc    rxfmer        ;format error if not there
  1158. ;
  1159.     mov    e,a        ;save octet 2 in <e>
  1160.     call    getbuf        ;get octet 3
  1161.     jc    rxfmer        ;format error if not there
  1162. ;
  1163.     mov    b,a        ;save octet 3 in <b>
  1164.     cpi    starid        ;restart request?
  1165.     jz    chkrst        ;yes, check format
  1166. ;
  1167.     cpi    stacid        ;restart confirmation
  1168.     jz    chkrst        ;yes, check format
  1169. ;
  1170.     cpi    diagid        ;diagnostic
  1171.     jz    chkrst        ;yes, check format
  1172. ;
  1173. ;    process packets having logical group and channel
  1174.     lda    chan        ;get logical channel #
  1175.     cmp    e        ;match?
  1176.     jnz    rxcher        ;no, channel # error
  1177. ;
  1178.     mov    a,d        ;get back octet 1
  1179.     ani    0011$0000b    ;get bits 6-5
  1180.     cpi    0001$0000b    ;numbering modulo 8?
  1181.     jnz    rxfmer        ;no, format error
  1182. ;
  1183.     mov    a,d        ;get back octet 1
  1184.     ani    0000$1111b    ;get bits 4-1
  1185.     push    b        ;save <bc>
  1186.     mov    b,a        ;save logical group # in <b>
  1187.     lda    group        ;get our logical group #
  1188.     cmp    b        ;same?
  1189.     pop    b        ;restore <bc>
  1190.     jnz    rxgrer        ;no, group # error
  1191. ;
  1192. ;    branch to process known packet types
  1193.     mov    a,b        ;get back octet 3
  1194.     bit    0,a        ;data packet?
  1195.     jz    rxdata        ;yes, process it
  1196. ;
  1197.     cpi    intid        ;interrupt packet?
  1198.     jz    rxint        ;yes, process it
  1199. ;
  1200.     cpi    intcid        ;interrupt confirmation?
  1201.     jz    rxintc        ;yes, process it
  1202. ;
  1203.     cpi    rstrid        ;reset request?
  1204.     jz    rxrstr        ;yes, process it
  1205. ;
  1206.     cpi    rstcid        ;reset confirmation?
  1207.     jz    rxrstc        ;yes, process it
  1208. ;
  1209.     cpi    calrid        ;call request?
  1210.     jz    rxcr        ;yes, process it
  1211. ;
  1212.     cpi    calaid        ;call accepted?
  1213.     jz    rxca        ;yes, process it
  1214. ;
  1215.     cpi    clrrid        ;clear request?
  1216.     jz    rxclr        ;yes, process it
  1217. ;
  1218.     cpi    clrcid        ;clear confirmation?
  1219.     jz    rxclc        ;yes, process it
  1220. ;
  1221. ;    process packets numbered modulo 8
  1222. rxpk3:    ani    0001$1111b    ;leave only bits 5-1
  1223.     cpi    rrid        ;RR
  1224.     jz    rxrr        ;yes, process it
  1225. ;
  1226.     cpi    rnrid        ;RNR?
  1227.     jz    rxrnr        ;yes, process it
  1228. ;
  1229.     jmp    rxpk4        ;else process id error
  1230.  
  1231. ;    check format of restart and diagnostic packets
  1232. chkrst:    mov    a,d        ;get back octet 1
  1233.     cpi    0001$0000b    ;modulo 8 format?
  1234.     jnz    rxfmer        ;no, format error
  1235. ;
  1236.     mov    a,e        ;get back octet 2
  1237.     ora    a        ;all zero?
  1238.     jnz    rxfmer        ;no, format error
  1239. ;
  1240. ;    now branch to known restart packet types
  1241.     mov    a,b        ;get back octet 3
  1242.     cpi    starid        ;restart?
  1243.     jz    rxstar        ;yes, process it
  1244. ;
  1245.     cpi    stacid        ;restart confirmation?
  1246.     jz    rxstac        ;yes, process it
  1247. ;
  1248.     cpi    diagid        ;diagnostic?
  1249.     jz    rxdiag        ;yes, process it
  1250. ;    else id is unrecognized so drop through to
  1251. ;
  1252. ;    process unrecognized id error
  1253. rxpk4:    call    flush        ;discard packet
  1254.     lhld    rbipct        ;increment bad id counter
  1255.     inx    h        ;    /
  1256.     shld    rbipct        ;      /
  1257.     ret
  1258.  
  1259. ;    process packet format error
  1260. rxfmer:    call    flush        ;discard packet
  1261.     lhld    rbfpct        ;increment bad format counter
  1262.     inx    h        ;    /
  1263.     shld    rbfpct        ;      /
  1264.     ret
  1265.  
  1266. ;    process packet group error
  1267. rxgrer:    call    flush        ;discard packet
  1268.     lhld    rbgpct        ;increment bad group counter
  1269.     inx    h        ;    /
  1270.     shld    rbgpct        ;      /
  1271.     ret
  1272.  
  1273. ;    process packet channel error
  1274. rxcher:    call    flush        ;discard packet
  1275.     lhld    rbcpct        ;increment bad channel counter
  1276.     inx    h        ;    /
  1277.     shld    rbcpct        ;      /
  1278.     ret
  1279.  
  1280.  
  1281.  
  1282. ;    process rx data packet
  1283. ;    (internally called)
  1284. ;    on entry:    <hl>=rx buffer bcb address
  1285. ;            <b>=packet octet #3
  1286. ;            <c>=rx buffer #
  1287. ;    on exit:    all regs, flags clobbered
  1288.  
  1289. rxdata:
  1290.     xchg            ;save bcb address
  1291.     lxi    h,chstat    ;point to channel state
  1292.     bit    0,m        ;flow control ready state?
  1293.     xchg            ;get back bcb address
  1294.     jz    flush        ;no, discard packet
  1295. ;
  1296.     call    ackd        ;process P(s) and P(r)
  1297.     jc    dterst        ;reset channel if invalid
  1298. ;
  1299.     xchg            ;save bcb address
  1300.     lxi    h,fstat        ;point to file status
  1301.     bit    0,m        ;receive file open?
  1302.     xchg            ;restore bcb address
  1303.     jnz    rxfdat        ;yes, write packet in file
  1304. ;
  1305. ;    else write packet to console receive buffer
  1306.     lxi    d,crbcb        ;point to console rx buffer
  1307. rxcdat:    call    getbuf        ;get data octet from rx buffer
  1308.     jc    rxcd1        ;exit when empty
  1309. ;
  1310.     xchg            ;point to console rx buffer
  1311.     call    putbuf        ;put octet in console rx buffer
  1312.     xchg            ;point back to rx buffer
  1313.     jmp    rxcdat        ;and go back for more
  1314. ;
  1315. ;    process end of packet to console
  1316. rxcd1:    xchg            ;point to console rx buffer
  1317.     call    setrdy        ;set buffer ready flag
  1318.     jmp    rxdexi        ;do common exit stuff
  1319.  
  1320.  
  1321. ;    write packet into disk file
  1322. rxfdat:
  1323.     call    getbuf        ;get data octet from rx buffer
  1324.     jc    rxfd1        ;exit if empty
  1325. ;
  1326.     call    pfdata        ;else put data in file
  1327.     jmp    rxfdat        ;and loop until empty
  1328. ;
  1329. ;    process end of rx packet data
  1330. rxfd1:
  1331.     mvi    a,'+'        ;tell console packet rx
  1332.     call    ctype        ;    /
  1333.     jmp    rxdexi        ;do common exit stuff
  1334.  
  1335. ;    common exit for rx packet data
  1336. rxdexi:
  1337.     mov    a,c        ;get rx buffer #
  1338.     call    rlsrxb        ;release rx buffer
  1339.     lhld    rxdpct        ;increment rx data packet count
  1340.     inx    h        ;    /
  1341.     shld    rxdpct        ;      /
  1342.     ret
  1343.  
  1344.  
  1345.  
  1346. ;    process rx incoming call packet
  1347. ;    (internally called)
  1348. ;    on entry:    <hl>=bcb address
  1349. ;            <b>=packet octet 3 (id)
  1350. ;            <c>=rx buffer #
  1351.  
  1352. rxcr:
  1353.     call    getbuf        ;get octet 4
  1354.     jc    rxfmer        ;format error if not there
  1355. ;
  1356.     sta    rxoc4        ;save the octet
  1357.     xchg            ;save bcb address
  1358.     lxi    h,chstat    ;point to channel status
  1359.     bit    0,m        ;flow control ready state (d1)?
  1360.     jnz    rxcr1        ;yes, accept packet
  1361. ;
  1362.     bit    1,m        ;DTE restart request state (r2)?
  1363.     jnz    flush        ;yes, discard packet 
  1364. ;
  1365.     bit    2,m        ;waiting state (p2)?
  1366.     jnz    rxcr1        ;yes, accept packet
  1367. ;
  1368.     bit    3,m        ;reset request state (d2)?
  1369.     jnz    rxcr1        ;yes, accept packet
  1370. ;
  1371.     bit    4,m        ;clear request state (p6)?
  1372.     jnz    rxcr1        ;yes, accept packet
  1373. ;
  1374.     bit    5,m        ;ready state (p1)?
  1375.     jnz    rxcr1        ;yes, accept packet
  1376. ;
  1377.     jmp    flush        ;else discard packet
  1378. ;
  1379. rxcr1:    xchg            ;get back bcb address
  1380.     call    chkcadr        ;check whether address is for us
  1381.     jc    badadr        ;refuse call if invalid
  1382. ;
  1383.     call    getbuf        ;get facilities length octet
  1384.     jc    rxfmer        ;format error if not there
  1385. ;    
  1386. ;***    special facilities not implemented
  1387.     ora    a        ;facilities requested?
  1388.     jnz    calrej        ;yes, refuse call
  1389. ;
  1390.     mov    a,c        ;get rx buffer #
  1391.     call    rlsrxb        ;release it
  1392.     call    reset        ;reset flow control variables
  1393.     call    t21off        ;turn off timer T21
  1394.     call    t22off        ;turn off timer T22
  1395.     call    t23off        ;turn off timer T23
  1396.     call    ilprt
  1397.     db    'L3: rx incoming call ',0
  1398.     lda    caddrl        ;get calling DTE address length
  1399.     ora    a        ;=0?
  1400.     jz    rxca3        ;yes, keep going
  1401. ;
  1402.     inr    a        ;increment length by one
  1403.     mov    b,a        ;and save in <b>
  1404.     call    ilprt        ;display calling address
  1405.     db    'from: ',0
  1406.     lxi    h,caddr        ;point to calling address
  1407. rxca2:    dcr    b        ;end of address?
  1408.     jz    rxca3        ;yes, exit loop
  1409. ;
  1410.     mov    a,m        ;else get nibble
  1411.     call    phex1        ;display it in hex
  1412.     inx    h        ;bump pointer
  1413.     jmp    rxca2        ;and get next nibble
  1414. ;
  1415. rxca3:    call    ilprt        ;terminate message
  1416.     db    cr,lf,0
  1417.     lxi    h,l3stat    ;point to flow status
  1418.     res    1,m        ;reset DCE busy flag
  1419.     res    2,m        ;reset interrupt pending flag
  1420.     res    6,m        ;reset end of message flag
  1421.     lxi    h,chstat    ;point to channel status
  1422.     setb    0,m        ;set flow control ready state (d1)
  1423.     res    3,m        ;reset DTE reset request state (d2)
  1424.     res    4,m        ;reset DTE clear request state (p6)
  1425.     res    5,m        ;reset ready state (p1)
  1426.     bit    2,m        ;DTE waiting state (p2)?
  1427.     jz    txca        ;no, tx call accepted packet
  1428. ;
  1429. ;    call collision state (p5)
  1430.     res    2,m        ;else reset state p2
  1431.     ret            ;and exit
  1432.  
  1433.  
  1434.  
  1435. ;    process rx call connected packet
  1436. ;    (internally called)
  1437. ;    on entry:    <hl>=bcb address
  1438. ;            <b>=packet octet 3 (id)
  1439. ;            <c>=rx buffer #
  1440.  
  1441. rxca:
  1442.     xchg            ;save bcb address
  1443.     lxi    h,chstat    ;point to channel status
  1444.     bit    2,m        ;DTE waiting state (p2)?
  1445.     jnz    rxca0        ;yes, accept packet
  1446. ;
  1447.     jmp    flush        ;else discard packet
  1448. ;
  1449. rxca0:    xchg            ;get back bcb address
  1450.     call    getbuf        ;get octet 4 if present
  1451.     jc    rxca1        ;skip address check if not present
  1452. ;
  1453.     sta    rxoc4        ;save octet 4 if present
  1454.     call    chkadr        ;check addresses
  1455.     jc    badadr        ;refuse call if invalid
  1456. ;
  1457.     call    getbuf        ;get octet 5 if present
  1458.     jc    rxca1        ;skip facilities check if not present
  1459. ;
  1460. ;***    special facilities not implemented
  1461. ;
  1462. ;    checks all done, accept call
  1463. rxca1:    mov    a,c        ;get rx buffer #
  1464.     call    rlsrxb        ;release it
  1465.     call    reset        ;reset flow control variables
  1466.     call    t21off        ;turn off timer T21
  1467.     call    t22off        ;turn off timer T22
  1468.     call    t23off        ;turn off timer T23
  1469.     call    ilprt
  1470.     db    'L3: rx call connected',cr,lf,0
  1471.     lxi    h,l3stat    ;point to flow control status
  1472.     res    1,m        ;reset DCE busy flag
  1473.     res    2,m        ;reset interrupt pending flag
  1474.     res    6,m        ;reset message complete flag
  1475.     lxi    h,chstat    ;point to channel status
  1476.     setb    0,m        ;set flow control ready state (d1)
  1477.     res    2,m        ;reset DTE waiting state (p2)
  1478.     res    3,m        ;reset DTE reset request state (d2)
  1479.     res    4,m        ;reset DTE clear request state (p6)
  1480.     res    5,m        ;reset ready state (p1)
  1481.     ret            ;and exit
  1482.  
  1483.  
  1484. ;    process invalid address
  1485. ;    (internally called)
  1486. ;    on entry:    <c>=rx buffer #
  1487. ;    on exit:    all flags, regs clobbered
  1488.  
  1489. ;    
  1490. badadr:    call    flush        ;discard packet
  1491.     lhld    rbapct        ;increment bad address count
  1492.     inx    h        ;    /
  1493.     shld    rbapct        ;      /
  1494.     call    ilprt
  1495.     db    'L3: bad address - tx clear request',cr,lf,0
  1496.     jmp    txclrr        ;transmit clear request
  1497.  
  1498.  
  1499. ;    refuse call
  1500. ;    (internally called)
  1501. ;    on entry:    <c>=rx buffer #
  1502. ;    on exit:    all flags, regs clobbered
  1503.  
  1504.  
  1505. calrej:    call    flush        ;discard packet
  1506.     call    ilprt
  1507.     db    'L3: call refused - tx clear request',cr,lf,0
  1508.     jmp    txclrr        ;transmit clear request
  1509.  
  1510.  
  1511.  
  1512. ;    process rx clear indication (clear request) packet
  1513. ;    (internally called)
  1514. ;    on entry:    <hl>=bcb address
  1515. ;            <b>=packet octet 3 (id)
  1516. ;            <c>=rx buffer #
  1517.  
  1518. rxclr:
  1519.     call    getbuf        ;get octet 4
  1520.     jc    rxfmer        ;format error if not there
  1521. ;
  1522.     mov    b,a        ;save octet 4 in <b>
  1523.     xchg            ;save bcb address
  1524.     lxi    h,chstat    ;point to channel status
  1525.     bit    0,m        ;flow control ready state (d1)?
  1526.     jnz    rxclr0        ;yes, accept packet
  1527. ;
  1528.     bit    4,m        ;clear request state (p6)?
  1529.     jnz    rxclr0        ;yes, accept packet
  1530. ;
  1531.     jmp    flush        ;else discard packet
  1532. ;
  1533. rxclr0:    xchg            ;restore bcb address
  1534.     call    ilprt        ;tell operator
  1535.     db    'L3: rx clear indication packet, cause: ',0
  1536.     mov    a,b        ;get back octet 4
  1537.     call    phex        ;print in hex
  1538.     call    ilprt        ;    /
  1539.     db    ' (hex)',cr,lf,0        ;      /
  1540.     call    getbuf        ;get octet 5
  1541.     jc    rxclr2        ;keep going if not there
  1542. ;
  1543.     mov    b,a        ;save octet 5 in <b>
  1544.     call    ilprt
  1545.     db    '    diagnostic code      : ',0
  1546.     mov    l,b        ;print diagnostic code
  1547.     mvi    h,0        ;    /
  1548.     call    pdec        ;print in decimal
  1549.     call    ilprt
  1550.     db    cr,lf,0
  1551. ;
  1552. ;    perform flow control actions
  1553. rxclr2:
  1554.     mov    a,c        ;get rx buffer #
  1555.     call    rlsrxb        ;and release it
  1556.     call    reset        ;reset flow control variables
  1557.     call    t21off        ;stop timers
  1558.     call    t22off        ;      /
  1559.     call    t23off        ;     /
  1560.     call    ctxfil        ;close transmit file
  1561.     call    crxfil        ;close receive file
  1562.     lxi    h,chstat    ;point to channel status
  1563.     res    0,m        ;reset state d1
  1564.     res    2,m        ;reset state p2
  1565.     res    3,m        ;reset state d2
  1566.     setb    5,m        ;set ready state p1
  1567.     bit    4,m        ;was it DTE clear request state (p6)?
  1568.     jz    txclrc        ;no, tx clear confirmation packet
  1569. ;
  1570. ;    DTE clear request state (p6)
  1571.     res    4,m        ;else reset clear request state 
  1572.     ret            ;and exit
  1573.  
  1574.  
  1575.  
  1576. ;    process rx clear confirmation packet
  1577. ;    (internally called)
  1578. ;    on entry:    <hl>=bcb address
  1579. ;            <b>=packet octet 3 (id)
  1580. ;            <c>=rx buffer #
  1581.  
  1582. rxclc:
  1583.     call    getbuf        ;get octet 4
  1584.     jnc    rxfmer        ;format error if there
  1585. ;
  1586.     lxi    h,chstat    ;point to channel status
  1587.     bit    4,m        ;DTE clear request state (p6)?
  1588.     jz    flush        ;no, discard packet
  1589. ;
  1590. ;    DTE clear request state (p6)
  1591.     res    4,m        ;reset back to ready state
  1592.     mov    a,c        ;get rx buffer #
  1593.     call    rlsrxb        ;and release it
  1594.     call    reset        ;reset flow control variables
  1595.     call    ilprt        ;tell operator
  1596.     db    'L3: rx clear confirmation packet',cr,lf,0
  1597.     ret
  1598.  
  1599.  
  1600.     
  1601. ;    process rx INT packet
  1602. ;    (internally called)
  1603. ;    on entry:    <hl>=bcb address
  1604. ;            <c>=rx buffer #
  1605.  
  1606. rxint:
  1607.     call    getbuf        ;get octet 4
  1608.     jc    rxfmer        ;format error if not there
  1609. ;
  1610.     xchg            ;save bcb address in <de>
  1611.     lxi    h,chstat    ;point to channel status
  1612.     bit    0,m        ;flow control ready state (d1)?
  1613.     jz    flush        ;no, discard packet
  1614. ;
  1615.     xchg            ;restore bcb address
  1616.     mov    b,a        ;save octet 4 in <b>
  1617.     call    ilprt
  1618.     db    'L3: rx INT packet - user data: ',0
  1619.     mov    a,b        ;get back octet 4
  1620.     call    phex        ;print in hex
  1621.     call    ilprt        ;terminate line
  1622.     db    cr,lf,0
  1623.     mov    a,c        ;get rx buffer #
  1624.     call    rlsrxb        ;release it
  1625.     jmp    txintc        ;and transmit int confirmation
  1626.  
  1627.  
  1628. ;    process rx INT confirmation packet
  1629. ;    (internally called)
  1630. ;    on entry:    <hl>=bcb address
  1631. ;            <c>=rx buffer #
  1632.  
  1633. rxintc:
  1634.     call    getbuf        ;tryto get octet 4
  1635.     jnc    rxfmer        ;format error if there
  1636. ;
  1637.     lxi    h,chstat    ;point to channel status
  1638.     bit    0,m        ;flow control ready state (d1)?
  1639.     jz    flush        ;no, discard packet
  1640. ;
  1641.     lxi    h,l3stat    ;point to level 3 status
  1642.     bit    2,m        ;interrupt pending?
  1643.     jz    flush        ;no, discard packet
  1644. ;
  1645.     res    2,m        ;else clear int pending flag
  1646.     call    ilprt
  1647.     db    'L3: rx interrupt confirmation packet',cr,lf,0
  1648.     mov    a,c        ;get rx buffer #
  1649.     call    rlsrxb        ;release it
  1650.     ret
  1651.  
  1652.  
  1653. ;    process DIAG packet
  1654. ;    (internally called)
  1655. ;    on entry:    <hl>=bcb address
  1656. ;            <b>=packet octet #3 (packet id)
  1657. ;            <c>=rx buffer #
  1658.  
  1659. rxdiag:
  1660.     call    getbuf        ;get octet 4
  1661.     jc    rxfmer        ;format error if not there
  1662. ;
  1663.     xchg            ;save bcb address in <de>
  1664.     mov    b,a        ;save octet 4 in <b>
  1665.     call    ilprt
  1666.     db    'L3: rx DIAG packet - diagnostic # ',0
  1667.     mov    l,b        ;print diagnostic code
  1668.     mvi    h,0        ;    /
  1669.     call    pdec        ;      /
  1670.     call    ilprt        ;print explanation if present
  1671.     db    cr,lf,'L3: diagnostic explanation: ',0
  1672.     xchg            ;get back bcb address
  1673.  
  1674. ;    print diagnostic explanation
  1675. diaglp:    call    getbuf        ;get next octet
  1676.     jc    diagexi        ;exit if not there
  1677. ;
  1678.     call    phex        ;print in hex
  1679.     call    ilprt        ;and separator
  1680.     db    ' ',0
  1681.     jmp    diaglp        ;and try for next byte
  1682. ;
  1683. diagexi:
  1684.     call    ilprt        ;terminate explanation line
  1685.     db    cr,lf,0
  1686.     mov    a,c        ;get rx buffer
  1687.     call    rlsrxb        ;release it
  1688.     ret
  1689.  
  1690.  
  1691.  
  1692. ;    process rx RR packet
  1693. ;    (internally called)
  1694. ;    on entry:    <b>=octet 3        
  1695. ;            <c>=rx buffer #
  1696.  
  1697. rxrr:    lxi    h,chstat    ;point to channel status
  1698.     bit    0,m        ;flow control ready state?
  1699.     jz    flush        ;no, discard packet
  1700. ;
  1701.     call    chkpr        ;check P(r) and update window
  1702.     jc    dterst        ;local procedure error
  1703. ;
  1704.     lxi    h,l3stat    ;point to level 3 status
  1705.     res    1,m        ;clear DCE busy
  1706.     mov    a,c        ;release rx buffer
  1707.     call    rlsrxb        ;    /
  1708.     ret
  1709.  
  1710.  
  1711.  
  1712. ;    process rx RNR packet
  1713. ;    (internally called)
  1714. ;    on entry:    <b>=octet 3        
  1715. ;            <c>=rx buffer #
  1716.  
  1717. rxrnr:    lxi    h,chstat    ;point to channel status
  1718.     bit    0,m        ;flow control ready state?
  1719.     jz    flush        ;no, discard packet
  1720. ;
  1721.     call    chkpr        ;check P(r) & update window
  1722.     jc    dterst        ;local procedure error
  1723. ;
  1724.     lxi    h,l3stat    ;point to level 3 status
  1725.     setb    1,m        ;signal DCE busy
  1726.     mov    a,c        ;release rx buffer
  1727.     call    rlsrxb        ;    /
  1728.     ret
  1729.  
  1730.  
  1731.  
  1732. ;    process received reset indication
  1733. ;    (internally called)
  1734. ;    on entry:    <b>=octet 3        
  1735. ;            <c>=rx buffer #
  1736.  
  1737. rxrstr:    lxi    h,chstat    ;point to channel status
  1738.     bit    3,m        ;reset request state (d2)?
  1739.     jnz    rxstr0        ;yes, accept packet
  1740. ;
  1741.     bit    0,m        ;flow control ready state (d1)
  1742.     jnz    rxstr1        ;yes, accept packet
  1743. ;
  1744.     jmp    flush        ;else discard packet
  1745. ;
  1746. ;    reset collision (para 4.4.3.3)
  1747. rxstr0:
  1748.     res    3,m        ;clear reset request state
  1749.     setb    0,m        ;set flow control ready state d1
  1750.     call    t22off        ;stop timer T22
  1751.     mov    a,c        ;get rx buffer #
  1752.     call    rlsrxb        ;release buffer
  1753.     ret            ;and exit
  1754. ;
  1755. ;    DTE in flow control ready (d1) state
  1756. rxstr1:
  1757.     mov    a,c        ;release rx buffer
  1758.     call    rlsrxb        ;    /
  1759.     call    reset        ;reset flow control variables
  1760.     lxi    h,l3stat    ;point to level 3 status
  1761.     res    1,m        ;clear DCE busy status
  1762.     jmp    txrstc        ;and transmit reset confirmation
  1763.  
  1764.  
  1765.  
  1766. ;    process received reset confirmation
  1767. ;    (internally called)
  1768. ;    on entry:    <b>=octet 3        
  1769. ;            <c>=rx buffer #
  1770.  
  1771. rxrstc:    lxi    h,chstat    ;point to channel status
  1772.     bit    3,m        ;DTE reset request state?
  1773.     jz    flush        ;no, discard packet
  1774. ;
  1775. ;    DTE in reset request state (d2)
  1776.     res    3,m        ;clear state d2
  1777.     setb    0,m        ;set state d1
  1778.     call    t22off        ;stop timer T22
  1779.     mov    a,c        ;get rx buffer #
  1780.     call    rlsrxb        ;release buffer
  1781.     lxi    h,l3stat    ;point to level 3 status
  1782.     res    1,m        ;clear DCE busy status
  1783.     ret            ;and exit
  1784. ;
  1785.  
  1786.  
  1787. ;    process received restart indication
  1788. ;    (internally called)
  1789. ;    on entry:    <b>=octet 3        
  1790. ;            <c>=rx buffer #
  1791.  
  1792. rxstar:    lxi    h,chstat    ;point to channel status
  1793.     res    0,m        ;clear state d1 for now
  1794.     res    2,m        ;and state p2
  1795.     res    3,m        ;and state d2
  1796.     res    4,m        ;and state p6
  1797.     setb    5,m        ;set ready state p1
  1798.     lda    pvcmod        ;get pvc mode flag
  1799.     cpi    1        ;VC?
  1800.     jz    rstar1        ;yes, keep going
  1801. ;
  1802. ;    set flow control ready if in PVC mode
  1803.     res    5,m        ;reset ready state p1
  1804.     setb    0,m        ;and set flow control state d1
  1805. ;
  1806. rstar1:
  1807.     mov    a,c        ;release buffer
  1808.     call    rlsrxb        ;    /
  1809.     bit    1,m        ;DTE restart request state (r2)?
  1810.     jz    rstar2        ;no, keep going
  1811. ;
  1812. ;    DTE in restart request state (r2)
  1813.     res    1,m        ;clear state r2
  1814.     call    t20off        ;stop timer T20
  1815.     ret            ;and exit
  1816. ;
  1817. ;    DTE not in restart request state
  1818. rstar2:
  1819.     call    reset        ;reset flow control variables
  1820.     lxi    h,l4stat    ;point to level 4 status
  1821.     setb    0,m        ;signal console prompt
  1822.  
  1823. ;***    do other things here?
  1824. ;
  1825.     call    ilprt
  1826.     db    'L3: rx restart',cr,lf,0
  1827.     jmp    txstac        ;and transmit restart confirmation
  1828.  
  1829.  
  1830.  
  1831. ;    process received restart confirmation
  1832. ;    (internally called)
  1833. ;    on entry:    <b>=octet 3        
  1834. ;            <c>=rx buffer #
  1835.  
  1836. rxstac:    lxi    h,chstat    ;point to channel status
  1837.     bit    1,m        ;DTE restart request state?
  1838.     jz    flush        ;no, discard packet
  1839. ;
  1840. ;    DTE in restart request state (r2)
  1841.     res    0,m        ;clear state d1 for now
  1842.     res    1,m        ;and state r2
  1843.     res    2,m        ;and state p2
  1844.     res    3,m        ;and state d2
  1845.     res    4,m        ;and state p6
  1846.     setb    5,m        ;set ready state p1
  1847.     lda    pvcmod        ;get PVC mode flag
  1848.     cpi    1        ;VC?
  1849.     jz    rstac1        ;yes, keep going
  1850. ;
  1851. ;    set flow control ready if in PVC mode
  1852.     res    5,m        ;reset ready state p1
  1853.     setb    0,m        ;and set flow control state d1
  1854. ;
  1855. rstac1:
  1856.     call    t20off        ;stop timer T20
  1857.     mov    a,c        ;get rx buffer #
  1858.     call    rlsrxb        ;release buffer
  1859.     lxi    h,l4stat    ;point to level 4 status
  1860.     setb    0,m        ;signal console prompt
  1861.     ret            ;and exit
  1862. ;
  1863.  
  1864.  
  1865.  
  1866. ;    reset DTE
  1867.  
  1868. dterst:
  1869.     mov    a,c        ;release buffer
  1870.     call    rlsrxb        ;    /
  1871.     call    ilprt
  1872.     db    cr,lf,'L3: local procedure error - '
  1873.     db    'resetting channel',cr,lf,0
  1874.     call    reset        ;reset flow control variables
  1875.     jmp    txrstr        ;and transmit reset request
  1876.  
  1877.  
  1878.  
  1879.  
  1880.  
  1881.  
  1882. ;    *************************************************
  1883. ;    *  utility subroutines for receive section    *
  1884. ;    *************************************************
  1885.  
  1886.  
  1887. ;    discard data packet
  1888. ;    (internally called)
  1889. ;    on entry:    <c>=rx buffer #
  1890. ;    on exit:    all regs, flags clobbered
  1891.  
  1892. flush:    
  1893.     mov    a,c        ;get rx buffer #
  1894.     call    rlsrxb        ;release it
  1895.     lhld    rxxpct        ;increment discarded packet count
  1896.     inx    h        ;    /
  1897.     shld    rxxpct        ;      /
  1898.     ret
  1899.  
  1900.  
  1901. ;    acknowledge received data packet & update window
  1902. ;    (internally called)
  1903. ;    on entry:    <b>=octet 3 of data packet
  1904. ;    on exit:    carry set if P(s) or P(r) sequence error
  1905. ;            <a>, other flags clobbered
  1906. ;            all other regs unchanged
  1907.  
  1908. ackd:    
  1909.     push    h        ;save regs
  1910.     push    d        ;    /
  1911.     push    b        ;      /
  1912.     call    chkpr        ;check P(r) and update window
  1913.     jc    ackdexi        ;exit with carry if invalid P(s)
  1914.  
  1915. ;    check for valid rx P(s)
  1916.     mov    a,b        ;get octet 3
  1917.     ani    0000$1110b    ;extract rx P(s)
  1918.     rrc            ;move to bits 0-2
  1919.     mov    c,a        ;save rx P(s) in <c>
  1920. ;
  1921. ;    check for P(s) next in sequence
  1922.     lda    lrxps        ;get last rx P(s)
  1923.     inr    a        ;bump mod 7
  1924.     ani    7        ;    /
  1925.     cmp    c        ;next in sequence?
  1926.     jnz    ackderr        ;no, invalid
  1927. ;
  1928. ;    calculate top of valid range for rx P(s)
  1929.     lda    pr        ;get local P(r)
  1930.     adi    wsize+1        ;add window size+1
  1931.     ani    7        ;mod 7
  1932.     mov    e,a        ;and save in <e>
  1933. ;
  1934. ;    check for rx P(s) within window
  1935.     lda    pr        ;bottom edge= local P(r)
  1936. ackd3:    cmp    e        ;past top of window?
  1937.     jz    ackderr        ;yes, error
  1938. ;
  1939.     cmp    c        ;rx P(s) at bottom edge?
  1940.     jz    ackdok        ;yes, valid rx P(r)
  1941. ;
  1942.     inr    a        ;else bump bottom edge
  1943.     ani    7        ;    /
  1944.     jmp    ackd3        ;and keep looping
  1945. ;
  1946. ;    valid rx P(s)
  1947. ackdok:    mov    a,c        ;get rx P(s)
  1948.     sta    lrxps        ;update last rx P(s)
  1949.     inr    a        ;let P(r)=P(s)+1..
  1950.     ani    7        ;..mod 7
  1951.     sta    pr        ;and update P(r)
  1952.     stc            ;clear carry bit
  1953.     cmc            ;    /
  1954.     jmp    ackdexi        ;and exit
  1955. ;
  1956. ;    invalid  rx P(s)
  1957. ackderr:
  1958.     stc            ;set carry bit
  1959.  
  1960. ;    common exit
  1961. ackdexi:
  1962.     pop    b        ;restore regs
  1963.     pop    d        ;    /
  1964.     pop    h        ;      /
  1965.     ret
  1966.  
  1967.  
  1968. ;    check received P(r) and update window if valid
  1969. ;    (internally called)
  1970. ;    on entry:    <b>=octet 3 of rx packet
  1971. ;    on exit:    carry set if invalid rx P(r)
  1972. ;            <a>,other flags clobbered
  1973. ;            all other regs unchanged
  1974.  
  1975. chkpr:    push    h        ;save regs
  1976.     push    d        ;    /
  1977.     push    b        ;      /
  1978.     mov    a,b        ;get octet 3
  1979.     ani    1110$0000b    ;extract rx P(r)
  1980.     rrc            ;move to bits 0-2
  1981.     rrc            ;    /
  1982.     rrc            ;      /
  1983.     rrc            ;     /
  1984.     rrc            ;    /
  1985.     mov    c,a        ;save rx P(r) in <c>
  1986.     lda    lastpr        ;get last rx P(r)
  1987.     cmp    c        ;same as this one?
  1988.     jz    chkexi        ;yes, nothing new
  1989. ;
  1990. ;    calculate top of valid range for rx P(r)
  1991.     lda    ps        ;get local P(s)
  1992.     inr    a        ;increment mod 7...
  1993.     inr    a        ;..past top of valid range
  1994.     ani    7        ;    /
  1995.     mov    e,a        ;save in <e>
  1996. ;
  1997. ;    check for rx P(r) within window
  1998.     lda    lastpr        ;bottom edge=last rx P(r)
  1999. chkpr1:    cmp    e        ;past top of window?
  2000.     jz    chkerr        ;yes, invalid
  2001.     cmp    c        ;rx P(r) at bottom edge?
  2002.     jz    chkpr2        ;yes, valid
  2003.     inr    a        ;else bump bottom edge
  2004.     ani    7        ;mod 7
  2005.     jmp    chkpr1        ;and keep looping
  2006. ;
  2007. ;    valid rx P(r)
  2008. chkpr2:    mov    a,c        ;get rx P(r)
  2009.     sta    lastpr        ;update lower window edge
  2010.     xra    a        ;clear carry flag
  2011.     jmp    chkexi        ;and exit
  2012. ;
  2013. ;    invalid rx P(r)
  2014. chkerr:    stc            ;set carry flag
  2015. ;
  2016. ;    common exit
  2017. chkexi:    pop    b        ;restore regs
  2018.     pop    d        ;    /
  2019.     pop    h        ;      /
  2020.     ret
  2021.  
  2022.  
  2023. ;    check for valid local DTE address in call request packet
  2024. ;    (internally called)
  2025. ;    on entry:    <hl>=bcb address
  2026. ;            <c>=rx buffer #
  2027. ;    on exit:    carry set if address is invalid
  2028. ;            <a>,flags clobbered
  2029. ;            all other regs unchanged
  2030.  
  2031. chkcadr:
  2032.     push    b        ;save regs
  2033.     push    d        ;    /
  2034.     push    h        ;      /
  2035.     lxi    h,l3stat    ;point to level 3 status
  2036.     res    5,m        ;clear address error flag
  2037.     pop    h        ;restore bcb address
  2038.     lda    rxoc4        ;get rx address length octet
  2039.     mov    b,a        ;save in <b>
  2040.     call    getmsn        ;get high nibble
  2041.     sta    caddrl        ;store calling address length
  2042.     mov    a,b        ;get back octet 4
  2043.     ani    0000$1111b    ;get called address length
  2044.     mov    b,a        ;save it in <b>
  2045.     lda    laddrl        ;get our address length
  2046.     cmp    b        ;same?
  2047.     cnz    adderr        ;no, signal error
  2048.     lxi    d,laddr        ;<de> points to our address
  2049.     inr    b        ;bump received called address length
  2050. ;
  2051. ;    check to see if called address is ours
  2052. laddr1:    dcr    b        ;last called address byte?
  2053.     jz    caddr1        ;yes, go read calling address
  2054. ;
  2055.     call    getbuf        ;else get next address octet
  2056.     cc    adderr        ;signal error if not there
  2057.     mov    c,a        ;save octet in <c>
  2058.     call    getmsn        ;get high nibble
  2059.     xchg            ;point to our address
  2060.     cmp    m        ;match?
  2061.     cnz    adderr        ;no, signal error
  2062.     xchg            ;point back to bcb
  2063.     inx    d        ;bump pointers
  2064.     dcr    b        ;last called address byte?
  2065.     jz    caddr0        ;yes, go read calling address
  2066. ;
  2067.     mov    a,c        ;get back octet
  2068.     ani    0000$1111b    ;get low nibble
  2069.     xchg            ;point to our address
  2070.     cmp    m        ;match?
  2071.     cnz    adderr        ;no, signal error
  2072.     xchg            ;point back to bcb
  2073.     inx    d        ;bump pointer
  2074.     jmp    laddr1        ;and look for next octet
  2075. ;
  2076. ;    read and store calling address if at high nibble
  2077. caddr0:    lda    caddrl        ;get calling address length
  2078.     mov    b,a        ;save in <b>
  2079.     lxi    d,caddr        ;point to calling address buffer
  2080.     inr    b        ;bump received calling address length
  2081.     jmp    caddr3        ;and keep going
  2082. ;
  2083. ;    read and store calling address if at low nibble
  2084. caddr1:    lda    caddrl        ;get calling address length
  2085.     mov    b,a        ;save in <b>
  2086.     lxi    d,caddr        ;point to calling address buffer
  2087.     inr    b        ;bump received calling address length
  2088. ;
  2089. ;    read address if at low nibble
  2090. caddr2:    dcr    b        ;last address nibble?
  2091.     jz    cadexi        ;yes, exit
  2092. ;
  2093.     call    getbuf        ;get next octet
  2094.     cc    adderr        ;else signal error
  2095.     mov    c,a        ;save in <c>
  2096.     call    getmsn        ;get high nibble
  2097.     stax    d        ;save at pointer location
  2098.     inx    d        ;bump pointers
  2099. ;
  2100. ;    read address if at high nibble
  2101. caddr3:    dcr    b        ;last address nibble?
  2102.     jz    cadexi        ;yes, exit
  2103. ;
  2104.     mov    a,c        ;else get back octet
  2105.     ani    0000$1111b    ;get low nibble
  2106.     stax    d        ;and save at pointer location
  2107.     inx    d        ;bump pointer
  2108.     jmp    caddr2        ;and get next octet
  2109. ;
  2110. ;    exit with carry set if error occured
  2111. cadexi:    stc            ;set carry flag
  2112.     push    h        ;save bcb
  2113.     lxi    h,l3stat    ;point to level 3 status
  2114.     bit    5,m        ;called address error?
  2115.     pop    h        ;restore bcb
  2116.     jnz    cadexi1        ;and exit with carry
  2117. ;
  2118.     cmc            ;else clear carry
  2119. cadexi1:
  2120.     pop    d        ;restore regs
  2121.     pop    b        ;    /
  2122.     ret
  2123.  
  2124.  
  2125. ;    get high nibble of octet
  2126. ;    (internally called)
  2127. ;    on entry:    <a>=octet
  2128. ;    on exit:    <a>=high nibble of octet
  2129. ;            all other regs unchanged
  2130.  
  2131. getmsn:
  2132.     ani    1111$0000b    ;strip out high nibble
  2133.     rrc            ;and move to bits 0-4
  2134.     rrc            ;    /
  2135.     rrc            ;      /
  2136.     rrc            ;     /
  2137.     ret
  2138.  
  2139.  
  2140. ;    signal called DTE address error
  2141. ;    (internally called)
  2142. ;    on entry:    no parameters
  2143. ;    on exit:    l3stat bit 5=1
  2144. ;            all regs unchanged
  2145. ;
  2146. adderr:    push    h        ;save <hl>
  2147.     lxi    h,l3stat    ;point to level 3 status
  2148.     setb    5,m        ;set address error bit
  2149.     pop    h        ;restore <hl>
  2150.     ret
  2151.  
  2152. ;    check for valid addresses in call accepted packet
  2153. ;    (internally called)
  2154. ;    on entry:    <hl>=rx bcb address
  2155. ;    on exit:    carry set if address error
  2156. ;            all other regs unchaged
  2157. chkadr:
  2158. ;***    not implemented yet
  2159.     xra    a
  2160.     ret
  2161.  
  2162.  
  2163.  
  2164.  
  2165. ;    *****************
  2166. ;    *  data area    *
  2167. ;    *****************
  2168.  
  2169.     dseg        ;data area
  2170.  
  2171. ;    level 3 status indicators
  2172.  
  2173. l3stat:    db    0    ;level 3 status flags
  2174. chstat:    db    0    ;logical channel state
  2175.  
  2176. ;    X.25 address and channel parameters
  2177. group    db    0    ;logical group number
  2178. chan    db    lchan    ;logical channel number
  2179. gfi    db    0    ;general format identifier
  2180. laddrl:    db    0    ;local address length (# of hex chars)
  2181. raddrl:    db    0    ;remote address length (# of hex chars)
  2182. caddrl:    db    0    ;rx calling DTE address length
  2183. laddr:    ds    15    ;local DTE address (1 hex char/byte)
  2184. raddr:    ds    15    ;remote DTE address (1 hex char/byte)
  2185. caddr:    ds    15    ;rx calling DTE address (1 hex char/byte)
  2186. rxoc4:    db    0    ;received address length octet 4
  2187.  
  2188.  
  2189. ;    X.25 packet flow control variables
  2190.  
  2191. pr    db    0    ;P(r)
  2192. ps    db    0    ;P(s)
  2193. lastpr    db    0    ;last rx P(r)
  2194. ltxpr    db    0    ;last tx P(r)
  2195. lrxps    db    7    ;last rx P(s)
  2196. ltxps    db    7    ;last tx P(s)
  2197. qbit    db    0    ;Q (qualifier) bit (bit 7)
  2198. dbit    db    0    ;D (delivery confirmation) bit (bit 6)
  2199. rtryct    db    n3    ;tx retry count
  2200. pvcmod    db    1    ;VC/PVC mode flag (1=VC,2=PVC)
  2201. packct    db    kpack    ;packet acknowledgement delay count
  2202.  
  2203. ;    level 3 diagnostic counters
  2204.     
  2205. txpct:    dw    0    ;total tx packets
  2206. txfpct:    dw    0    ;tx file data packets
  2207. txcpct:    dw    0    ;tx console data packets
  2208. ntxbct:    dw    0    ;errors due to no free tx bcb
  2209. ;
  2210. rxpct:    dw    0    ;total rx packets
  2211. rxdpct:    dw    0    ;total rx data packets
  2212. rbfpct:    dw    0    ;total rx bad format packets
  2213. rbcpct:    dw    0    ;total rx bad channel packets
  2214. rbapct:    dw    0    ;total rx bad address packets
  2215. rbipct:    dw    0    ;total rx bad id packets
  2216. rbgpct:    dw    0    ;total rx bad group packets
  2217. rxxpct:    dw    0    ;total discarded rx packets
  2218.