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

  1.             page    55,132
  2.             title   "BXMODM - XMODEM 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'      ; Ascii module
  15.             assume  cs:protocol
  16.  
  17. start:      jmp     bpmxmodem               ; jump to start
  18.             db      "BD"                    ; backdown protocol ID
  19.  
  20.             db      2                       ; number of protcols
  21.  
  22.             db      "X"                     ; invocation letter
  23.             db      "Xmodem V1.0     ", 0   ; name to display
  24.             db      1                       ; protocol number
  25.  
  26.             db      "C"                     ; invocation letter
  27.             db      "Xmodem/CRC V1.0 ", 0   ; name to display
  28.             db      2                       ; protocol number
  29.  
  30.  
  31. ; --------------------------------------------------------------------
  32. ;  Macro(s)
  33. ; --------------------------------------------------------------------
  34.  
  35. FARRET      macro                           ; far return macro
  36.             db      0cbh
  37.             endm
  38.  
  39. ; ---------------------------------------------------------------------
  40. ;  Protocol characters equates
  41. ; ---------------------------------------------------------------------
  42.  
  43. $SOH        =       1                       ; First byte of packets
  44. $EOT        =       4                       ; Last byte of packet
  45. $ACK        =       6                       ; Positive acknowledgement
  46. $NAK        =       21                      ; Negative acknowledgement
  47. $CAN        =       24                      ; Cancel transmission
  48.  
  49. ; ---------------------------------------------------------------------
  50. ;  Local stack
  51. ; ---------------------------------------------------------------------
  52.  
  53.             even
  54. bpmstack    db      32 dup ("St")           ; local stack area
  55. bpmstackend db      "Es"                    ; End of local stack
  56.  
  57. stackoffset dw      offset bpmstackend      ; New stack pointer
  58.  
  59. ; ---------------------------------------------------------------------
  60. ;  State definitions
  61. ; ---------------------------------------------------------------------
  62.  
  63. $ST_INIT    =       -1                      ; Awaiting initialization
  64. $ST_SOH     =       0                       ; Awaiting - between pkts
  65. $ST_EOP     =       2                       ; Awaiting end of packet
  66. $ST_CAN     =       4                       ; Cancelling protocol
  67. $ST_UCAN    =       6                       ; User cancelled protocol
  68.  
  69. state       dw      $ST_INIT                ; current state
  70.  
  71. state_jmp   dw      xmsoh                   ;  0: Awaiting SOH
  72.             dw      xmeop                   ;  2: Awaiting end of pkt
  73.             dw      xmcan                   ;  4: cancel
  74.             dw      xmucan                  ;  6: user cancel
  75.  
  76.  
  77. ; ---------------------------------------------------------------------
  78. ;  Data areas
  79. ; ---------------------------------------------------------------------
  80.  
  81. flgs        db      0                       ; various flags
  82. flgfnc      =       80h                     ; 1... .... callback active
  83. flgrcv      =       40h                     ; .1.. .... character rcv'd
  84. flgcan      =       20h                     ; ..1. .... cancel req'd
  85. flgnrm      =       10h                     ; ...1 .... normal XMODEM
  86. flgsoh      =       08h                     ; .... 1... first SOH rcvd
  87.  
  88. ticks       dw      ?                       ; entry nbr ticks
  89.  
  90. jmptab      dw      init                    ; 0: initialization call
  91.             dw      fncok                   ; 2: last function ok
  92.             dw      fncfail                 ; 4: last function failed
  93.             dw      commchar                ; 6: character received
  94.             dw      kbdchar                 ; 8: keystroke encountered
  95.  
  96. MAXCODE     =       8                       ; maximum entry code
  97.  
  98. ONESEC      =       19                      ; A solid 1 sec in ticks
  99.  
  100. CHRTMOUT    =       12                      ; 12 second char timeout
  101. CANTMOUT    =       2                       ; 2 seconds for char timout
  102. MAXERRS     =       10                      ; maximum errors in row
  103. SOHTMOUT    =       22                      ; Timeout for inter-packet NAK's
  104.                                             ; Initial NAK to first SOH
  105.  
  106. timer       db      SOHTMOUT                ; Timeout after first NAK
  107.  
  108. nseq        db      1                       ; next sequence number
  109. nakch       db      'C'                     ; NAK Character
  110. errors      db      0                       ; error counter
  111.  
  112. cancnt      db      0                       ; count of cancels
  113.  
  114. filename    db      65 dup (0)              ; space for filename
  115.  
  116. packet      db      133 dup (?)             ; XMODEM packet buffer
  117.  
  118. rcvaddr     dw      offset packet           ; address for next receive
  119. pktsz       db      133                     ; size of expected packet
  120.  
  121. PKTSOH      equ     byte ptr packet         ; SOH
  122. PKTSEQ      equ     byte ptr packet+1       ; sequence number
  123. PKTCSEQ     equ     byte ptr packet+2       ; complementary seq nbr
  124. PKTDATA     equ     byte ptr packet+3       ; start of data
  125. PKTCSUM     equ     byte ptr packet+131     ; checksum
  126. PKTCRC      equ     word ptr packet+131     ; crc if XMODEM/CRC
  127. PKTBUFLEN   equ     word ptr packet+1       ; length for write
  128.  
  129. oldds       dw      ?                       ; caller's ds
  130.  
  131. oldsp       dw      ?                       ; caller's sp
  132. oldss       dw      ?                       ; caller's ss
  133.  
  134. init2x      db      13, 'XMODEM: Init called twice', 13, 0
  135. badfnc      db      13, 'XMODEM: Bad function code', 13, 0
  136. openerr     db      13, 'XMODEM: Unable to open that file..'
  137. fileprompt  db      13, 'XMODEM: Enter filename, <CR> to exit: ', 0
  138. nofile      db      13, 'XMODEM: No filename, protocol aborted', 13, 0
  139. fileopened  db      13, 'XMODEM: File opened.. starting download', 13, 0
  140. timedout    db      13, 'XMODEM: Timeout, protocol ended', 13, 0
  141. toomany     db      13, 'XMODEM: Too many error, download cancelled', 13, 0
  142. notinited   db      13, 'XMODEM: BD did not call init first', 13, 0
  143. usercan     db      13, 'XMODEM: User cancelled download', 13, 0
  144. sendercan   db      13, 'XMODEM: Sender cancelled download', 13,0
  145. success     db      13, 'XMODEM: Download completed OK', 13, 0
  146. writerr     db      13, 'XMODEM: Write error.. protocol aborted', 13, 0
  147. seqerr      db      13, 'XMODEM: Packet sequence error', 13, 0
  148. staterr0    db      13, 'XMODEM: State error 0', 13, 0
  149. staterr1    db      13, 'XMODEM: State error 1', 13, 0
  150.  
  151. ; ---------------------------------------------------------------------
  152. ;  Protocol Mainline
  153. ; ---------------------------------------------------------------------
  154.  
  155. bpmxmodem   proc
  156.             push    es                      ; save caller's regs
  157.             push    ds
  158.  
  159.             mov     cs:oldds, ds            ; keep copy of caller's ds
  160.  
  161.             mov     cs:oldss, ss            ; save caller's stack
  162.             mov     cs:oldsp, sp
  163.  
  164.             mov     cs:ticks, ax            ; save entry ticks
  165.  
  166.             mov     ax, cs                  ; ax -> our segment
  167.             mov     ds, ax                  ; ds -> our segment
  168.             mov     es, ax                  ; es -> our segment
  169.  
  170.             cli                             ; no interrupts ..
  171.             mov     ss, ax                  ; ss -> our segment
  172.             mov     sp, stackoffset         ; sp -> end of stack
  173.             sti                             ; .. allow ints again
  174.  
  175.             cmp     di, MAXCODE             ; q. is code ok?
  176.             ja      bpmxmodm90              ; a. no .. return "done"
  177.  
  178.             test    di, 1                   ; q. is code even?
  179.             jnz     bpmxmodm90              ; a. no .. return "done"
  180.  
  181.             jmp     jmptab[di]              ; .. call requested routine
  182.  
  183. bpmxmodm90: lea     bx, badfnc              ; bx -> bad function code
  184.             jmp     proto_err               ; issue error and leave
  185.  
  186. bpmxmodem   endp
  187.  
  188.  
  189. ; ---------------------------------------------------------------------
  190. ;   Initialization call;                 ds:bx -> operands (filename)
  191. ; ---------------------------------------------------------------------
  192.  
  193. init        proc
  194.  
  195.             cmp     state, $ST_INIT         ; q. already init'd?
  196.             je      init00                  ; a. no .. continue
  197.  
  198.             lea     bx, init2x              ; bx -> error message
  199.             jmp     proto_err               ; .. kill the protocol
  200.  
  201. init00:     cmp     dl, 1                   ; q. normal xmodem?
  202.             jne     init02                  ; a. no .. assume CRC
  203.  
  204.             or      flgs, flgnrm            ; show normal wanted
  205.             mov     pktsz, 132              ; .. size of packet
  206.             mov     nakch, $NAK             ; .. reset nak char
  207.  
  208. init02:     mov     ds, oldds               ; ds -> callers segment
  209.  
  210.             cmp     byte ptr [bx], 0        ; q. any filename given?
  211.             je      init10                  ; a. no .. get the file name
  212.  
  213.             lea     di, filename            ; di -> area for filename
  214.             mov     si, bx                  ; si -> input filename
  215.             cld                             ; .. move upward
  216.  
  217. init05:     movsb                           ; move in a byte
  218.  
  219.             cmp     di, offset filename+64  ; q. end of area?
  220.             je      init20                  ; a. yes .. continue
  221.  
  222.             cmp     byte ptr [si-1],0       ; q. end of string?
  223.             jne     init05                  ; a. no .. continue
  224.  
  225.             push    cs                      ; save our segment
  226.             pop     ds                      ; .. ds -> our segment
  227.             jmp     short init20            ; .. open the file
  228.  
  229. init10:     lea     bx, fileprompt          ; bx -> filename prompt
  230.  
  231. init15:     mov     di, 12                  ; di =  display ASCIIZ
  232.             call    callback                ; .. ask bd to display
  233.  
  234.             lea     bx, filename            ; bx -> filename
  235.             mov     di, 16                  ; di =  get a line
  236.             call    callback                ; .. ask bd to get it
  237.  
  238.             cmp     filename, ' '           ; q. first char non-blank?
  239.             ja      init20                  ; a. yes .. continue
  240.  
  241.             lea     bx, nofile              ; bx = no file given
  242.             jmp     proto_err               ; .. kill the protocol
  243.  
  244. init20:     lea     bx, filename            ; bx -> filename
  245.             mov     di, 2                   ; di = open file
  246.             call    callback                ; q. file open ok?
  247.             jnc     init25                  ; a. yes .. continue
  248.  
  249.             lea     bx, openerr             ; bx -> open error
  250.             jmp     init15                  ; Tell user .. ask for next
  251.  
  252. init25:     lea     bx, fileopened          ; bx -> file opened msg
  253.             mov     di, 12                  ; di = display string
  254.             call    callback                ; .. ask bd to do it
  255.  
  256.             mov     timer, SOHTMOUT         ; set timer to packet timeout
  257.  
  258.             call    nak                     ; send a NAK
  259.  
  260.             mov     bx, ONESEC              ; bx = ticks for 1 second
  261.             mov     di, 22                  ; di = set tick downcounter
  262.             call    callback                ; .. set the down counter
  263.  
  264.             jmp     proto_ok                ; .. and init is done
  265.  
  266. init        endp
  267.  
  268.  
  269. ; ---------------------------------------------------------------------
  270. ;  Last function executed ok -or- simple dispatch
  271. ;                                           flgfnc = 0: simple dispatch
  272. ;                                           fncfnc = 1: state return
  273. ;                                               -- Carry is cleared
  274. ; ---------------------------------------------------------------------
  275.  
  276. fncok       proc
  277.  
  278.             test    flgs, flgfnc            ; q. callback return?
  279.             jz      fncok05                 ; a. no .. dispatch
  280.  
  281.             clc                             ; show function succeeded
  282.             ret                             ; .. rtn to callback caller
  283.  
  284. fncok05:    cmp     state, $ST_INIT         ; q. init'd yet?
  285.             jne     fncok10                 ; a. yes .. continue
  286.  
  287.             lea     bx, notinited           ; bx -> not init'd msg
  288.             jmp     proto_err               ; .. kill the protocol
  289.  
  290. fncok10:    jmp     short state_exec        ; run the state machine
  291.  
  292. fncok       endp
  293.  
  294.  
  295. ; ---------------------------------------------------------------------
  296. ;  Previous function failed                 Carry set to show failure
  297. ; ---------------------------------------------------------------------
  298.  
  299. fncfail     proc                            ; last function failed
  300.  
  301.             test    flgs, flgfnc            ; q. callback return?
  302.             jnz     fncfail10               ; a. yes .. continue
  303.  
  304.             lea     bx, staterr1            ; bx -> state error msg
  305.             jmp     proto_err               ; .. tell user & die
  306.  
  307. fncfail10:  stc                             ; set carry to show fail
  308.             ret                             ; return to callback caller
  309.  
  310. fncfail     endp
  311.  
  312. ; ---------------------------------------------------------------------
  313. ;  Process Communications Character         dl = character
  314. ; ---------------------------------------------------------------------
  315.  
  316. commchar    proc
  317.  
  318.             cmp     state, $ST_INIT         ; q. init'd yet?
  319.             jne     commchar05              ; a. yes .. continue
  320.  
  321.             lea     bx, notinited           ; bx -> not init'd msg
  322.             jmp     proto_err               ; .. kill the protocol
  323.  
  324. commchar05: test    flgs, flgfnc            ; q. callback return?
  325.             jz      commchar10              ; a. no .. continue
  326.  
  327.             lea     bx, staterr0            ; bx -> state error msg
  328.             jmp     proto_err               ; .. tell user & die
  329.  
  330. commchar10: mov     bx, rcvaddr             ; bx -> receive address
  331.             mov     [bx], dl                ; save received character
  332.  
  333.             or      flgs, flgrcv            ; show a char was received
  334.  
  335.             jmp     short state_exec        ; run the state machine
  336.  
  337. commchar    endp
  338.  
  339.  
  340. ; ---------------------------------------------------------------------
  341. ;  Process keyboard character               dl = character
  342. ; ---------------------------------------------------------------------
  343.  
  344. kbdchar     proc
  345.  
  346.             cmp     state, $ST_INIT         ; q. init'd yet?
  347.             jne     kbdchar05               ; a. yes .. continue
  348.  
  349.             lea     bx, notinited           ; bx -> not init'd msg
  350.             jmp     proto_err               ; .. kill the protocol
  351.  
  352. kbdchar05:  test    flgs, flgfnc            ; q. callback return?
  353.             jz      kbdchar10               ; a. no .. continue
  354.  
  355.             lea     bx, staterr0            ; bx -> state error msg
  356.             jmp     proto_err               ; .. tell user & die
  357.  
  358. kbdchar10:  cmp     dx, 4F00H               ; q. END key?
  359.             jnz     kbdchar20               ; a. no .. skip it
  360.  
  361.             or      flgs, flgcan            ; show cancel requested.
  362.  
  363. kbdchar20:  jmp     short state_exec        ; run the state machine
  364.  
  365. kbdchar     endp
  366.  
  367.  
  368. ; ---------------------------------------------------------------------
  369. ;  Run the state machine
  370. ; ---------------------------------------------------------------------
  371.  
  372. state_exec  proc
  373.  
  374.             cmp     ticks, 0                ; q. timeout on ticks?
  375.             jg      state10                 ; a. no .. continue
  376.  
  377.             dec     timer                   ; countdown the timer
  378.  
  379.             mov     bx, ONESEC              ; bx = ticks for 1 second
  380.             mov     di, 22                  ; di = set tick downcounter
  381.             call    callback                ; reset the down counter
  382.  
  383. state10:    mov     bx, state               ; bx = state offset
  384.             jmp     state_jmp[bx]           ; .. go to appropriate state
  385.  
  386. state_exec  endp
  387.  
  388. ; ---------------------------------------------------------------------
  389. ;  Awaiting SOH
  390. ; ---------------------------------------------------------------------
  391.  
  392. xmsoh       proc
  393.  
  394.             test    flgs, flgrcv            ; q. character received?
  395.             jz      xmsoh50                 ; a. no .. check timeouts
  396.  
  397.             test    flgs, flgcan            ; q. cancel requested?
  398.             jz      xmsoh05                 ; a. no .. continue
  399.  
  400.             mov     bl, $CAN                ; bl = CAN
  401.             mov     di, 20                  ; di = send one character
  402.             call    callback                ; .. send the cancel
  403.  
  404.             mov     state, $ST_UCAN         ; set up for user cancel
  405.             jmp     proto_ok                ; .. and say we're ok
  406.  
  407. xmsoh05:    cmp     packet, $SOH            ; q. packet received?
  408.             jne     xmsoh10                 ; a. no .. check next
  409.  
  410.             call    charcvd                 ; show char processed
  411.  
  412.             or      flgs, flgsoh            ; show 1st SOH found
  413.             mov     nakch, $NAK             ; reset the NAK char
  414.  
  415.             mov     state, $ST_EOP          ; show awaiting end pkt
  416.             jmp     proto_ok                ; .. show we are ok
  417.  
  418. xmsoh10:    cmp     packet, $CAN            ; q. cancel by sender?
  419.             jne     xmsoh15                 ; a. no .. check next
  420.  
  421.             mov     state, $ST_CAN          ; start the cancel
  422.             mov     timer, SOHTMOUT         ; .. restart the timer
  423.             jmp     short xmsoh20           ; .. kill the character
  424.  
  425. xmsoh15:    cmp     packet, $EOT            ; q. end of transmission?
  426.             jne     xmsoh20                 ; a. no .. continue
  427.  
  428.             mov     di, 6                   ; close the file
  429.             call    callback                ; .. ask bd to do it
  430.  
  431.             call    ack                     ; send an ack
  432.  
  433.             lea     bx, success             ; bx -> success message
  434.             call    proto_err               ; .. and we are done.
  435.  
  436. xmsoh20:    and     flgs, not flgrcv        ; shut off receive bit
  437.             jmp     proto_ok                ; .. no change of state
  438.  
  439. xmsoh50:    cmp     timer, 0                ; q. timeout?
  440.             jng     xmsoh55                 ; a. yes .. process it
  441.  
  442.             jmp     proto_ok                ; else .. continue
  443.  
  444. xmsoh55:    inc     errors                  ; add one to errors
  445.  
  446.             cmp     errors, 2               ; q. time to chg NAK char?
  447.             jb      xmsoh90                 ; a. no .. get out ok
  448.  
  449.             test    flgs, flgsoh            ; q. first SOH found?
  450.             jnz     xmsoh60                 ; a. yes .. don't change
  451.  
  452.             mov     nakch, $NAK             ; reset nak char
  453.             mov     pktsz, 132              ; .. not CRC
  454.             or      flgs, flgnrm            ; .. normal XMODEM
  455.  
  456. xmsoh60:    cmp     errors, MAXERRS         ; q. enough errors?
  457.             jb      xmsoh90                 ; a. no .. continue ok
  458.  
  459. xmsoh80:    mov     bl, $CAN                ; bl = CAN
  460.             mov     di, 20                  ; di = send one character
  461.             call    callback                ; .. send the cancel
  462.  
  463.             lea     bx, timedout            ; bx -> timeout message
  464.             jmp     proto_err               ; .. and kill the protocol
  465.  
  466. xmsoh90:    call    nak                     ; NAK 'em again
  467.             mov     timer, SOHTMOUT         ; reset timeout
  468.             jmp     proto_ok                ; .. and continue
  469.  
  470. xmsoh       endp
  471.  
  472.  
  473. ; ---------------------------------------------------------------------
  474. ;  Awaiting end of packet
  475. ; ---------------------------------------------------------------------
  476.  
  477. xmeop       proc
  478.  
  479.             test    flgs, flgrcv            ; q. character received?
  480.             jnz     xmeop50                 ; a. yes .. process it
  481.  
  482.             cmp     timer,0                 ; q. Timeout?
  483.             jng     xmeop05                 ; a. yes .. process it
  484.             jmp     proto_ok                ; else .. continue
  485.  
  486. xmeop05:    inc     errors                  ; add one to errors
  487.  
  488.             cmp     errors, MAXERRS         ; q. enough errors to die?
  489.             jb      xmeop10                 ; a. no .. continue
  490.  
  491.             mov     bl, $CAN                ; bl = CAN
  492.             mov     di, 20                  ; di = send one character
  493.             call    callback                ; .. send the cancel
  494.  
  495.             lea     bx, timedout            ; bx -> timeout message
  496.             jmp     proto_err               ; .. and kill the protocol
  497.  
  498. xmeop10:    mov     timer, SOHTMOUT         ; reset tmout
  499.  
  500.             call    nak                     ; send a nak
  501.             jmp     proto_ok                ; and continue ..
  502.  
  503. xmeop50:    call    charcvd                 ; process the char
  504.             mov     ax, rcvaddr             ; get current rcv address
  505.             sub     ax, offset packet       ; ax = chars received
  506.  
  507.             cmp     al, pktsz               ; q. packet received?
  508.             jb      xmeop58                 ; a. no .. continue recieve
  509.  
  510.             call    chkpkt                  ; q. packet ok?
  511.             jnc     xmeop60                 ; a. yes .. write & continue
  512.  
  513.             inc     errors                  ; .. add an error
  514.  
  515.             cmp     errors, MAXERRS         ; q. too many errors?
  516.             jb      xmeop55                 ; a. no .. continue
  517.  
  518.             mov     bl, $CAN                ; bl = CAN
  519.             mov     di, 20                  ; di = send one character
  520.             call    callback                ; .. send the cancel
  521.  
  522.             lea     bx, toomany             ; bx -> too many error msg
  523.             jmp     proto_err               ; .. and kill the protocol
  524.  
  525. xmeop55:    call    nak                     ; nak the packet
  526.             mov     timer, SOHTMOUT         ; .. start the timer
  527. xmeop58:    jmp     proto_ok                ; .. and continue
  528.  
  529. xmeop60:    mov     al, nseq                ; get the next seq nbr
  530.  
  531.             cmp     al, PKTSEQ              ; q. same sequence?
  532.             jne     xmeop90                 ; a. no .. skip write
  533.  
  534.             inc     nseq                    ; nseq = next sequence nbr
  535.  
  536.             mov     PKTBUFLEN, 128          ; set the buffersize
  537.             lea     bx, PKTBUFLEN           ; bx -> buffer to write
  538.             mov     di, 4                   ; di = write to file
  539.             call    callback                ; q. BD write it ok?
  540.             jnc     xmeop90                 ; a. yes .. continue
  541.  
  542.             mov     bl, $CAN                ; bl = CAN
  543.             mov     di, 20                  ; di = send one character
  544.             call    callback                ; .. send the cancel
  545.  
  546.             lea     bx, writerr             ; bx -> write error
  547.             jmp     proto_err               ; .. and kill the protocol
  548.  
  549. xmeop90:    call    ack                     ; show it went well
  550.             mov     timer, SOHTMOUT         ; reset the timer
  551. xmeop95:    jmp     proto_ok                ; .. and continue
  552.  
  553. xmeop       endp
  554.  
  555.  
  556. ; ---------------------------------------------------------------------
  557. ;  Process cancel request
  558. ; ---------------------------------------------------------------------
  559.  
  560. xmcan       proc
  561.  
  562.             test    flgs, flgrcv            ; q. character received?
  563.             jz      xmcan90                 ; a. no .. continue
  564.  
  565.             and     flgs, not flgrcv        ; cancel the character
  566.  
  567.             cmp     packet, $CAN            ; q. cancel?
  568.             jne     xmcan50                 ; a. no .. wait
  569.  
  570. xmcan40:    lea     bx, sendercan           ; bx -> sender cancelled
  571.             call    proto_err               ; .. cancel the protocol
  572.  
  573. xmcan50:    call    nak                     ; don't accept packet
  574.             mov     timer, SOHTMOUT         ; reset timer
  575.             jmp     proto_ok                ; .. continue
  576.  
  577. xmcan90:    cmp     timer, 0                ; q. timeout?
  578.             jng     xmcan40                 ; a. yes .. just die.
  579.             jmp     proto_ok                ; else .. continue
  580.  
  581. xmcan       endp
  582.  
  583.  
  584. ; ---------------------------------------------------------------------
  585. ;  Process user cancel request
  586. ; ---------------------------------------------------------------------
  587.  
  588. xmucan      proc
  589.  
  590.             test    flgs, flgrcv            ; q. character received?
  591.             jz      xmucan50                ; a. no .. test for timeout
  592.  
  593.             mov     timer, CANTMOUT         ; else .. renew timeout
  594.             and     flgs, not flgrcv        ; .. kill received char
  595.             mov     rcvaddr, offset packet  ; .. and next char addr
  596.             jmp     proto_ok                ; .. continue
  597.  
  598. xmucan50:   cmp     timer, 0                ; q. timeout yet?
  599.             jng     xmucan60                ; a. yes .. die
  600.             jmp     proto_ok                ; else .. let it continue
  601.  
  602. xmucan60:   lea     bx, usercan             ; bx -> user cancelled
  603.             jmp     proto_err               ; .. and kill the protocol
  604.  
  605. xmucan      endp
  606.  
  607.  
  608. ; ---------------------------------------------------------------------
  609. ;  Show received character processed
  610. ; ---------------------------------------------------------------------
  611.  
  612. charcvd     proc
  613.  
  614.             and     flgs, not flgrcv        ; shut off receive bit
  615.             inc     rcvaddr                 ; point to next address
  616.  
  617.             mov     timer, CHRTMOUT         ; set new character timeout
  618.             ret                             ; return to caller
  619.  
  620. charcvd     endp
  621.  
  622.  
  623. ; ---------------------------------------------------------------------
  624. ;  Check the received packet                carry = error in packet
  625. ; ---------------------------------------------------------------------
  626.  
  627. chkpkt      proc
  628.  
  629.             lea     si, PKTDATA             ; si -> packet data
  630.             mov     cx, 128                 ; cl =  len of data
  631.  
  632.             test    flgs, flgnrm            ; q. CRC?
  633.             jnz     chkpkt05                ; a. no .. do CHKSUM
  634.  
  635.             call    calc_crc                ; calculate the CRC
  636.             xchg    dh, dl                  ; .. make it little-endian
  637.  
  638.             cmp     dx, PKTCRC              ; q. same CRC?
  639.             jmp     short chkpkt10          ; .. test it later
  640.  
  641. chkpkt05:   call    calc_cksum              ; calculate the chksum
  642.  
  643.             cmp     dl, PKTCSUM             ; q. same chksum?
  644. chkpkt10:   jne     chkpkt90                ; a. no .. kill it now
  645.  
  646.                                             ; Check the sequence number
  647.  
  648.             mov     al, PKTSEQ              ; ah = sequence number
  649.             not     al                      ; al = 1's complement
  650.  
  651.             cmp     al, PKTCSEQ             ; q. same seq/Cseq?
  652.             jne     chkpkt90                ; a. no .. bad packet
  653.  
  654.             mov     al, PKTSEQ              ; al = packet's seq
  655.             mov     ah, nseq                ; .. and expected seq
  656.  
  657.             cmp     al, ah                  ; q. sequence ok?
  658.             je      chkpkt80                ; a. yes .. continue
  659.  
  660.             dec     ah                      ; ah = previous sequence
  661.  
  662.             cmp     al, ah                  ; q. previous packet?
  663.             je      chkpkt80                ; a. yes .. continue ..
  664.  
  665.             lea     bx, seqerr              ; bx = sequence error
  666.             jmp     short proto_err         ; .. kill the protocol
  667.  
  668. chkpkt80:   clc                             ; show it succeeded
  669.             ret                             ; return to caller
  670.  
  671. chkpkt90:   stc                             ; show it failed
  672.             ret                             ; .. return to caller
  673.  
  674. chkpkt      endp
  675.  
  676.  
  677. ; ----------------------------------------------------------------------
  678. ;   Calculate chksum        entry: si -> message block
  679. ;                                  cx =  length of message
  680. ;                            exit: dl =  returned checksum
  681. ; ----------------------------------------------------------------------
  682.  
  683. calc_cksum  proc
  684.  
  685.             xor     dl, dl                  ; dl = 0
  686.  
  687. calc_cks10: lodsb                           ; al = data char
  688.             add     dl, al                  ; dl = checksum .. so far
  689.             loop    calc_cks10              ; .. loop 'til done
  690.  
  691.             ret
  692.  
  693. calc_cksum  endp
  694.  
  695. ; ----------------------------------------------------------------------
  696. ;   Calculate CRC           entry: si -> message block
  697. ;                                  cx =  length of message
  698. ;                            exit: dx =  returned CRC
  699. ; ----------------------------------------------------------------------
  700.  
  701. calc_crc    proc
  702.  
  703.             xor     dx, dx                  ; dx = initialize crc
  704.             mov     bx, 1021h               ; bx = working constant
  705.             mov     di, 8000h               ; di = constant, too
  706.  
  707. calc_c10:   lodsb                           ; al = char from message
  708.             xor     ah, ah                  ; ax = cast char as integer
  709.             xchg    al, ah                  ; shift left char by 8
  710.             xor     dx, ax                  ; crc ^= (int)*ptr++ << 8
  711.  
  712.             push    cx                      ; save register
  713.             mov     cx, 8                   ; cx = bit loop count
  714.  
  715. calc_c20:   mov     ax, dx                  ; ax = temp copy of crc
  716.  
  717.             and     ax, di                  ; q. bit on?
  718.             jz      calc_c30                ; a. no .. continue
  719.  
  720.             shl     dx, 1                   ; shift left by one bit
  721.             xor     dx, bx                  ; crc = crc << 1 ^ 0x1021
  722.             jmp     short calc_c40          ; ..continue with common code
  723.  
  724. calc_c30:   shl     dx, 1                   ; crc <<= 1
  725.  
  726. calc_c40:   loop    calc_c20                ; ..just loop thru this byte
  727.  
  728.             pop     cx                      ; restore register
  729.             loop    calc_c10                ; ..and loop thru whole message
  730.  
  731.             ret
  732. calc_crc    endp
  733.  
  734.  
  735. ; ---------------------------------------------------------------------
  736. ;  Send a NAK
  737. ; ---------------------------------------------------------------------
  738.  
  739. nak         proc
  740.  
  741.             mov     bl, nakch               ; bl = current NAK char
  742.             mov     di, 20                  ; di = send one char
  743.             call    callback                ; .. ask BD to do it
  744.  
  745.             mov     state, $ST_SOH          ; Awaiting new pkt
  746.             mov     rcvaddr, offset packet  ; .. reset address
  747.  
  748.             ret                             ; .. return to caller
  749.  
  750. nak         endp
  751.  
  752.  
  753. ; ---------------------------------------------------------------------
  754. ;  Send an ACK
  755. ; ---------------------------------------------------------------------
  756.  
  757. ack         proc
  758.  
  759.             mov     bl, $ACK                ; bl = ACK char
  760.             mov     di, 20                  ; di = send one char
  761.             call    callback                ; .. ask BD to do it
  762.  
  763.             mov     bl, '.'                 ; show we're processing
  764.             mov     di, 14                  ; di = display one char
  765.             call    callback                ; .. ask BD to do it
  766.  
  767.             mov     state, $ST_SOH          ; Awaiting new pkt
  768.             mov     rcvaddr, offset packet  ; .. reset address
  769.             mov     errors, 0               ; .. and reset error cnt
  770.  
  771.             ret                             ; .. return to caller
  772.  
  773. ack         endp
  774.  
  775.  
  776. ; ---------------------------------------------------------------------
  777. ;  Setup to "call" backdown                 di = return code
  778. ; ---------------------------------------------------------------------
  779.  
  780. callback    proc
  781.  
  782.             or      flgs, flgfnc            ; show were in callback mode
  783.  
  784.             jmp     short proto_exit        ; return to caller
  785.  
  786. callback    endp
  787.  
  788.  
  789. ; ---------------------------------------------------------------------
  790. ;  Display error, return done               bx -> string
  791. ; ---------------------------------------------------------------------
  792.  
  793. proto_err   proc
  794.  
  795.             mov     di, 12                  ; di = display string
  796.             call    callback                ; .. display it
  797.  
  798.             jmp     short proto_done        ; tell bd we are done
  799.  
  800. proto_err   endp
  801.  
  802.  
  803. ; ---------------------------------------------------------------------
  804. ;  Protocol done - leave forever
  805. ; ---------------------------------------------------------------------
  806.  
  807. proto_done  proc
  808.  
  809.             mov     di, 10                  ; di = done code
  810.             jmp     short proto_exit        ; leave the protocol
  811.  
  812. proto_done  endp
  813.  
  814.  
  815. ; ---------------------------------------------------------------------
  816. ;  Exit with the OK code
  817. ; ---------------------------------------------------------------------
  818.  
  819. proto_ok    proc
  820.  
  821.             and     flgs, not flgfnc        ; zero out the function flag
  822.             mov     di, 0                   ; di = ok return code
  823.             jmp     short proto_exit        ; restore regs & exit
  824.  
  825. proto_ok    endp
  826.  
  827.  
  828. ; ---------------------------------------------------------------------
  829. ;  Protcol exit routine
  830. ; ---------------------------------------------------------------------
  831.  
  832. proto_exit  proc
  833.  
  834.             mov     stackoffset, sp         ; save our stack offset
  835.  
  836.             cli                             ; no interrupts
  837.             mov     ss, oldss               ; ..restore callers ss
  838.             mov     sp, oldsp               ; ..and sp
  839.             sti                             ; ints ok again
  840.  
  841.             pop     ds                      ; restore caller's regs
  842.             pop     es
  843.  
  844.             FARRET                          ; return to caller
  845.  
  846. proto_exit  endp
  847.  
  848. protocol    ends
  849.             end     start
  850.  
  851.