home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / pcmagazi / 1992 / 09 / bbplus.asm < prev    next >
Assembly Source File  |  1992-03-29  |  59KB  |  1,462 lines

  1.             page    55,132
  2.             title   "BBPLUS - Compuserve B+ Protocol Module"
  3.  
  4. ; ---------------------------------------------------------------------
  5. ;
  6. ; Maintenance Log:
  7. ;
  8. ; Version    Date   Description                        Who
  9. ; -------  -------  ---------------------------------- ----------------
  10. ;   1.0    08Feb91  Initial version complete           Flanders/Holmes
  11. ;
  12. ; ---------------------------------------------------------------------
  13.  
  14. protocol    segment para public 'code'
  15.             assume  cs:protocol
  16.  
  17. start:      jmp     bpmbplus                ; jump to start
  18.             db      "BD"                    ; backdown protocol ID
  19.  
  20.             db      1                       ; nbr of protocols
  21.  
  22.             db      "B"                     ; invocation letter
  23.             db      "CIS B+ V1.0     ", 0   ; name to display
  24.             db      1                       ; protocol number
  25.  
  26. ; --------------------------------------------------------------------
  27. ;  Macro(s)
  28. ; --------------------------------------------------------------------
  29.  
  30. FARRET      macro                           ; far return macro
  31.             db      0cbh
  32.             endm
  33.  
  34. NSTATE      macro   nxtstate                ; go to next state
  35.             ifnb    <nxtstate>              ; if next state given
  36.             mov     state, nxtstate         ; move in next state
  37.             endif
  38.             stc                             ; tell state_exec to do it
  39.             ret                             ; .. continue
  40.             endm
  41.  
  42. XSTATE      macro   nxtstate                ; exit the state machine
  43.             ifnb    <nxtstate>              ; if next state given
  44.             mov     state, nxtstate         ; move in next state
  45.             endif
  46.             clc                             ; tell state_exec to do it
  47.             ret                             ; .. continue
  48.             endm
  49.  
  50. ; ---------------------------------------------------------------------
  51. ;  Protocol characters equates
  52. ; ---------------------------------------------------------------------
  53.  
  54. $ETX        =       03h                     ; Trailer byte
  55. $ENQ        =       05h                     ; Enquiry code
  56. $CR         =       0Dh                     ; Carriage return
  57. $DLE        =       10h                     ; Lead in byte
  58. $NAK        =       15h                     ; Negative acknowledgement
  59.  
  60. ; ---------------------------------------------------------------------
  61. ;  Local stack
  62. ; ---------------------------------------------------------------------
  63.  
  64.             even
  65. bpmstack    db      32 dup ("St")           ; local stack area
  66. bpmstackend db      "Es"                    ; End of local stack
  67.  
  68. stackoffset dw      offset bpmstackend      ; New stack pointer
  69.  
  70. ; ---------------------------------------------------------------------
  71. ;  State definitions
  72. ; ---------------------------------------------------------------------
  73.  
  74. $ST_INIT    =       -1                      ; Awaiting initialization
  75. $ST_DLE     =       0                       ; DLE seen
  76. $ST_DLEB    =       2                       ; <DLE>B seen
  77. $ST_GETDATA =       4                       ; Getting data in packet
  78. $ST_GETCKS  =       6                       ; Getting checksum
  79. $ST_GETCRC  =       8                       ; Getting crc
  80. $ST_VERCRC  =       10                      ; Verifying CRC
  81. $ST_VERCKS  =       12                      ; Verifying Checksum
  82. $ST_VERPKT  =       14                      ; Verifying Packet
  83. $ST_SNDNAK  =       16                      ; Sending a NAK
  84. $ST_SNDACK  =       18                      ; Sending an ACK
  85. $ST_GETDLE  =       20                      ; Wait for a DLE
  86.  
  87. state       dw      $ST_INIT                ; current state
  88.  
  89. state_jmp   dw      bpdle                   ;  0: DLE seen
  90.             dw      bpdleb                  ;  2: <DLE>B seen
  91.             dw      bpgetdata               ;  4: Getting data in packet
  92.             dw      bpgetcks                ;  6: Getting checksum
  93.             dw      bpgetcrc                ;  8: Getting crc
  94.             dw      bpvercrc                ; 10: Verifying CRC
  95.             dw      bpvercks                ; 12: Verifying Checksum
  96.             dw      bpverpkt                ; 14: Verifying Packet
  97.             dw      bpsndnak                ; 16: Sending a NAK
  98.             dw      bpsndack                ; 18: Sending an ACK
  99.             dw      bpgetdle                ; 20: Wait for a DLE
  100.  
  101.  
  102. ; ---------------------------------------------------------------------
  103. ;  Transport Parameter Packet
  104. ;
  105. ;  This protocol supports the following:
  106. ;
  107. ;        Send window:   1 packet    Receive window:   2 packets
  108. ;         Block size: 512 bytes       Check method: CRC
  109. ;    Transport Layer:  No          Download resume:  No
  110. ;      Upload Resume:  No         File information:  No
  111. ;
  112. ;       Data Quoting: <ETX> <ENQ> <DLE> <DC1> <DC3> and <NAK>
  113. ; ---------------------------------------------------------------------
  114.  
  115. tp_seq      db      ?                       ; sequence number
  116. tp_msg      db      "+", 0, 1, 4, 1, 1, 0   ; Transport parmameter pkt
  117. tp_msgq     db           14h, 0, 0d4h, 0    ; quoting level
  118.             db      $ETX
  119. tp_msg_len  =       $-tp_seq                ; Length of message
  120.  
  121. ; ---------------------------------------------------------------------
  122. ;  Data areas
  123. ; ---------------------------------------------------------------------
  124.  
  125. flgs        db      0                       ; various flags
  126. flgfnc      =       10000000b               ; 1... .... callback active
  127. flgrcv      =       01000000b               ; .1.. .... character rcv'd
  128. flgcan      =       00100000b               ; ..1. .... cancel req'd
  129. flgtmo      =       00010000b               ; ...1 .... timeout
  130. flgopen     =       00001000b               ; .... 1... file is open
  131. flgrec      =       00000100b               ; .... .1.. record available
  132.  
  133. bparea      label   byte                    ; internal BPAREA
  134. bpflg       db      0                       ; BPLUS flags
  135. bpfcrc      =       10000000b               ; 1... .... Use CRC checking
  136. bpfqut      =       01000000b               ; .1.. .... Next is quoted char
  137. bpseq       db      '0'                     ; current sequence number
  138. bpq         db      8 dup (0ffh)            ; default quoting set
  139.  
  140. ubp_area    dd      ?                       ; users' save area
  141. ubp_areao   equ     word ptr ubp_area       ; offset
  142. ubp_areas   equ     word ptr ubp_area+2     ; segment
  143.  
  144. bpqc00      db      32 dup (0)              ; 00h-1fh quoting
  145. bpqc80      db      32 dup (0)              ; 80h-9fh quoting
  146.  
  147. ticks       dw      ?                       ; entry nbr ticks
  148.  
  149. jmptab      dw      init                    ; 0: initialization call
  150.             dw      fncok                   ; 2: last function ok
  151.             dw      fncfail                 ; 4: last function failed
  152.             dw      commchar                ; 6: character received
  153.             dw      kbdchar                 ; 8: keystroke encountered
  154.  
  155. MAXCODE     =       8                       ; maximum entry code
  156.  
  157. CHRTMOUT    =       ((10*182)/10)           ; 10 second char timeout
  158. PKTTMOUT    =       ((25*182)/10)           ; 25 second char timeout
  159. MAXERRS     =       10                      ; maximum errors in row
  160.  
  161. errors      db      0                       ; error counter
  162.  
  163. filename    db      65 dup (0)              ; space for filename
  164.  
  165. packet      db      520 dup (?)             ; packet buffer
  166.  
  167. rcvaddr     dw      offset packet           ; address for next receive
  168.  
  169. ckbyte2     db      ?                       ; byte 2 of chk val (crc)
  170. ckbyte1     db      ?                       ; byte 1 (crc or cksum)
  171. crcval      equ     word ptr ckbyte2        ; .. to access it as a word
  172. chksumval   equ     byte ptr ckbyte1        ; .. to access it as a byte
  173.  
  174. oldds       dw      ?                       ; caller's ds
  175.  
  176. oldsp       dw      ?                       ; caller's sp
  177. oldss       dw      ?                       ; caller's ss
  178.  
  179. init2x      db      13, 'B+: Init called 2x', 13, 0
  180. badfnc      db      13, 'B+: Bad fnc code', 13, 0
  181. openerr     db      13, 'B+: Unable to open requested file', 13, 0
  182. timedout    db      13, 'B+: Timeout, protocol ended', 13, 0
  183. toomany     db      13, 'B+: Too many errors', 13, 0
  184. notinited   db      13, "B+: Not init'd first", 13, 0
  185. sendercan   db      13, 'B+: Download cancelled', 13, 0
  186. success     db      13, 'B+: Download completed OK', 13, 0
  187. writerr     db      13, 'B+: Aborted: write error', 13, 0
  188. openok      db      13, 'B+: Receiving ', 0
  189. alrdyopen   db      13, 'B+: File opened twice', 13, 0
  190. unknownpkt  db      13, 'B+: Unknown packet type', 13, 0
  191. noupload    db      13, "B+: Can't upload", 13, 0
  192. clsb4open   db      13, 'B+: Close before open', 13, 0
  193. staterr0    db      13, 'B+: Staterr 0', 13, 0
  194. staterr1    db      13, 'B+: Staterr 1', 13, 0
  195.  
  196. panicmsg    dw      7
  197.             db      10h, 10h, 10h, 10h, 10h, "++"
  198. ; ---------------------------------------------------------------------
  199. ;  Protocol Mainline
  200. ; ---------------------------------------------------------------------
  201.  
  202. bpmbplus    proc                            ; entry point
  203.             push    es                      ; save caller's regs
  204.             push    ds
  205.  
  206.             mov     cs:oldds, ds            ; keep copy of caller's ds
  207.  
  208.             mov     cs:oldss, ss            ; save caller's stack
  209.             mov     cs:oldsp, sp
  210.  
  211.             mov     cs:ticks, ax            ; save entry ticks
  212.  
  213.             mov     ax, cs                  ; ax -> our segment
  214.             mov     ds, ax                  ; ds -> our segment
  215.             mov     es, ax                  ; es -> our segment
  216.  
  217.             cli                             ; no interrupts ..
  218.             mov     ss, ax                  ; ss -> our segment
  219.             mov     sp, stackoffset         ; sp -> end of stack
  220.             sti                             ; .. allow ints again
  221.  
  222.             cmp     di, MAXCODE             ; q. is code ok?
  223.             ja      bpmbplus90              ; a. no .. return "done"
  224.  
  225.             test    di, 1                   ; q. is code even?
  226.             jnz     bpmbplus90              ; a. no .. return "done"
  227.  
  228.             jmp     jmptab[di]              ; .. call requested routine
  229.  
  230. bpmbplus90: lea     bx, badfnc              ; bx -> bad function code
  231.             jmp     proto_err               ; issue error and leave
  232.  
  233. bpmbplus    endp
  234.  
  235.  
  236. ; ---------------------------------------------------------------------
  237. ;   Initialization call;                 ds:bx -> operands (filename)
  238. ; ---------------------------------------------------------------------
  239.  
  240. init        proc
  241.  
  242.             cmp     state, $ST_INIT         ; q. already init'd?
  243.             je      init00                  ; a. no .. continue
  244.  
  245.             lea     bx, init2x              ; bx -> error message
  246.             jmp     proto_err               ; .. kill the protocol
  247.  
  248. init00:     mov     ubp_areao, si           ; save user's offset
  249.             push    oldds                   ; push user's ds
  250.             pop     ubp_areas               ; .. set bparea segment
  251.  
  252.             push    ds                      ; save our ds
  253.             lds     si, ubp_area            ; ds:si -> user's area
  254.             lea     di, bparea              ; di -> our bp area
  255.             mov     cx, 10                  ; cx = bytes to move
  256.             cld                             ; .. in upward direction
  257.       rep   movsb                           ; .. move it in.
  258.             pop     ds                      ; restore our ds
  259.  
  260.             lea     si, bpq                 ; si -> quote parameters
  261.             lea     di, bpqc00              ; di -> quote array
  262.             call    bd_setq                 ; setup quote array
  263.  
  264.             mov     state, $ST_DLE          ; set state to DLE SEEN
  265.             mov     bx, CHRTMOUT            ; bx = ticks to wait
  266.             call    setimer                 ; .. set the timer
  267.             jmp     proto_ok                ; .. return to caller
  268.  
  269. init        endp
  270.  
  271.  
  272. ; ---------------------------------------------------------------------
  273. ;  Last function executed ok -or- simple dispatch
  274. ;                                           flgfnc = 0: simple dispatch
  275. ;                                           fncfnc = 1: state return
  276. ;                                               -- Carry is cleared
  277. ; ---------------------------------------------------------------------
  278.  
  279. fncok       proc
  280.  
  281.             test    flgs, flgfnc            ; q. callback return?
  282.             jz      fncok05                 ; a. no .. dispatch
  283.  
  284.             clc                             ; show function succeeded
  285.             ret                             ; .. rtn to callback caller
  286.  
  287. fncok05:    cmp     state, $ST_INIT         ; q. init'd yet?
  288.             jne     fncok10                 ; a. yes .. continue
  289.  
  290.             lea     bx, notinited           ; bx -> not init'd msg
  291.             jmp     proto_err               ; .. kill the protocol
  292.  
  293. fncok10:    jmp     short check_rec         ; see if record received
  294.  
  295. fncok       endp
  296.  
  297.  
  298. ; ---------------------------------------------------------------------
  299. ;  Previous function failed                 Carry set to show failure
  300. ; ---------------------------------------------------------------------
  301.  
  302. fncfail     proc                            ; last function failed
  303.  
  304.             test    flgs, flgfnc            ; q. callback return?
  305.             jnz     fncfail10               ; a. yes .. continue
  306.  
  307.             lea     bx, staterr1            ; bx -> state error msg
  308.             jmp     proto_err               ; .. tell user & die
  309.  
  310. fncfail10:  stc                             ; set carry to show fail
  311.             ret                             ; return to callback caller
  312.  
  313. fncfail     endp
  314.  
  315. ; ---------------------------------------------------------------------
  316. ;  Process Communications Character         dl = character
  317. ; ---------------------------------------------------------------------
  318.  
  319. commchar    proc
  320.  
  321.             cmp     state, $ST_INIT         ; q. init'd yet?
  322.             jne     commchar05              ; a. yes .. continue
  323.  
  324.             lea     bx, notinited           ; bx -> not init'd msg
  325.             jmp     proto_err               ; .. kill the protocol
  326.  
  327. commchar05: test    flgs, flgfnc            ; q. callback return?
  328.             jz      commchar10              ; a. no .. continue
  329.  
  330.             lea     bx, staterr0            ; bx -> state error msg
  331.             jmp     proto_err               ; .. tell user & die
  332.  
  333. commchar10: mov     bx, rcvaddr             ; bx -> receive address
  334.             mov     [bx], dl                ; save received character
  335.  
  336.             or      flgs, flgrcv            ; show a char was received
  337.  
  338.             jmp     short check_rec         ; see if record received
  339.  
  340. commchar    endp
  341.  
  342.  
  343. ; ---------------------------------------------------------------------
  344. ;  Process keyboard character               dl = character
  345. ; ---------------------------------------------------------------------
  346.  
  347. kbdchar     proc
  348.  
  349.             cmp     state, $ST_INIT         ; q. init'd yet?
  350.             jne     kbdchar05               ; a. yes .. continue
  351.  
  352.             lea     bx, notinited           ; bx -> not init'd msg
  353.             jmp     proto_err               ; .. kill the protocol
  354.  
  355. kbdchar05:  test    flgs, flgfnc            ; q. callback return?
  356.             jz      kbdchar10               ; a. no .. continue
  357.  
  358.             lea     bx, staterr0            ; bx -> state error msg
  359.             jmp     proto_err               ; .. tell user & die
  360.  
  361. kbdchar10:  cmp     dx, 4F00H               ; q. END key?
  362.             jnz     kbdchar20               ; a. no .. skip it
  363.  
  364.             or      flgs, flgcan            ; show cancel requested.
  365.  
  366. kbdchar20:  jmp     short check_rec         ; see if record received
  367.  
  368. kbdchar     endp
  369.  
  370.  
  371. ; ---------------------------------------------------------------------
  372. ;  See if record received
  373. ; ---------------------------------------------------------------------
  374.  
  375. check_rec   proc
  376.  
  377.             call    state_exec              ; exec the state machine
  378.  
  379.             test    flgs, flgrec            ; q. record received?
  380.             jz      chk_rec90               ; a. no .. exit
  381.  
  382.             and     flgs, not flgrec        ; shut off indicator
  383.  
  384.             cmp     packet+1, '+'           ; q. transport parms?
  385.             jne     chk_rec10               ; a. no .. check next
  386.  
  387.             call    proc_tport              ; process transport rec
  388.             jmp     proto_ok                ; .. continue
  389.  
  390. chk_rec10:  cmp     packet+1, 'T'           ; q. transfer packet?
  391.             jne     chk_rec20               ; a. no .. check next
  392.  
  393.             call    proc_trec               ; process T record
  394.             jmp     proto_ok                ; .. continue
  395.  
  396. chk_rec20:  cmp     packet+1, 'N'           ; q. data packet?
  397.             jne     chk_rec30               ; a. no .. check next
  398.  
  399.             call    proc_nrec               ; process N record
  400.             jmp     proto_ok                ; .. continue
  401.  
  402. chk_rec30:  lea     bx, sendercan           ; else .. sender cancelled it
  403.  
  404.             cmp     packet+1, 'F'           ; q. failure packet?
  405.             je      chk_rec40               ; a. yes .. kill protocol
  406.  
  407.             lea     bx, unknownpkt          ; unknown packet type
  408.  
  409. chk_rec40:  call    panic                   ; panic abort!
  410.             jmp     proto_err               ; .. the the users
  411.  
  412. chk_rec90:  jmp     proto_ok                ; .. continue later
  413.  
  414. check_rec   endp
  415.  
  416.  
  417. ; ---------------------------------------------------------------------
  418. ;  Process transport (+) record
  419. ; ---------------------------------------------------------------------
  420.  
  421. proc_tport  proc
  422.  
  423.  
  424.  
  425.             lea     si, packet+8            ; point at quoting set
  426.             lea     di, bpq                 ; di -> quoting set
  427.             mov     cx, 4                   ; words to move
  428.             cld                             ; .. in upward direction
  429.        rep  movsw                           ; .. move in the quote set
  430.  
  431.             mov     al, packet+5            ; al = tp's crc flag
  432.             push    ax                      ; .. save on stack
  433.  
  434.             mov     al, packet              ; get his packet #
  435.             mov     bpseq, al               ; .. save it in ours
  436.  
  437.             call    nxtseq                  ; set next sequence nbr
  438.  
  439.             mov     al, bpseq               ; al =  next sequence no
  440.             mov     tp_seq, al              ; .. save in seq record
  441.  
  442.             lea     si, tp_seq              ; si -> our tport record
  443.             lea     di, packet              ; di -> send packet area
  444.             mov     cx, tp_msg_len          ; cx =  length o'packet
  445.             call    bd_setout               ; .. set up output
  446.  
  447.             pop     ax                      ; restore crc flag
  448.  
  449.             and     bpflg, not bpfcrc       ; assume checksum
  450.  
  451.             or      al, al                  ; q. use CRC?
  452.             jz      tport10                 ; a. no .. continue
  453.  
  454.             or      bpflg, bpfcrc           ; .. set on CRC
  455.  
  456. tport10:    mov     bx, di                  ; bx -> string to send
  457.             mov     di, 18                  ; di =  send 2cnt string
  458.             call    callback                ; .. send it out
  459.  
  460.             lea     si, bpq                 ; si -> quote parameters
  461.             lea     di, bpqc00              ; di -> quote array
  462.             call    bd_setq                 ; setup new quote array
  463.  
  464.             and     flgs, not flgtmo        ; reset timout
  465.             mov     bx, PKTTMOUT            ; .. use packet timout
  466.             call    setimer                 ; .. reset timer
  467.             mov     state, $ST_GETDLE       ; .. set next state
  468.  
  469.             ret                             ; .. and return to caller
  470.  
  471. proc_tport  endp
  472.  
  473.  
  474. ; ---------------------------------------------------------------------
  475. ;  Process T record
  476. ; ---------------------------------------------------------------------
  477.  
  478. proc_trec   proc
  479.  
  480.             cmp     packet+2, 'D'           ; q. send to us (download)?
  481.             jne     trec10                  ; a. no .. check next
  482.  
  483.             lea     bx, alrdyopen           ; file already open
  484.  
  485.             test    flgs, flgopen           ; q. file open?
  486.             jnz     trec06                  ; a. yes.. error
  487.  
  488.             lea     si, packet+4            ; si -> file name
  489.             lea     di, filename            ; di -> output area
  490.             cld                             ; .. address ascending
  491.  
  492. trec03:     lodsb                           ; al = filename char
  493.  
  494.             cmp     al, ' '                 ; q. above blank?
  495.             ja      trec05                  ; a. yes ..
  496.  
  497.             xor     al, al                  ; else .. clear al
  498.  
  499. trec05:     stosb                           ; .. put char in filename
  500.  
  501.             or      al, al                  ; q. end of filename?
  502.             jnz     trec03                  ; a. no .. continue
  503.  
  504.             lea     bx, filename            ; bx -> filename to open
  505.             mov     di, 2                   ; di = open a file
  506.             call    callback                ; ask for open
  507.             jnc     trec07                  ; .. continue protocol
  508.  
  509.             call    panic                   ; kill the protocol
  510.             lea     bx, openerr             ; bx -> open error msg
  511. trec06:     jmp     proto_err               ; .. die now
  512.  
  513. trec07:     lea     bx, openok              ; bx -> opened ok
  514.             mov     di, 12                  ; di = display ASCIIZ
  515.             call    callback                ; .. display the message
  516.  
  517.             lea     bx, filename            ; bx -> filename opened
  518.             mov     di, 12                  ; di = display ASCIIZ
  519.             call    callback                ; .. display the message
  520.  
  521.             mov     bl, $CR                 ; bx -> carriage return
  522.             mov     di, 14                  ; di = display character
  523.             call    callback                ; .. display the message
  524.  
  525.             call    nxtseq                  ; set next sequence number
  526.             call    bpsndack                ; .. ack the pack
  527.             or      flgs, flgopen           ; .. show file open
  528.             ret                             ; .. continue
  529.  
  530. trec10:     cmp     packet+2, 'C'           ; q. closing file?
  531.             jne     trec20                  ; a. no .. check next
  532.  
  533.             call    nxtseq                  ; get next sequence number
  534.             call    bpsndack                ; send an ack
  535.  
  536.             lea     bx, clsb4open           ; close before open
  537.  
  538.             test    flgs, flgopen           ; q. file open?
  539.             jz      trec90                  ; a. no .. error
  540.  
  541.             and     flgs, not flgopen       ; reset open flag
  542.             lea     bx, success             ; bx -> success
  543.             jmp     proto_err               ; .. return to caller
  544.  
  545. trec20:     lea     bx, noupload            ; bx -> no upload msg
  546.  
  547.             cmp     packet+3, 'U'           ; q. upload from us?
  548.             je      trec30                  ; a. no .. uh oh.
  549.  
  550.             lea     bx, unknownpkt          ; bx -> unknown packet type
  551.  
  552. trec30:     call    panic                   ; panic abort!
  553. trec90:     jmp     proto_err               ; .. tell the user
  554.  
  555. proc_trec   endp
  556.  
  557.  
  558. ; ---------------------------------------------------------------------
  559. ;  Process data packet
  560. ; ---------------------------------------------------------------------
  561.  
  562. proc_nrec   proc
  563.  
  564.             mov     cx, rcvaddr             ; cx = next rcv addr
  565.             sub     cx, offset packet       ; cx = len of packet
  566.             sub     cx, 3                   ; cx = len of data
  567.             jz      nrec10                  ; .. skip if no data
  568.             mov     word ptr packet, cx     ; .. save in packet
  569.  
  570.             lea     bx, packet              ; bx -> packet
  571.             mov     di, 4                   ; di =  write data
  572.             call    callback                ; q. write that data ok?
  573.             jc      nrec20                  ; a. yes .. continue
  574.  
  575. nrec10:     call    nxtseq                  ; .. set for next sequence
  576.             call    bpsndack                ; else .. send an ack
  577.             ret                             ; .. let it keep running
  578.  
  579. nrec20:     call    panic                   ; abort the protocol
  580.             lea     bx, writerr             ; bx -> write error message
  581.             jmp     proto_err               ; .. kill the protocol
  582.  
  583. proc_nrec   endp
  584.  
  585.  
  586. ; ---------------------------------------------------------------------
  587. ;  Run the state machine
  588. ; ---------------------------------------------------------------------
  589.  
  590. state_exec  proc
  591.  
  592.             cmp     ticks, 0                ; q. timeout on ticks?
  593.             jg      state10                 ; a. no .. continue
  594.  
  595.             or      flgs, flgtmo            ; timeout occurred
  596.  
  597. state10:    mov     bx, state               ; bx = state offset
  598.             call    state_jmp[bx]           ; .. go to appropriate state
  599.             jc      state10                 ; .. next state
  600.  
  601.             ret                             ; return to caller
  602.  
  603. state_exec  endp
  604.  
  605.  
  606.  
  607. ; ---------------------------------------------------------------------
  608. ;  State: Wait for DLE
  609. ; ---------------------------------------------------------------------
  610.  
  611. bpgetdle    proc
  612.  
  613.             test    flgs, flgcan            ; q. user cancel?
  614.             jz      bpgdle00                ; a. no .. continue
  615.  
  616.             call    panic                   ; panic abort
  617.             and     flgs, not flgcan        ; .. and shut off flag
  618.  
  619. bpgdle00:   test    flgs, flgrcv            ; q. character received?
  620.             jnz     bpgdle10                ; a. yes .. check it out
  621.  
  622.             mov     bx, PKTTMOUT            ; bx = packet timeout
  623.             call    chktimer                ; q. timeout?
  624.             jz      bpgdle05                ; a. no .. continue
  625.  
  626.             lea     bx, timedout            ; bx -> timeout message
  627.             jmp     chk_err                 ; see if too many errors
  628.  
  629. bpgdle05:   XSTATE                          ; .. exit the state machine
  630.  
  631. bpgdle10:   mov     bx, rcvaddr             ; bx -> received char
  632.             mov     al, [bx]                ; al = received char
  633.  
  634.             and     flgs, not flgrcv        ; reset receive flag
  635.  
  636.             cmp     al, $DLE                ; q. <DLE> seen?
  637.             je      bpgdle50                ; a. yes .. process it
  638.  
  639.             cmp     al, $ENQ                ; q. <ENQ> seen?
  640.             jne     bpgdle15                ; a. no .. continue
  641.  
  642.             NSTATE  $ST_SNDACK              ; else .. send an ACK
  643.  
  644. bpgdle15:   cmp     al, $NAK                ; q. <NAK> received?
  645.             jne     bpgdle20                ; a. no .. continue
  646.  
  647.             and     flgs, not flgtmo        ; bx -> protocol error msg
  648.             XSTATE                          ; .. stay in state
  649.  
  650. bpgdle20:   cmp     al, $ETX                ; q. ETX?
  651.             jne     bpgdle05                ; a. no .. continue
  652.  
  653.             NSTATE  $ST_SNDNAK              ; else .. send a NAK
  654.  
  655. bpgdle50:   mov     bx, CHRTMOUT            ; set character timout
  656.             call    setimer                 ; .. reset timer
  657.             mov     errors, 0               ; .. reset errors
  658.             and     flgs, not flgtmo        ; .. reset timout
  659.             XSTATE  $ST_DLE                 ; .. state = DLE seen
  660.  
  661. bpgetdle    endp
  662.  
  663.  
  664. ; ---------------------------------------------------------------------
  665. ;  State: DLE Seen
  666. ; ---------------------------------------------------------------------
  667.  
  668. bpdle       proc
  669.  
  670.             test    flgs, flgrcv            ; q. character received?
  671.             jnz     bpdle10                 ; a. yes .. check it out
  672.  
  673.             mov     bx, CHRTMOUT            ; bx = character timeout
  674.             call    chktimer                ; q. timeout?
  675.             jz      bpdle05                 ; a. no .. continue
  676.  
  677.             lea     bx, timedout            ; bx -> timeout message
  678.             jmp     chk_err                 ; see if too many errors
  679.  
  680. bpdle05:    XSTATE                          ; exit the state machine
  681.  
  682. bpdle10:    mov     bx, rcvaddr             ; bx -> received char
  683.             mov     al, [bx]                ; al = received char
  684.  
  685.             and     flgs, not flgrcv        ; .. shut off char rcvd
  686.  
  687.             cmp     al, 'B'                 ; q. <DLE> B seen?
  688.             je      bpdle50                 ; a. yes .. process it
  689.  
  690.             cmp     al, '0'                 ; q. possible ack?
  691.             jb      bpdle12                 ; a. no .. continue
  692.  
  693.             cmp     al, '9'                 ; q. is it an ACK?
  694.             ja      bpdle12                 ; a. no .. continue
  695.  
  696.             cmp     al, bpseq               ; q. it it THE ACK?
  697.             jne     bpdle15                 ; a. no .. continue
  698.  
  699.             jmp     short bpdle15           ; .. continue
  700.  
  701. bpdle12:    cmp     al, $ENQ                ; q. Enquiry?
  702.             jne     bpdle15                 ; a. no .. continue
  703.  
  704.             NSTATE  $ST_SNDACK              ; .. resend an ack
  705.  
  706. bpdle15:    mov     bx, PKTTMOUT            ; bx = packet timout
  707.             call    setimer                 ; .. set the timer
  708.             XSTATE  $ST_GETDLE              ; else .. get a DLE
  709.  
  710. bpdle50:    mov     bx, CHRTMOUT            ; bx = character timeout
  711.             call    setimer                 ; set timer to 10 sec
  712.             mov     errors, 0               ; reset errors
  713.             and     flgs, not flgtmo        ; reset timout
  714.             mov     rcvaddr, offset packet  ; address of sequence
  715.             XSTATE  $ST_DLEB                ; set next state
  716.  
  717. bpdle       endp
  718.  
  719.  
  720. ; ---------------------------------------------------------------------
  721. ;  State: <DLE> B seen
  722. ; ---------------------------------------------------------------------
  723.  
  724. bpdleb      proc
  725.  
  726.             test    flgs, flgrcv            ; q. character received?
  727.             jnz     bpdleb10                ; a. yes .. check it out
  728.  
  729.             mov     bx, CHRTMOUT            ; bx = character timeout
  730.             call    chktimer                ; q. timeout?
  731.             jz      bpdleb90                ; a. no .. continue
  732.  
  733.             NSTATE  $ST_SNDNAK              ; send a NAK
  734.  
  735. bpdleb10:   mov     bx, rcvaddr             ; bx -> received char
  736.             mov     al, [bx]                ; al = char received
  737.  
  738.             cmp     al, $ENQ                ; q. ENQ received?
  739.             jne     bpdleb20                ; a. no .. save character
  740.  
  741.             XSTATE  $ST_SNDACK              ; send an ACK
  742.  
  743. bpdleb20:   call    charcvd                 ; receive the char
  744.  
  745.             and     flgs, not flgtmo        ; reset any timeout
  746.             mov     bx, CHRTMOUT            ; .. set for char timeout
  747.             call    setimer                 ; .. reset the timer
  748.             mov     errors, 0               ; .. reset error counter
  749.             XSTATE  $ST_GETDATA             ; .. state = get data
  750.  
  751. bpdleb90:   XSTATE                          ; .. continue
  752.  
  753. bpdleb      endp
  754.  
  755.  
  756. ; ---------------------------------------------------------------------
  757. ;  State: Get data
  758. ; ---------------------------------------------------------------------
  759.  
  760. bpgetdata   proc
  761.  
  762.             test    flgs, flgrcv            ; q. character received?
  763.             jnz     bpgdat10                ; a. yes .. check it out
  764.  
  765.             mov     bx, CHRTMOUT            ; bx = character timeout
  766.             call    chktimer                ; q. timeout?
  767.             jz      bpdleb90                ; a. no .. continue
  768.  
  769.             NSTATE  $ST_SNDNAK              ; send a NAK
  770.  
  771. bpgdat10:   mov     bx, rcvaddr             ; bx -> received char
  772.             mov     al, [bx]                ; al = char received
  773.  
  774.             test    bpflg, bpfqut           ; q. awaiting quoted?
  775.             jz      bpgdat20                ; a. no .. continue
  776.  
  777.             cmp     al, 60h                 ; q. upper set?
  778.             pushf                           ; .. save results
  779.  
  780.             and     al, 1fh                 ; set off upper bits
  781.  
  782.             popf                            ; q. add 80 hex?
  783.             jb      bpgdat15                ; a. no .. leave as is.
  784.  
  785.             add     al, 80h                 ; else .. 80h-9fh
  786.  
  787. bpgdat15:   mov     [bx], al                ; save unquoted char
  788.             and     bpflg, not bpfqut       ; .. shut off quoting
  789.             jmp     short bpgdat85          ; .. and continue protocol
  790.  
  791. bpgdat20:   cmp     al, $DLE                ; q. quoted char?
  792.             jne     bpgdat25                ; a. no .. continue
  793.  
  794.             and     flgs, not flgrcv        ; set off received flag
  795.             or      bpflg, bpfqut           ; .. and set on quoted flag
  796.             jmp     short bpgdat90          ; .. and continue
  797.  
  798. bpgdat25:   cmp     al, $ETX                ; q. ETX received?
  799.             jne     bpgdat30                ; a. no .. check next
  800.  
  801.             call    charcvd                 ; save the ETX
  802.             mov     state, $ST_GETCKS       ; get first byte of check
  803.             jmp     short bpgdat90          ; .. continue processing
  804.  
  805. bpgdat30:   cmp     al, $ENQ                ; q. ENQ received?
  806.             jne     bpgdat85                ; a. no .. received char
  807.  
  808.             mov     state, $ST_SNDACK       ; .. send out an ack
  809.             jmp     short bpgdat90          ; .. and continue
  810.  
  811. bpgdat85:   call    charcvd                 ; .. and process it
  812.  
  813. bpgdat90:   and     flgs, not flgtmo        ; reset timeout
  814.             mov     bx, CHRTMOUT            ; .. set to CHAR timout
  815.             call    setimer                 ; .. reset the timer
  816.             XSTATE                          ; .. and continue
  817.  
  818. bpgetdata   endp
  819.  
  820.  
  821.  
  822. ; ---------------------------------------------------------------------
  823. ;  Wait for checksum char
  824. ; ---------------------------------------------------------------------
  825.  
  826. bpgetcks    proc
  827.  
  828.             test    flgs, flgrcv            ; q. character received?
  829.             jnz     bpgcks10                ; a. yes .. check it out
  830.  
  831.             mov     bx, CHRTMOUT            ; bx = character timeout
  832.             call    chktimer                ; q. timeout?
  833.             jz      bpgcks90                ; a. no .. continue
  834.  
  835.             XSTATE  $ST_SNDNAK              ; send a NAK
  836.  
  837. bpgcks10:   mov     bx, rcvaddr             ; bx -> received char
  838.             mov     al, [bx]                ; al = char received
  839.  
  840.             test    bpflg, bpfqut           ; q. quoting active?
  841.             jz      bpgcks50                ; a. no .. check/save char
  842.  
  843.             and     bpflg, not bpfqut       ; .. reset quoting flag
  844.  
  845.             cmp     al, 60h                 ; q. 80-9f range?
  846.             pushf                           ; .. save the answer
  847.  
  848.             and     al, 1fh                 ; .. upper bits off
  849.  
  850.             popf                            ; .. restore answer ..
  851.             jb      bpgcks70                ; a. no .. store as is
  852.  
  853.             add     al, 80h                 ; else.. reconstitute 80-9f
  854.             jmp     short bpgcks70          ; .. and save it
  855.  
  856. bpgcks50:   cmp     al, $DLE                ; q. quoted char?
  857.             jne     bpgcks70                ; a. no .. continue
  858.  
  859.             and     flgs, not flgrcv        ; "receive" the quote
  860.             or      bpflg, bpfqut           ; show quoted char expected
  861.             XSTATE                          ; .. and say in state
  862.  
  863. bpgcks70:   and     flgs, not flgrcv        ; show byte processed
  864.             mov     ckbyte1, al             ; save as checksum
  865.  
  866.             mov     state, $ST_GETCRC       ; .. assume CRC checking
  867.  
  868.             test    bpflg, bpfcrc           ; q. using CRC?
  869.             jnz     bpgcks90                ; a. yes .. continue
  870.  
  871.             NSTATE  $ST_VERCKS              ; else .. verify checksum
  872.  
  873. bpgcks90:   XSTATE                          ; .. continue
  874.  
  875. bpgetcks    endp
  876.  
  877. ; ---------------------------------------------------------------------
  878. ;  Wait for CRC character
  879. ; ---------------------------------------------------------------------
  880.  
  881. bpgetcrc    proc
  882.  
  883.             test    flgs, flgrcv            ; q. character received?
  884.             jnz     bpgcrc10                ; a. yes .. check it out
  885.  
  886.             mov     bx, CHRTMOUT            ; bx = character timeout
  887.             call    chktimer                ; q. timeout?
  888.             jz      bpgcrc90                ; a. no .. continue
  889.  
  890.             XSTATE  $ST_SNDNAK              ; send a NAK
  891.  
  892. bpgcrc10:   mov     bx, rcvaddr             ; bx -> received char
  893.             mov     al, [bx]                ; al = char received
  894.  
  895.             test    bpflg, bpfqut           ; q. quoting active?
  896.             jz      bpgcrc50                ; a. no .. check/save char
  897.  
  898.             and     bpflg, not bpfqut       ; .. reset quoting flag
  899.  
  900.             cmp     al, 60h                 ; q. 80-9f range?
  901.             pushf                           ; .. save the answer
  902.  
  903.             and     al, 1fh                 ; .. upper bits off
  904.  
  905.             popf                            ; .. restore answer ..
  906.             jb      bpgcrc70                ; a. no .. store as is
  907.  
  908.             add     al, 80h                 ; else.. reconstitute 80-9f
  909.             jmp     short bpgcrc70          ; .. and save it
  910.  
  911. bpgcrc50:   cmp     al, $DLE                ; q. quoted char?
  912.             jne     bpgcrc70                ; a. no .. continue
  913.  
  914.             and     flgs, not flgrcv        ; "receive" the quote
  915.             or      bpflg, bpfqut           ; show quoted char expected
  916.             XSTATE                          ; .. and say in state
  917.  
  918. bpgcrc70:   and     flgs, not flgrcv        ; show byte processed
  919.             mov     ckbyte2, al             ; save as CRC byte 2
  920.             NSTATE  $ST_VERCRC              ; .. assume CRC checking
  921.  
  922. bpgcrc90:   XSTATE                          ; .. continue
  923.  
  924. bpgetcrc    endp
  925.  
  926.  
  927. ; ---------------------------------------------------------------------
  928. ;  Verify Checksum
  929. ; ---------------------------------------------------------------------
  930.  
  931. bpvercks    proc
  932.  
  933.             lea     si, packet              ; si -> packet
  934.             mov     cx, rcvaddr             ; cx -> next to receive
  935.             sub     cx, si                  ; cx =  length to check
  936.  
  937.             call    bpcksum                 ; dx = calc'd chksum
  938.  
  939.             cmp     dl, chksumval           ; q. does it match?
  940.             je      bpvercks90              ; a. yes .. exit AOK!
  941.  
  942.             XSTATE  $ST_SNDNAK              ; else .. send a NAK
  943.  
  944. bpvercks90: NSTATE  $ST_VERPKT              ; .. continue
  945.  
  946. bpvercks    endp
  947.  
  948.  
  949.  
  950. ; ---------------------------------------------------------------------
  951. ;  Verify CRC
  952. ; ---------------------------------------------------------------------
  953.  
  954. bpvercrc    proc
  955.  
  956.             lea     si, packet              ; si -> packet
  957.             mov     cx, rcvaddr             ; cx -> next to receive
  958.             sub     cx, si                  ; cx =  length to check
  959.  
  960.             call    bpcrc                   ; dl = calc'd crc
  961.  
  962.             cmp     dx, crcval              ; q. does it match?
  963.             je      bpvercrc90              ; a. yes .. exit AOK!
  964.  
  965.             XSTATE  $ST_SNDNAK              ; else .. send a NAK
  966.  
  967. bpvercrc90: NSTATE  $ST_VERPKT              ; .. continue
  968.  
  969. bpvercrc    endp
  970.  
  971.  
  972. ; ---------------------------------------------------------------------
  973. ;  Verify packet
  974. ; ---------------------------------------------------------------------
  975.  
  976. bpverpkt    proc
  977.  
  978.             mov     al, packet              ; al = sequence number
  979.  
  980.             mov     ah, bpseq               ; ah = last good sequence
  981.             inc     ah                      ; ah = next seq number
  982.  
  983.             cmp     ah, '9'                 ; q. did seq wrap?
  984.             jna     bpverpkt05              ; a. no .. continue
  985.  
  986.             mov     ah, '0'                 ; ah = next packet number
  987.  
  988. bpverpkt05: cmp     al, ah                  ; q. expected number?
  989.             jne     bpverpkt10              ; a. no .. check it out
  990.  
  991.             mov     errors, 0               ; reset error count
  992.             or      flgs, flgrec            ; show record received
  993.             XSTATE  $ST_SNDACK              ; else .. exit the state
  994.  
  995. bpverpkt10: cmp     packet+1, 'F'           ; q. Fail packet?
  996.             jne     bpverpkt20              ; a. no .. continue
  997.  
  998.             or      flgs, flgrec            ; show record received
  999.             XSTATE                          ; else .. exit the state
  1000.  
  1001. bpverpkt20: cmp     al, bpseq               ; q. previous packet?
  1002.             jne     bpverpkt40              ; a. no .. NAK it
  1003.  
  1004.             NSTATE  $ST_SNDACK              ; .. ack the pak
  1005.  
  1006. bpverpkt40: NSTATE  $ST_SNDNAK              ; .. nak that pak!
  1007.  
  1008. bpverpkt    endp
  1009.  
  1010.  
  1011. ; ---------------------------------------------------------------------
  1012. ;  Send an ACK
  1013. ; ---------------------------------------------------------------------
  1014.  
  1015. bpsndack    proc
  1016.  
  1017.             mov     bl, $DLE                ; bl = DLE
  1018.             mov     di, 20                  ; di = send one char
  1019.             call    callback                ; .. ask BD to do it
  1020.  
  1021.             mov     bl, bpseq               ; bl = sequence number
  1022.             mov     di, 20                  ; di = send one char
  1023.             call    callback                ; .. ask BD to do it
  1024.  
  1025.             mov     bl, '.'                 ; bl = I'm alive char
  1026.             mov     di, 14                  ; di = display one char
  1027.             call    callback                ; .. ask BD to do it
  1028.  
  1029.             mov     bx, PKTTMOUT            ; set packet timeout
  1030.             call    setimer                 ; set the timer
  1031.             and     flgs, not flgtmo        ; .. reset timeout
  1032.             mov     rcvaddr, offset packet  ; .. reset the receive addr
  1033.             XSTATE  $ST_GETDLE              ; get a DLE
  1034.  
  1035. bpsndack    endp
  1036.  
  1037.  
  1038. ; ---------------------------------------------------------------------
  1039. ;  Send a NAK
  1040. ; ---------------------------------------------------------------------
  1041.  
  1042. bpsndnak    proc
  1043.  
  1044.             cmp     errors, MAXERRS         ; q. too many errors?
  1045.             jb      bpsndnak10              ; a. no .. continue
  1046.  
  1047.             lea     bx, toomany             ; bx -> too many errors msg
  1048.             jmp     proto_err               ; .. exit the protocol
  1049.  
  1050. bpsndnak10: mov     bl, $NAK                ; bl = NAK
  1051.             mov     di, 20                  ; di = send one char
  1052.             call    callback                ; .. ask BD to do it
  1053.  
  1054.             mov     bl, 'X'                 ; bl = I'm nakking char
  1055.             mov     di, 14                  ; di = display one char
  1056.             call    callback                ; .. ask BD to do it
  1057.  
  1058.             mov     bx, PKTTMOUT            ; set packet timeout
  1059.             call    setimer                 ; set the timer
  1060.             and     flgs, not flgtmo        ; .. reset timeout
  1061.             mov     rcvaddr, offset packet  ; .. reset the receive addr
  1062.             XSTATE  $ST_GETDLE              ; get a DLE
  1063.  
  1064. bpsndnak    endp
  1065.  
  1066.  
  1067. ; ---------------------------------------------------------------------
  1068. ;  Send a panic abort
  1069. ; ---------------------------------------------------------------------
  1070.  
  1071. panic       proc
  1072.  
  1073.             push    bx                      ; save caller's bx
  1074.  
  1075.             lea     bx, panicmsg            ; bx -> panic stop msg
  1076.             mov     di, 18                  ; di = send one char
  1077.             call    callback                ; .. ask BD to do it
  1078.  
  1079.             pop     bx                      ; restore caller's bx
  1080.             ret                             ; return to caller
  1081.  
  1082. panic       endp
  1083.  
  1084.  
  1085. ; ---------------------------------------------------------------------
  1086. ;  Check for timeout                        non-zero = timeout
  1087. ; ---------------------------------------------------------------------
  1088.  
  1089. chktimer    proc
  1090.  
  1091.             test    flgs, flgtmo            ; set zf if no timeout
  1092.             pushf                           ; save flags
  1093.             jz      chktimer10              ; .. jump if no timeout
  1094.  
  1095.             call    setimer                 ; set 10 second value
  1096.  
  1097. chktimer10: popf                            ; restore test results
  1098.             ret                             ; .. return to caller
  1099.  
  1100. chktimer    endp
  1101.  
  1102.  
  1103. ; ---------------------------------------------------------------------
  1104. ;  Set timer to 10 second timeout           bx = ticks to wait
  1105. ; ---------------------------------------------------------------------
  1106.  
  1107. setimer     proc
  1108.  
  1109.             mov     di, 22                  ; di = set tick downcounter
  1110.             call    callback                ; .. have BD do it
  1111.  
  1112.             ret                             ; .. return to caller
  1113.  
  1114. setimer    endp
  1115.  
  1116.  
  1117. ; ---------------------------------------------------------------------
  1118. ;  Check errors                             bx -> error message
  1119. ; ---------------------------------------------------------------------
  1120.  
  1121. chk_err     proc
  1122.  
  1123.             inc     errors                  ; add one to errors
  1124.  
  1125.             cmp     errors, MAXERRS         ; q. too many errors?
  1126.             jb      chk_err10               ; a. no .. continue
  1127.  
  1128.             jmp     proto_err               ; .. kill the protocol
  1129.  
  1130. chk_err10:  XSTATE                          ; .. continue the protocol
  1131.  
  1132. chk_err     endp
  1133.  
  1134.  
  1135. ; ---------------------------------------------------------------------
  1136. ;  Show received character processed
  1137. ; ---------------------------------------------------------------------
  1138.  
  1139. charcvd     proc
  1140.  
  1141.             and     flgs, not flgrcv        ; shut off receive bit
  1142.             inc     rcvaddr                 ; point to next address
  1143.  
  1144.             ret                             ; return to caller
  1145.  
  1146. charcvd     endp
  1147.  
  1148.  
  1149. ; ----------------------------------------------------------------------
  1150. ;   Calculate standard B protocol checksum
  1151. ;
  1152. ;   entry: si -> block to check
  1153. ;          cx =  length
  1154. ;    exit: dl =  checksum
  1155. ; ----------------------------------------------------------------------
  1156.  
  1157. bpcksum     proc
  1158.  
  1159.             push    cx                      ; save register
  1160.  
  1161.             xor     ah, ah                  ; ah = zero for additions
  1162.             xor     dx, dx                  ; dx = zero for accumulator
  1163.  
  1164. bpcksum10:  shl     dx, 1                   ; dx = shifted left by 1
  1165.  
  1166.             cmp     dx, 0ffh                ; q. over 255?
  1167.             jle     bpcksum20               ; a. no .. continue
  1168.  
  1169.             and     dx, 0ffh                ; dx = less than 255
  1170.             inc     dx                      ; ..plus one
  1171.  
  1172. bpcksum20:  lodsb                           ; al = char from buffer
  1173.             add     dx, ax                  ; dx = acculation of chars
  1174.  
  1175.             cmp     dx, 0ffh                ; q. over 255?
  1176.             jle     bpcksum30               ; a. no .. continue
  1177.  
  1178.             and     dx, 0ffh                ; dx = less than 255
  1179.             inc     dx                      ; ..plus one
  1180.  
  1181. bpcksum30:  loop    bpcksum10               ; loop back till done
  1182.             pop     cx                      ; ..restore register
  1183.             ret                             ; ..then return to caller
  1184.  
  1185. bpcksum     endp
  1186.  
  1187.  
  1188. ; ----------------------------------------------------------------------
  1189. ;   Calculate CRC           entry: si -> message block
  1190. ;                                  cx =  length of message
  1191. ;                            exit: dx =  returned CRC
  1192. ; ----------------------------------------------------------------------
  1193.  
  1194. bpcrc       proc
  1195.  
  1196.             push    bx                      ; save registers
  1197.             push    cx
  1198.             push    di
  1199.  
  1200.             mov     dx, -1                  ; dx = initialize crc
  1201.             mov     bx, 1021h               ; bx = working constant
  1202.             mov     di, 8000h               ; di = constant, too
  1203.  
  1204. bpcrc10:    lodsb                           ; al = char from message
  1205.             xor     ah, ah                  ; ax = cast char as integer
  1206.             xchg    al, ah                  ; shift left char by 8
  1207.             xor     dx, ax                  ; crc ^= (int)*ptr++ << 8
  1208.  
  1209.             push    cx                      ; save register
  1210.             mov     cx, 8                   ; cx = bit loop count
  1211.  
  1212. bpcrc20:    mov     ax, dx                  ; ax = temp copy of crc
  1213.  
  1214.             and     ax, di                  ; q. bit on?
  1215.             jz      bpcrc30                 ; a. no .. continue
  1216.  
  1217.             shl     dx, 1                   ; shift left by one bit
  1218.             xor     dx, bx                  ; crc = crc << 1 ^ 0x1021
  1219.             jmp     short bpcrc40           ; ..continue with common code
  1220.  
  1221. bpcrc30:    shl     dx, 1                   ; crc <<= 1
  1222.  
  1223. bpcrc40:    loop    bpcrc20                 ; ..just loop thru this byte
  1224.  
  1225.             pop     cx                      ; restore register
  1226.             loop    bpcrc10                 ; ..and loop thru whole message
  1227.  
  1228.             pop     di                      ; restore registers
  1229.             pop     cx
  1230.             pop     bx
  1231.  
  1232.             ret                             ; return to caller
  1233.  
  1234. bpcrc       endp
  1235.  
  1236.  
  1237. ; ----------------------------------------------------------------------
  1238. ;   Setup output field
  1239. ;       - with count
  1240. ;       - DLE + "B"
  1241. ;       - move in data, applying quouting rules
  1242. ;       - call CRC/cksum routines
  1243. ;
  1244. ;   entry: si -> user data w/terminating ETX
  1245. ;          di -> destination area
  1246. ;          cx =  length
  1247. ;    exit: di -> 2byte length + data + CRC/cksum
  1248. ; ----------------------------------------------------------------------
  1249.  
  1250. bd_setout   proc
  1251.  
  1252.             push    di                      ; save registers
  1253.             xor     bx, bx                  ; bx = extra DLE bytes added
  1254.             mov     ax, cx                  ; get copy of length
  1255.             stosw                           ; store in output record
  1256.  
  1257.             push    si                      ; save registers
  1258.             test    bpflg, bpfcrc           ; q. using CRC?
  1259.             jz      bd_seto20               ; a. no .. calculate chksum
  1260.  
  1261.             call    bpcrc                   ; dx = CRC of the data
  1262.             add     bx, 2                   ; bx = 2 extra bytes
  1263.             jmp     short bd_seto30         ; ..continue w/common code
  1264.  
  1265. bd_seto20:  call    bpcksum                 ; dl = checksum of data
  1266.             inc     bx                      ; bx = 1 extra byte
  1267.  
  1268. bd_seto30:  pop     si                      ; restore register
  1269.             push    dx                      ; save CRC/checksum
  1270.             mov     ax, 4210h               ; ax = DLE + "B"
  1271.             stosw                           ; save in output record
  1272.             add     bx, 2                   ; bx = 2 more bytes
  1273.             mov     dx, bx                  ; dx = extra length, now
  1274.             dec     cx                      ; cx = len - 1, for ETX's sake
  1275.  
  1276. bd_seto40:  lodsb                           ; al = source byte
  1277.  
  1278.             cmp     al, 1fh                 ; q. in the 1st range?
  1279.             ja      bd_seto50               ; a. no .. continue
  1280.  
  1281.             xor     ah, ah                  ; ax = (int) source byte
  1282.             mov     bx, ax                  ; bx = index into quote array
  1283.  
  1284.             cmp     bpqc00[bx], 0           ; q. need to quote char?
  1285.             je      bd_seto70               ; a. no .. continue
  1286.  
  1287.             add     al, 40h                 ; al = quoted character
  1288.             jmp     short bd_seto60         ; ..do rest of quoting stuff
  1289.  
  1290. bd_seto50:  cmp     al, 80h                 ; q. maybe in 2nd range?
  1291.             jb      bd_seto70               ; a. no .. normal character
  1292.  
  1293.             cmp     al, 9fh                 ; q. really in 2nd range?
  1294.             ja      bd_seto70               ; a. no .. must be normal
  1295.  
  1296.             and     al, 1fh                 ; al = 00 - 1fh
  1297.             xor     ah, ah                  ; ax = (int) source byte
  1298.             mov     bx, ax                  ; bx = index into quote array
  1299.  
  1300.             cmp     bpqc80[bx], 0           ; q. need to quote char?
  1301.             je      bd_seto70               ; a. no .. continue
  1302.  
  1303.             add     al, 60h                 ; al = quoted character
  1304. bd_seto60:  mov     ah, 10h                 ; ah = DLE
  1305.             xchg    al, ah                  ; swap around for store
  1306.             stosw                           ; ..save in output record
  1307.             inc     dx                      ; dx = one more extra char
  1308.             jmp     short bd_seto80         ; ..continue w/common code
  1309.  
  1310. bd_seto70:  stosb                           ; save char in output area
  1311. bd_seto80:  loop    bd_seto40               ; ..then loop till done
  1312.  
  1313.             movsb                           ; copy ETX to output area
  1314.             pop     ax                      ; ax = CRC/checksum
  1315.             stosw                           ; save one or the other
  1316.  
  1317.             pop     di                      ; di -> output count
  1318.             add     [di], dx                ; add in "extra" bytes cnt
  1319.             ret                             ; ..finally, return to caller
  1320.  
  1321. bd_setout   endp
  1322.  
  1323.  
  1324. ; ----------------------------------------------------------------------
  1325. ;   Unroll set quote mode fields
  1326. ;
  1327. ;   entry: si -> source field of 8 bytes
  1328. ;          di -> destination field of 64 bytes
  1329. ; ----------------------------------------------------------------------
  1330.  
  1331. bd_setq     proc
  1332.  
  1333.             mov     cx, 8                   ; cx = big loop size
  1334.  
  1335. bd_setq10:  push    cx                      ; save outer loop size
  1336.             mov     cx, 8                   ; cx = bits per byte
  1337.             lodsb                           ; al = source byte
  1338.             mov     ah, al                  ; ah = work value
  1339.  
  1340. bd_setq20:  test    ah, 80h                 ; q. bit set?
  1341.             jz      bd_setq30               ; a. no .. clear dest byte
  1342.  
  1343.             mov     al, 0ffh                ; al = true value
  1344.             jmp     short bd_setq40         ; ..continue w/common code
  1345.  
  1346. bd_setq30:  xor     al, al                  ; al = false value
  1347.  
  1348. bd_setq40:  stosb                           ; save in destination array
  1349.             shl     ah, 1                   ; ah = next bit to test
  1350.             loop    bd_setq20               ; ..loop till byte done
  1351.  
  1352.             pop     cx                      ; restore outer loop count
  1353.             loop    bd_setq10               ; ..loop till array finished
  1354.  
  1355.             ret                             ; ..finally, return to caller
  1356.  
  1357. bd_setq     endp
  1358.  
  1359. ; ---------------------------------------------------------------------
  1360. ;  Set bpseq to next sequence number
  1361. ; ---------------------------------------------------------------------
  1362.  
  1363. nxtseq      proc
  1364.  
  1365.             inc     bpseq                   ; increment seq number
  1366.  
  1367.             cmp     bpseq, '9'              ; q. rollover?
  1368.             jna     nxtseq90                ; a. no .. exit
  1369.  
  1370.             mov     bpseq, '0'              ; .. else return to '0'
  1371.  
  1372. nxtseq90:   ret                             ; .. return to caller
  1373.  
  1374. nxtseq      endp
  1375.  
  1376. ; ---------------------------------------------------------------------
  1377. ;  Setup to "call" backdown                 di = return code
  1378. ; ---------------------------------------------------------------------
  1379.  
  1380. callback    proc
  1381.  
  1382.             or      flgs, flgfnc            ; show were in callback mode
  1383.  
  1384.             jmp     short proto_exit        ; return to caller
  1385.  
  1386. callback    endp
  1387.  
  1388.  
  1389. ; ---------------------------------------------------------------------
  1390. ;  Display error, return done               bx -> string
  1391. ; ---------------------------------------------------------------------
  1392.  
  1393. proto_err   proc
  1394.  
  1395.             mov     di, 12                  ; di = display string
  1396.             call    callback                ; .. display it
  1397.  
  1398.             jmp     short proto_done        ; tell bd we are done
  1399.  
  1400. proto_err   endp
  1401.  
  1402.  
  1403. ; ---------------------------------------------------------------------
  1404. ;  Protocol done - leave forever
  1405. ; ---------------------------------------------------------------------
  1406.  
  1407. proto_done  proc
  1408.  
  1409.             push    ds                      ; save our ds
  1410.             les     di, ubp_area            ; es:di -> caller' area
  1411.             lea     si, bparea              ; ds:di -> our area
  1412.             mov     cx, 5                   ; words to move
  1413.             cld                             ; ascending
  1414.       rep   movsw                           ; .. return 'em to user
  1415.             pop     ds                      ; restore our DS
  1416.  
  1417.             mov     di, 10                  ; di = done code
  1418.  
  1419.             jmp     short proto_exit        ; leave the protocol
  1420.  
  1421. proto_done  endp
  1422.  
  1423.  
  1424. ; ---------------------------------------------------------------------
  1425. ;  Exit with the OK code
  1426. ; ---------------------------------------------------------------------
  1427.  
  1428. proto_ok    proc
  1429.  
  1430.             and     flgs, not flgfnc        ; zero out the function flag
  1431.  
  1432.             mov     di, 0                   ; di = ok return code
  1433.  
  1434.             jmp     short proto_exit        ; restore regs & exit
  1435.  
  1436. proto_ok    endp
  1437.  
  1438.  
  1439. ; ---------------------------------------------------------------------
  1440. ;  Protcol exit routine
  1441. ; ---------------------------------------------------------------------
  1442.  
  1443. proto_exit  proc
  1444.  
  1445.             mov     stackoffset, sp         ; save our stack offset
  1446.  
  1447.             cli                             ; no interrupts
  1448.             mov     ss, oldss               ; ..restore callers ss
  1449.             mov     sp, oldsp               ; ..and sp
  1450.             sti                             ; ints ok again
  1451.  
  1452.             pop     ds                      ; restore caller's regs
  1453.             pop     es
  1454.  
  1455.             FARRET                          ; return to caller
  1456.  
  1457. proto_exit  endp
  1458.  
  1459. protocol    ends
  1460.             end     start
  1461.  
  1462.