home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s1.zip / MSSCOM.ASM < prev    next >
Assembly Source File  |  1988-02-12  |  59KB  |  1,242 lines

  1.         NAME    msscom
  2. ; File MSSCOM.ASM
  3. ; Edit history:
  4. ; Last edit 1 Jan 1988
  5. ; 1 Jan 1988 version 2.30
  6. ; 30 Dec 1987 Do 5 retries, 10 ms apart, on sending bytes before failing.[jrd]
  7. ; 5 Nov 1987 Permit extra EOLs preceeding handshake char. [jrd]
  8. ; 28 Oct 1987 Replace CRC routine (CRCCLC).  Delete CRCTAB and CRCTAB2 [ebb]
  9. ; 25 Oct 1987 Allow extra bytes between EOL and handshake char. [jrd]
  10. ; 31 July 1987 Correct timeofday routine, from Jack Bryans. Add 8-bit display
  11. ; 24 July 1987 Rewrite Debugging and rpack to log bytes received before
  12. ;  the SOH char and to add occassional console read during receive. [jrd]
  13. ; 22 July 1987 Rewrite time of day material for no ambiguities. [jrd]
  14. ; 2 July 1987 Allow reception of junk chars between block check and
  15. ;  end of line without generating an error condition. [jrd]
  16. ; 20 May 1987 Reject incoming null characters. [jrd]
  17. ; 16 May 1987 Make Port3 and Port4 data structures available. [jrd]
  18. ; 24 April 1987 Add error return in spack if output of char fails. [jrd]
  19. ; 5 April 1987 Add call to chkcon at end of spack to update flags quicker,
  20. ;  suggested by Jack Bryans. [jrd]
  21. ; 24 March 1987 Modify debug display to sense debug separate from logging.[jrd]
  22. ; 21 March 1987 Change procedure Sleep to a) remove saveac macro and b) do
  23. ;  a check of console for a c/r or a Control C to force a timeout. [jrd]
  24. ; 12 March 1987 make premature reception of EOL char a full error.
  25. ;  Add clearing of serial port buffer before sending packets. [jrd]
  26. ; 28 Feb 1987 Add number of bytes sent and received for statistics. [jrd]
  27. ; 19 Feb 1987 Correct Sleep routine to avoid endless loop if ending time
  28. ;  just exceeds midnight. [jrd]
  29. ; 1 Oct 1986 Version 2.29a
  30. ; 12 Sept 1986 bug fixes plus lenient search (ignore errors) for handshake
  31. ;  character when receiving.
  32. ; 11 August 1986 Complete rewrite for overlapping computation with i/o,
  33. ;  add Long Packet support. [jrd]
  34. ; 15 May 86 - Fix stack corruption problem in outpkt when padding chars
  35. ;  used. Thanks to Bernie Eiben. [jrd]
  36. ; [2.29] code frozen on 6 May 1986 [jrd]
  37.  
  38.         public  data, spack, rpack, portval, port1, port2, port3, port4, hierr
  39.         public  prtbase, nports, sleep, spause
  40.         include mssdef.h
  41.  
  42. biostod equ     1ah             ; Bios time of day tic routine
  43. stat_suc equ    0               ; success
  44. stat_tmo equ    1               ; timeout
  45. stat_chk equ    2               ; checksum mismatch
  46. stat_ptl equ    4               ; packet too long
  47. stat_int equ    8               ; user interrupt
  48. stat_eol equ    10h             ; eol char seen
  49.  
  50. datas   segment public 'datas'
  51.         extrn   flags:byte, trans:byte, pack:byte, fsta:word, fmtdsp:byte
  52.  
  53. prtbase label   byte
  54. port1   prtinfo <0FFFH,0,defpar,1,0,defhand,floxon>
  55. port2   prtinfo <0FFFH,0,defpar,1,0,defhand,floxon>
  56. port3   prtinfo <0FFFH,0,defpar,1,0,defhand,floxon>
  57. port4   prtinfo <0FFFH,0,defpar,1,0,defhand,floxon>
  58.         rept    portmax-4
  59.         prtinfo <0FFFH,0,defpar,1,0,defhand,floxon>
  60.         endm
  61.  
  62. ;; systems with two ports can set portval to port1 or port2.
  63. ;; systems with more than two ports can set nports higher,
  64. ;; then set portval to the address prtbase+(#-1)*size prtinfo
  65. ;; where # is the desired port.
  66.  
  67. portval dw      port1           ; Default is to use port 1.
  68. nports  db      2               ; # of known ports
  69. hierr   db      0               ; Non-ascii char (non-zero if yes).
  70. parmsk  db      0ffh            ; parity mask (0FFH for 8bit data path) [umd]
  71. spmes   db      'Spack: $'
  72. rpmes   db      'Rpack: $'
  73. crlf    db      cr,lf,'$'
  74. cemsg   db      'User intervention$'
  75.  
  76. sixzero dw      60              ; for div operation in rec packet timeouts
  77. ninefive dw     95              ; for mult/div with long packets
  78. temp    dw      ?
  79. tmp     db      ?
  80. linecnt dw      ?               ; debug line width counter
  81. spause  db      0               ; # millisec to wait before sending pkt
  82. prvtyp  db      ?               ; Type of last packet sent
  83. pktptr  dw      ?               ; Position in receive packet.
  84. chksum  dw      ?               ; running checksum (two char)
  85. chrcnt  dw      ?               ; number of bytes in data field of a packet
  86. status  dw      ?               ; status of packet receiver (0 = ok)
  87. pktype  db      ?               ; received packet TYPE holding area
  88. debflg  db      ?               ; debug display, send/receive flag
  89. tmpflg  db      ?               ; flags.cxzflg at entry to rpack
  90. timeit  db      ?               ; arm timeout counter
  91. fairflg dw      0               ; fairness flag, for console/port reads.
  92. time    dw      2 dup (?)       ; Sleep, when we should timeout.
  93. rptim   db      4 dup (?)       ; read packet timeout slots
  94. spkcnt  dw      ?               ; number of bytes sent in this packet
  95. rpkcnt  dw      ?               ; number of bytes received in this packet
  96.  
  97.                                 ; Prolog, Data, Trailer must be kept together
  98. prolog  db      8 dup (?)       ; Packet header (SOH, LEN, SEQ, TYPE, xlen)
  99. data    db      maxpack+10 dup (?) ; Data field of packet (used in many places)
  100.                                 ; checksum, eol, handshake + null term
  101. datas   ends
  102.  
  103. code    segment public 'code'
  104.         extrn   prtchr:near, clrbuf:near, outchr:near
  105.         extrn   sppos:near, stpos:near, biterr:near, intmsg:near
  106.         extrn   clearl:near, rppos:near, errpack:near, prtscr:near
  107.         extrn   cptchr:near, strlen:near, pcwait:near
  108.  
  109.         assume  cs:code, ds:datas
  110.  
  111. ;       Packet routines
  112.  
  113. ; Send_Packet
  114. ; This routine assembles a packet from the arguments given and sends it
  115. ; to the host.
  116. ;
  117. ; Expects the following:
  118. ;       AH     - Type of packet (D,Y,N,S,I,R,E,F,Z,T)
  119. ;       ARGBLK - Packet sequence number
  120. ;       ARGBK1 - Number of data characters
  121. ; Returns: +1 always
  122. ; Packet construction areas:
  123. ;       Prolog (8 bytes)                        Data     null  Data
  124. ;+----------------------------------------+---------------+---------------+
  125. ;| SOH,LEN,SEQ,TYPE,Xlen(2-3),Xlen chksum | packet's data | chksum,EOL,HS |
  126. ;+----------------------------------------+---------------+---------------+
  127. ; where Xlen is 2 byte (Long) or 3 byte (Extra Long) count of bytes to follow.
  128. ;
  129. SPKT    PROC    NEAR
  130.  
  131. spack:  push    ax              ; save packet type (in ah)
  132.         call    clrbuf          ; clear serial port input buffer
  133.         call    prtchr          ; exercise receiver
  134.          nop
  135.          nop
  136.          nop
  137.         call    clrbuf          ; clear serial  port input buffer
  138.         mov     spkcnt,0        ; number of bytes sent in this packet
  139.         add     fsta.pspkt,1    ; statistics, count a packet being sent
  140.         adc     fsta.pspkt+2,0  ;  ripple carry
  141.         mov     al,spause       ; Wait spause milliseconds before
  142.         xor     ah,ah           ;   sending a packet
  143.         or      al,al           ; zero?
  144.         jz      spk1            ; z = yes
  145.         call    pcwait          ;   to let other side get ready
  146. spk1:   mov     dh,trans.spad   ; Get the number of padding chars.
  147. spk2:   dec     dh
  148.         cmp     dh,0
  149.         jl      spk5            ; If none left proceed.
  150.         mov     ah,trans.spadch ; Get the padding char.
  151.         push    dx              ; save loop counter
  152.         call    outchr          ; Output it.
  153.          jmp    spk3            ; failed
  154.          nop                    ; must be three bytes
  155.         pop     dx              ; get loop counter
  156.         jmp     spk2            ; do remaining padding chars
  157. spk3:   pop     dx
  158.         pop     ax
  159.         ret                     ; failed
  160.         pop     dx
  161. spk5:   pop     ax              ; recover ah
  162.         mov     prvtyp,ah       ; Remember packet type
  163.         mov     bx,portval      ; Get current port structure [umd]
  164.         mov     parmsk,0ffh     ; Set parity mask for 8 bits [umd]
  165.         cmp     [bx].parflg,parnon      ; Using parity? [umd]
  166.         je      spacka          ; e = no. use mask as is. [umd]
  167.         mov     parmsk,7fh      ; else set mask for 7 data bits. [umd]
  168. spacka: call    snddeb          ; do debug display (while it's still our turn)
  169.         mov     pktptr,offset prolog
  170.         mov     word ptr prolog,0
  171.         mov     word ptr prolog+2,0
  172.         mov     word ptr prolog+4,0
  173.         mov     word ptr prolog+6,0
  174.         mov     al,trans.ssoh   ; Get the start of header char.
  175.         mov     prolog,al       ; Put SOH in the packet.
  176.         mov     ax,pack.argblk  ; SEQ
  177.         add     al,20h          ; ascii bias
  178.         mov     prolog+2,al     ; store SEQ in packet
  179.         mov     ah,0
  180.         mov     chksum,ax       ; start checksum
  181.         mov     al,prvtyp       ; TYPE
  182.         mov     prolog+3,al     ; store TYPE
  183.         add     chksum,ax       ; add to checksum
  184. ;
  185. ; packet length type is directly governed here by length of header plus data
  186. ; field, pack.argbk1, plus chksum: regular <= 94, long <= 9024, else X long.
  187. ;
  188.         mov     ax,pack.argbk1  ; DATA length
  189.         add     ax,2            ; add SEQ, TYPE lengths
  190.         add     al,trans.chklen ; add checksum length at the end
  191.         adc     ah,0            ; propagate carry, yields overall new length
  192.         cmp     ax,maxpack      ; too big?
  193.         jle     spdlp0          ; le = ok
  194.         ret                     ; return bad
  195. spdlp0:
  196.         mov     pack.argbk3,3   ; assume regular packet
  197.         cmp     ax,94           ; longer than a regular?
  198.         ja      spdlp1          ; a = use long
  199.         add     al,20h          ; convert length to ascii
  200.         mov     prolog+1,al     ; store LEN
  201.         mov     ah,0
  202.         add     chksum,ax       ; add LEN to checksum
  203.         jmp     spklp5          ; do regular
  204. spdlp1: push    ax              ; Use Long packets (type 3)
  205.         push    bx
  206.         push    cx
  207.         push    dx
  208.         sub     ax,2            ; deduct SEQ and TYPE from above = data+chksum
  209.         mov     pack.argbk3,0   ; assume type 0 packet
  210.         cmp     ax,(95*95-1)    ; longest type 0 packet (9024)
  211.         jbe     spdlp3          ; be = type 0
  212.         mov     pack.argbk3,1   ; type 1 packet
  213. spdlp3: mov     bx,pack.argbk3  ; add new LEN field to checksum
  214.         add     bl,20h          ; ascii bias, tochar()
  215.         mov     bh,0
  216.         add     chksum,bx       ; add to running checksum
  217.         mov     prolog+1,bl     ; put LEN into packet
  218.         mov     bx,offset prolog+4      ; address of extended length field
  219.         mov     cx,1            ; a counter
  220.         xor     dx,dx           ; high order numerator of length
  221. spdlp7: div     ninefive        ; divide ax by 95. quo = ax, rem = dx
  222.         push    dx              ; push remainder
  223.         inc     cx              ; count push depth
  224.         cmp     ax,95           ; quotient >= 95?
  225.         jae     spdlp7          ; ae = yes, recurse
  226.         push    ax              ; push for pop below
  227. spdlp8: pop     ax              ; get a digit
  228.         add     al,20h          ; apply tochar()
  229.         mov     [bx],al         ; store in data field
  230.         add     chksum,ax       ; accumulate checksum for header
  231.         inc     bx              ; point to next data field byte
  232.         mov     byte ptr[bx],0  ; insert terminator
  233.         loop    spdlp8          ; get the rest
  234.                                 ;
  235.         mov     ax,chksum       ; current checksum
  236.         shl     ax,1            ; put two highest bits of al into ah
  237.         shl     ax,1
  238.         and     ah,3            ; want just those two bits
  239.         shr     al,1            ; put al back in place
  240.         shr     al,1
  241.         add     al,ah           ; add two high bits to earlier checksum
  242.         and     al,03fh         ; chop to lower 6 bits (mod 64)
  243.         add     al,20h          ; apply tochar()
  244.         mov     [bx],al         ; store that in length's header checksum
  245.         mov     ah,0
  246.         add     chksum,ax       ; add that byte to running checksum
  247.         pop     dx
  248.         pop     cx
  249.         pop     bx
  250.         pop     ax
  251.  
  252. spklp5: push    si      ; assume soh, len, seq, type, extra len are in prolog
  253.         push    di
  254.         push    cx
  255.         push    ds
  256.         pop     es              ; set es to data segment for implied es:di
  257.         mov     si,offset prolog        ; source
  258.         mov     di,offset data-1        ; end point of destination
  259.         mov     pktptr,offset data      ; start of packet ptr for debug
  260.         cmp     pack.argbk3,0   ; long packets?
  261.         jne     spklp6          ; ne = no
  262.         add     si,6            ; long packets
  263.         mov     cx,7            ; seven bytes soh,len,seq,type, xl1,xl2,xlchk
  264.         jmp     spklp8
  265. spklp6: cmp     pack.argbk3,1   ; extra long packets?
  266.         jne     spklp7          ; ne = no
  267.         mov     cx,8            ; extra long packets
  268.         add     si,7
  269.         jmp     spklp8
  270. spklp7: add     si,3            ; regular packets, slide up by four bytes
  271.         mov     cx,4            ; number of bytes to move
  272. spklp8: jcxz    spklp9          ; no movement needed
  273.         sub     pktptr,cx       ; pktprt=new offset of prolog section
  274.         std
  275.         rep     movsb           ; move the protocol header, cx times
  276.         cld
  277. spklp9: pop     cx
  278.         pop     di
  279.         pop     si
  280.         mov     bx,pktptr       ; place where protocol section starts
  281. spklp10:mov     ah,[bx]         ; protocol part
  282.         inc     bx
  283.         call    spkout          ; send byte to serial port
  284.         jnc     spklp11         ; nc = good send
  285.         jmp     spackq          ; bad send
  286. spklp11:cmp     bx,offset data  ; done all protocol parts yet?
  287.         jb      spklp10         ; b = not yet
  288.         mov     bx,offset data  ; select from given data buffer
  289.         mov     dx,pack.argbk1  ; Get the number of data bytes in packet.
  290. spack2: dec     dx              ; Decrement the char count.
  291.         js      spack3          ;  sign = no, finish up.
  292.         mov     al,byte ptr[bx] ; get a data char
  293.         inc     bx              ; point to next char [umd]
  294.         test    al,80h          ; eighth bit set?
  295.         jz      spackb          ; z = no
  296.         and     al,parmsk       ; apply parity mask, may clear 8th bit [umd]
  297.         cmp     hierr,0         ; printed high bit error yet? [umd]
  298.         jne     spackb          ; ne = yes [umd]
  299.         push    ax
  300.         push    bx
  301.         push    cx
  302.         push    dx
  303.         call    biterr
  304.         pop     dx
  305.         pop     cx
  306.         pop     bx
  307.         pop     ax
  308.         mov     hierr,0FFH      ; set err flag.
  309. spackb: mov     ah,0
  310.         add     chksum,ax       ; add the char to the checksum [umd]
  311.         and     chksum,0fffh    ; keep only low order 12 bits
  312.         mov     ah,al           ; put char in ah where spkout wants it
  313.         call    spkout          ; send it
  314.         jnc     spack2          ; Go get more data chars
  315.         jmp     spackq          ; bad send
  316.  
  317. spack3: mov     cx,chksum
  318.         cmp     trans.chklen,2  ; What kind of checksum are we using?
  319.         je      spackx          ; e = 2 characters.
  320.         jg      spacky          ; g = 3 characters.
  321.         mov     ah,cl           ; 1 char: get the character total.
  322.         mov     ch,cl           ; Save here too (need 'cl' for shift).
  323.         and     ah,0C0H         ; Turn off all but the two high order bits.
  324.         mov     cl,6
  325.         shr     ah,cl           ; Shift them into the low order position.
  326.         mov     cl,ch
  327.         add     ah,cl           ; Add it to the old bits.
  328.         and     ah,3FH          ; Turn off the two high order bits.  (MOD 64)
  329.         add     ah,' '          ; Add a space so the number is printable.
  330.         mov     [bx],ah         ; Put in the packet.
  331.         inc     bx              ; Point to next char.
  332.         call    spkout          ; send it
  333.         jnc     spackz          ; Add EOL char.
  334.         jmp     spackq          ; bad send
  335. spacky: mov     byte ptr[bx],0  ; null, to determine end of buffer.
  336.         push    bx              ; Don't lose our place.
  337.         mov     bx,pktptr       ; First checksummed character.
  338.         inc     bx              ; skip SOH
  339.         call    crcclc          ; Calculate the CRC.
  340.         pop     bx
  341.         push    cx              ; save the crc
  342.         mov     ax,cx           ; Manipulate it here.
  343.         and     ax,0F000H       ; Get 4 highest bits.
  344.         mov     cl,4
  345.         shr     ah,cl           ; Shift them over 4 bits.
  346.         add     ah,' '          ; Make printable.
  347.         mov     [bx],ah         ; Add to buffer.
  348.         inc     bx
  349.         pop     cx              ; Get back checksum value.
  350.         call    spkout          ; send it
  351.         jnc     spackx
  352.         jmp     spackq          ; bad send
  353. spackx: push    cx              ; Save it for now.
  354.         and     cx,0FC0H        ; Get bits 6-11.
  355.         mov     ax,cx
  356.         mov     cl,6
  357.         shr     ax,cl           ; Shift them bits over.
  358.         add     al,' '          ; Make printable.
  359.         mov     [bx],al         ; Add to buffer.
  360.         inc     bx
  361.         mov     ah,al
  362.         call    spkout          ; send it
  363.         pop     cx              ; Get back the original.
  364.         jc      spackq          ; c = bad send
  365.         and     cx,003FH        ; Get bits 0-5.
  366.         add     cl,' '          ; Make printable.
  367.         mov     [bx],cl         ; Add to buffer.
  368.         inc     bx
  369.         mov     ah,cl
  370.         call    spkout          ; send it
  371.         jnc     spackz
  372. spackq: RET                     ; bad send, do ret to caller of spack
  373. spackz: mov     ah,trans.seol   ; Get the EOL the other host wants.
  374.         mov     [bx],ah         ; Put eol
  375.         inc     bx
  376.         call    deblin          ; do debug display (while it's still our turn)
  377.         cmp     flags.debug,0   ; In debug mode?
  378.         jne     spackz0         ; ne = yes
  379.         test    flags.capflg,logpkt ; log packets?
  380.         jz      spackz1         ; z = no
  381. spackz0:cmp     linecnt,0       ; anything on current line?
  382.         je      spackz1         ; e = no
  383.         mov     dx,offset crlf  ; finish line with cr/lf
  384.         call    captdol         ;  to log file
  385. spackz1:mov     ah,trans.seol   ; recover EOL
  386.         call    spkout          ; send it
  387.         jnc     spackz2
  388.         jmp     spackq          ; bad send
  389. spackz2:
  390.         mov     ax,spkcnt       ; number of bytes sent in this packet
  391.         add     fsta.psbyte,ax  ; total bytes sent
  392.         adc     fsta.psbyte+2,0 ; propagate carry to high word
  393.         call    chkcon          ; check console for user interrupts
  394.          nop                    ;  no action on plain rets
  395.          nop
  396.          nop
  397.         jmp     rskp            ; return successfully
  398. SPKT    ENDP
  399.  
  400. spkout: push    ax              ; send char in ah out the serial port
  401.         push    bx              ; return carry clear if success
  402.         push    cx
  403.         push    dx
  404.         mov     tmp,1           ; retry counter
  405. spkour: call    outchr          ; serial port transmitter procedure
  406.          jmp    short spkoux    ; bad send, retry
  407.          nop
  408.         inc     spkcnt          ; count number of bytes sent in this packet
  409.         pop     dx
  410.         pop     cx
  411.         pop     bx
  412.         pop     ax
  413.         clc                     ; carry clear for good send
  414.         ret
  415. spkoux: cmp     tmp,5           ; done 5 attempts on this char?
  416.         jge     spkoux1         ; ge = yes, fail the sending
  417.         inc     tmp
  418.         push    ax
  419.         mov     ax,10           ; wait 10 milliseconds
  420.         call    pcwait
  421.         pop     ax
  422.         jmp     short spkour    ; retry
  423. spkoux1:pop     dx              ; failed to send char
  424.         pop     cx
  425.         pop     bx
  426.         pop     ax
  427.         stc                     ; set carry for bad send
  428.         ret
  429.  
  430. ; Calculate the CRC of the null-terminated string whose
  431. ; address is in BX.  Returns the CRC in CX.  Destroys BX and AX.
  432. ; The CRC is based on the SDLC polynomial: x**16 + x**12 + x**4 + 1.
  433. ; By Edgar Butt  28 Oct 1987 [ebb].
  434. crcclc: push    dx
  435.         mov     dx,0                ; Initial CRC value is 0.
  436.         mov     cl,4                ; Load shift count.
  437. crc0:   mov     ah,[bx]             ; Get the next char of the string.
  438.         cmp     ah,0                ; If null, then we're done.
  439.         je      crc1
  440.         inc     bx
  441.         xor     dl,ah               ; XOR input with lo order byte of CRC.
  442.         mov     ah,dl               ; Copy it.
  443.         shl     ah,cl               ; Shift copy.
  444.         xor     ah,dl               ; XOR to get quotient byte in ah.
  445.         mov     dl,dh               ; High byte of CRC becomes low byte.
  446.         mov     dh,ah               ; Initialize high byte with quotient.
  447.         mov     al,0
  448.         shr     ax,cl               ; Shift quotient byte.
  449.         xor     dl,ah               ; XOR (part of) it with CRC.
  450.         shr     ax,1                ; Shift it again.
  451.         xor     dx,ax               ; XOR it again to finish up.
  452.         jmp     short crc0
  453. crc1:   mov     cx,dx               ; Return it in CX.
  454.         pop     dx
  455.         ret
  456.  
  457. ; Receive_Packet
  458. ; This routine waits for a packet arrive from the host.  It reads
  459. ; chars until it finds a SOH.
  460. ; Packet construction areas:
  461. ;       Prolog (8 bytes+2 nulls)        null    Data    null  Data     null
  462. ;+----------------------------------------+---------------+---------------+
  463. ;| SOH,LEN,SEQ,TYPE,Xlen(2-3),Xlen chksum | packet's data | chksum,EOL,HS |
  464. ;+----------------------------------------+---------------+---------------+
  465. ; where Xlen is 2 byte (Long) or 3 byte (Extra Long) count of bytes to follow.
  466.  
  467. RPACK   PROC    NEAR
  468.         call    rcvdeb                  ; setup debug banner, if needed.
  469.         mov     fairflg,0               ; set fairness flag
  470.         mov     pktptr,offset prolog   ; where to place packet prolog material
  471.         mov     bx,pktptr               ; bx = debug buffer pointer for new data
  472.         mov     rpkcnt,0             ; number of bytes received in this packet
  473.         mov     ax,0                  ; most recently read char, initialize it
  474.         push    bx
  475.         mov     bl,flags.cxzflg         ; Remember original value
  476.         mov     tmpflg,bl               ; Store it here
  477.         mov     parmsk,0ffh             ; parity mask, assume 8 bit data
  478.         mov     bx,portval
  479.         cmp     [bx].parflg,parnon      ; parity is none?
  480.         pop     bx
  481.         je      rpack0                  ; e = none
  482.         mov     parmsk,07fh             ; else strip parity (8th) bit
  483. rpack0: call    deblin                  ; debug, show chars received thus far
  484.         mov     word ptr prolog,0       ; clear prolog and data fields
  485.         mov     word ptr prolog+2,0
  486.         mov     word ptr prolog+4,0
  487.         mov     word ptr prolog+6,0
  488.         mov     word ptr data,0
  489.         mov     pktptr,offset prolog  ; where to place packet prolog material
  490.         mov     bx,pktptr             ; bx = debug buffer pointer for new data
  491.         mov     status,stat_suc         ; assume success
  492.         call    inchr                   ; Get a character. SOH
  493.          jmp    rpack0a         ; failure (eol, timeout, user intervention)
  494.          nop
  495. rpack0b:mov     byte ptr[bx],al ; store char in buffer
  496.         inc     bx
  497.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  498.         jne     rpack0          ; ne = no, go until it is.
  499.         jmp     rpack1          ; got the SOH char from the port
  500. rpack0a:jc      rpack0b         ; c = hit eol from prev packet, restart
  501.         jmp     rpack6          ; timeout or user intervention
  502. rpack1: mov     pktptr,offset prolog    ; if we got here from below
  503.         mov     bx,pktptr               ; debug pointer
  504.         mov     byte ptr[bx],al ; store SOH in buffer
  505.         inc     bx
  506.         mov     status,stat_suc ; say success, in case rescanning for pkt.
  507.         call    inchr           ; Get a character. LEN
  508.          jmp    rpack4          ; failure
  509.          nop
  510.         mov     byte ptr[bx],al ; store LEN in buffer
  511.         inc     bx
  512.         mov     ah,0
  513.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  514.         jne     rpack1e         ; ne = no
  515.         jmp     rpack7          ; yes, start over
  516. rpack1e:mov     chksum,ax       ; start the checksum
  517.         sub     al,20h          ; unchar() to binary
  518.         mov     pack.argbk1,ax  ; Save the data count (byte)
  519.         call    inchr           ; Get a character. SEQ
  520.          jmp    rpack4          ; failure
  521.          nop
  522.         mov     byte ptr[bx],al ; store SEQ in buffer
  523.         inc     bx
  524.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  525.         jz      rpack1          ; nz = yes, then go start over.
  526.         mov     ah,0
  527.         add     chksum,ax
  528.         sub     al,' '          ; Get the real packet number.
  529.         mov     ah,0
  530.         mov     pack.argblk,ax  ; Save the packet number. SEQ
  531.         call    inchr           ; Get a character. TYPE
  532.          jmp    rpack4          ; failure
  533.         mov     byte ptr[bx],al ; store TYPE in buffer
  534.         inc     bx
  535.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  536.         jz      rpack1          ; nz = yes, then go start over.
  537.         mov     pktype,al       ; Save the message type
  538.         mov     ah,0
  539.         add     chksum,ax       ; Add it to the checksum.
  540.         push    bx
  541.         mov     bx,portval      ; Point to current port structure
  542.         cmp     [bx].ecoflg,0   ; Is the host echoing?
  543.         pop     bx
  544.         jne     rpak11          ; No, packets not echoed
  545.         cmp     al,prvtyp       ; Packet type same as last sent?
  546.         jne     rpak11          ; ne = no
  547.         mov     prvtyp,0        ; clear to respond to next packet
  548.         jmp     rpack0          ; Yes, chuck echoed packet
  549. rpak11: call    getlen          ; get complicated data length (reg, lp, elp)
  550.                                 ; into  pack.argbk1 and kind into pack.argbk3
  551.                                 ; carry set if error
  552.         jnc     rpack1d         ; nc = long packet checksum is ok
  553.         or      status,stat_chk ; say bad checksum
  554.         jmp     rpack4          ; checksum failure
  555. rpack1d:
  556. ; Start of change.
  557. ; Now determine block check type for this packet.  Here we violate the layered
  558. ; nature of the protocol by inspecting the packet type in order to detect when
  559. ; the two sides get out of sync.  Two heuristics allow us to resync here:
  560. ;   a. I and S packets always has a type 1 checksum.
  561. ;   b. A NAK never contains data, so its block check type is argblk1.
  562.         cmp     prolog+3,'S'    ; Is this an "S" packet?
  563.         jne     rpk0            ; ne = no.
  564.         mov     trans.chklen,1  ; S packets use one byte checksums
  565.         jmp     rpk3
  566. rpk0:   cmp     prolog+3,'I'    ; I packets are like S packets
  567.         jne     rpk1
  568.         mov     trans.chklen,1  ; I packets use one byte checksums
  569.         jmp     rpk3
  570. rpk1:   cmp     prolog+3,'N'    ; Is this a NAK?
  571.         jne     rpk3            ; ne = no.
  572.         cmp     pack.argbk1,1   ; NAK, get length of data + chklen
  573.         jb      rpk1a           ; b = impossible length
  574.         cmp     pack.argbk1,3   ; longest NAK (3 char checksum)
  575.         jbe     rpk2            ; be = possible
  576. rpk1a:  or      status,stat_ptl ; status = bad length
  577.         jmp     rpack4          ;  ret on impossible length
  578. rpk2:   mov     ax,pack.argbk1
  579.         mov     trans.chklen,al ; remainder must be checksum type for NAK.
  580. rpk3:   mov     ax,pack.argbk1  ; get length of data + chksum
  581.         sub     al,trans.chklen ; minus checksum length, for all packets
  582.         sbb     ah,0            ; propagate borrow
  583.         mov     pack.argbk1,ax  ; store apparent length of data field
  584. ; End of change.
  585. ; now, for long packets we start the real data (after the extended byte
  586. ; count 3 or 4 bytes) at offset data and thus the checksumming starts
  587. ; such packets a few bytes earlier. [jrd]
  588.         push    si
  589.         push    di
  590.         push    cx
  591.         mov     di,offset data-1
  592.         mov     si,offset prolog
  593.         mov     pktptr,offset data
  594.         cmp     pack.argbk3,0   ; long packets?
  595.         jne     rpk5            ; ne = no
  596.         mov     cx,7            ; seven bytes mark...type, xl,xl,xlchk
  597.         add     si,6
  598.         jmp     rpk7
  599. rpk5:   cmp     pack.argbk3,1   ; extra long packets?
  600.         jne     rpk6            ; ne = no
  601.         mov     cx,8            ; extra long packets, no movement
  602.         add     si,7
  603.         jmp     rpk7
  604. rpk6:   add     si,3            ; regular packets, slide by four bytes
  605.         mov     cx,4            ; number of bytes to move
  606. rpk7:   jcxz    rpk8            ; no movement needed
  607.         sub     pktptr,cx       ; pktptr=new offset of prolog section
  608.         push    es              ; save es
  609.         push    ds
  610.         pop     es              ; set es to datas segment
  611.         std                     ; move backward
  612.         rep     movsb           ; move the protocol header, cx times
  613.         pop     es
  614.         cld                     ; reset direction flag to normal
  615. rpk8:   pop     cx
  616.         pop     di
  617.         pop     si
  618.         mov     dx,pack.argbk1  ; length of data field, excl LP header
  619.         mov     chrcnt,dx
  620.         mov     dx,trans.rlongp ; longest packet we can receive
  621.         sub     dl,trans.chklen ; minus checksum length
  622.         sbb     dh,0            ; propagate borrow
  623.         cmp     pack.argbk3,3   ; Regular Packet?
  624.         jne     rpk8a           ; ne = no
  625.         sub     dx,2            ; minus SEQ, TYPE for regular packets
  626. rpk8a:  cmp     dx,pack.argbk1  ; is data field too long?
  627.         jae     rpk8b           ; ae = not too big
  628.         or      status,stat_ptl ; failure status, packet too long
  629.         jmp     rpack4          ; too big, quit now
  630. rpk8b:  mov     bx,offset data  ; Point to the data buffer.
  631.  
  632.                                 ; Get DATA field characters
  633. rpack2: dec     chrcnt          ; # data chars
  634.         js      rpack3          ; s = exhausted data, go get the checksum.
  635.         call    inchr           ; Get a character into al. DATA
  636.          jmp    rpack4          ; control-c, timeout (out of data), eol
  637.          nop
  638.         mov     byte ptr[bx],al ; Put the char into the packet.
  639.         inc     bx              ; Point to the next character.
  640.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  641.         jnz     rpak2b          ; nz = no
  642.         jmp     rpack7          ; yes, then go start over.
  643. rpak2b: mov     ah,0
  644.         add     chksum,ax
  645.         and     chksum,0fffh    ; keep only lower 12 bits
  646.         jmp     rpack2          ; Go get another.
  647.  
  648. rpack3: call    inchr           ; Get a character. Start Checksum bytes
  649.          jmp    rpack4          ; failed
  650.          nop
  651.         mov     byte ptr[bx],al ; place to store checksum, EOL, HS for debug
  652.         inc     bx              ; point at next slot
  653.         cmp     al,trans.rsoh   ; Is the char the start of header char?
  654.         jne     rpk3x           ; ne = no
  655.         jmp     rpack7          ; yes, then go start over.
  656. rpk3x:  sub     al,' '          ; Turn the char back into a number.
  657.         mov     cx,chksum       ; current checksum
  658.         cmp     trans.chklen,2  ; What checksum length is in use.
  659.         je      rpackx          ; e = Two character checksum.
  660.         jg      rpacky          ; g = Three character CRC.
  661.         shl     cx,1            ; put two highest digits of al into ah
  662.         shl     cx,1
  663.         and     ch,3            ; want just those two bits
  664.         shr     cl,1            ; put al back in place
  665.         shr     cl,1
  666.         add     cl,ch           ; add two high bits to earlier checksum
  667.         and     cl,03fh         ; chop to lower 6 bits (mod 64)
  668.         cmp     cl,al           ; computed vs received checksum byte (binary)
  669.         je      rpk3xa          ; e = equal, so finish up.
  670.         or      status,stat_chk ; say checksum failure
  671. rpk3xa: jmp     rpack4
  672.  
  673. rpack7: call    deblin          ; dump debugging information so far
  674.         jmp     rpack1          ; For the jump out of range.
  675.  
  676. rpacky: mov     tmp,al          ; Save value from packet here.
  677.         push    bx              ; Three character CRC.
  678.         mov     cx,[bx-1]       ; save checksum char and next
  679.         mov     temp,cx
  680.         mov     word ptr[bx-1],0 ; put null at end of Data field for crc
  681.         mov     bx,pktptr       ; Where data for CRC is.
  682.         inc     bx              ; skip SOH
  683.         call    crcclc          ; Calculate the CRC and put into CX.
  684.         pop     bx
  685.         mov     ax,temp
  686.         mov     [bx-1],ax       ; restore char pair from above
  687.         mov     ah,ch           ; cx = 16 bit binary CRC of rcv'd data
  688.         and     ah,0f0h         ; Manipulate it here.
  689.         shr     ah,1
  690.         shr     ah,1            ; Get 4 highest bits.
  691.         shr     ah,1
  692.         shr     ah,1            ; Shift them over 4 bits.
  693.         cmp     ah,tmp          ; Is what we got == what we calculated?
  694.         je      rpky1           ; e = yes
  695.         or      status,stat_chk ; checksum failure
  696. rpky1:  call    inchr           ; Get next character of checksum.
  697.          jmp    rpack4          ; Failed.
  698.          nop
  699.         mov     byte ptr[bx],al ; put into buffer for debug
  700.         inc     bx
  701.         cmp     al,trans.rsoh   ; Restarting?
  702.         je      rpack7          ; e = yes
  703.         sub     al,' '          ; Get back real value.
  704. rpackx: mov     tmp,al          ; Save here for now.
  705.         push    cx              ; Two character checksum.
  706.         and     cx,0FC0H        ; Get bits 6-11.
  707.         mov     ax,cx
  708.         mov     cl,6
  709.         shr     ax,cl           ; Shift them bits over.
  710.         pop     cx              ; Get back the original.
  711.         cmp     al,tmp          ; Are they equal?
  712.         je      rpkx1           ; yes
  713.         or      status,stat_chk ; checksum failure
  714. rpkx1:  call    inchr           ; Get last character of checksum.
  715.          jmp    rpack4          ; Failed.
  716.          nop
  717.         mov     byte ptr[bx],al ; put into buffer for debug
  718.         inc     bx
  719.         cmp     al,trans.rsoh   ; Restarting?
  720.         je      rpack7          ; e = yes
  721.         sub     al,' '          ; Get back real value.
  722.         and     cx,003FH        ; Get bits 0-5.
  723.         cmp     al,cl           ; Do the last chars match?
  724.         je      rpack4          ; e = yes
  725.         or      status,stat_chk ; say checksum failure
  726.  
  727. rpack4: test    status,stat_tmo ; timeout?
  728.         jnz     rpack6          ; nz = yes
  729.         test    status,stat_eol ; premature eol?
  730.         jnz     rpack4c         ; nz = yes, try handshake
  731.         call    inchr           ; get eol char (ok = ret with carry set)
  732.          jnc    rpack6          ; nc = timeout or user intervention
  733.          nop
  734.         cmp     bx,offset data+maxpack+7        ; filled debug buffer yet?
  735.         ja      rpack4e         ; a = yes
  736.         mov     byte ptr[bx],al ; put into buffer for debug
  737.         inc     bx
  738. rpack4e:cmp     al,trans.rsoh   ; soh already?
  739.         jne     rpack4a         ; ne = no
  740.         jmp     rpack7          ; yes
  741. rpack4a:test    status,stat_eol ; got expected eol character?
  742.         pushf
  743.         and     status,not stat_eol ; desired eol is not an error,
  744.         popf                        ;  lack of eol is
  745.         jnz     rpack4c         ; nz = yes (note bit clearing above)
  746.         jmp     short rpack4    ; keep looking for eol
  747. rpack4c:
  748.         push    bx              ; test for line turn char, if handshaking
  749.         mov     bx,portval
  750.         mov     ah,[bx].hands   ; get desired handshake char
  751.         cmp     [bx].hndflg,0   ; doing half duplex handshaking?
  752.         pop     bx
  753.         je      rpack6          ; e = no
  754.         mov     tmp,ah          ; keep it here
  755.         call    inchr           ; get handshake char
  756.          jnc    rpack5          ; nc = timeout or user intervention
  757.          nop
  758.         and     status,not stat_eol     ; ignore unexpected eol status here.
  759.         cmp     bx,offset data+maxpack+7        ; filled debug buffer yet?
  760.         ja      rpack4f         ; a = yes
  761.         mov     byte ptr[bx],al ; put into buffer for debug
  762.         inc     bx
  763. rpack4f:cmp     al,trans.rsoh   ; soh already?
  764.         jne     rpack4d         ; ne = no
  765.         jmp     rpack7          ; yes
  766. rpack4d:cmp     al,tmp          ; compare received char with handshake
  767.         jne     rpack4c         ; ne = not handshake, try again til timeout
  768. rpack5: and     status,not stat_tmo     ; ignore timeouts on handshake char
  769.  
  770. rpack6: call    deblin          ; do debug display
  771.         cmp     flags.debug,0   ; In debug mode?
  772.         jne     rpack6a         ; ne = yes
  773.         test    flags.capflg,logpkt ; log packets?
  774.         jz      rpack6b         ; z = no
  775. rpack6a:cmp     linecnt,0       ; anything on current line?
  776.         je      rpack6b         ; e = no
  777.         mov     dx,offset crlf  ; finish line with cr/lf
  778.         call    captdol         ;  to log file
  779.  
  780. rpack6b:call    chkcon          ; check console for user interrupt
  781.          nop
  782.          nop
  783.          nop
  784.         test    status,stat_tmo ; did a timeout get us here?
  785.         jz      rpack6c         ; z = no
  786.         mov     pktype,'T'      ; yes, say 'T' type packet (timeout)
  787. rpack6c:mov     bl,tmpflg       ; flags before rpack began
  788.         cmp     bl,flags.cxzflg ; did flags change?
  789.         je      rpack6e         ; e = no
  790.         cmp     flags.cxzflg,'C'; did user type contol-C?
  791.         je      rpack6d         ; e = yes
  792.         cmp     flags.cxzflg,'E'; protocol exit request?
  793.         jne     rpack6e         ; ne = no
  794.         mov     bx,offset cemsg ; user intervention message for error packet
  795.         call    errpack         ; send error message
  796. rpack6d:mov     pack.state,'A'  ; and move to abort state
  797.         call    intmsg          ; show interrupt msg for control-C-E
  798.  
  799. rpack6e:mov     ax,rpkcnt       ; number of bytes received in this packet
  800.         add     fsta.prbyte,ax  ; total received bytes
  801.         adc     fsta.prbyte+2,0 ; propagate carry to high word
  802.         add     fsta.prpkt,1    ; count received packet
  803.         adc     fsta.prpkt+2,0  ;  ripple carry
  804.         mov     ah,pktype       ; return packet type in ah
  805.         cmp     status,stat_suc ; successful so far?
  806.         jne     rpack6x         ; ne = no
  807.         jmp     rskp            ; success exit
  808. rpack6x:ret                     ; failure exit
  809.  
  810. RPACK   ENDP
  811.  
  812. ; Check Console (keyboard). Ret if "action" chars: cr for forced timeout,
  813. ; Control-E for force out Error packet, Control-C for quit work now.
  814. ; Return rskp on Control-X and Control-Z as these are acted upon by higher
  815. ; layers. Consume and ignore anything else.
  816. chkcon: mov     dl,0ffh
  817.         mov     ah,dconio       ; read console
  818.         int     dos
  819.         jz      chkco5          ; z = nothing there
  820.         cmp     al,cr           ; carriage return?
  821.         je      chkco3          ; e = yes, simulate timeout
  822.         cmp     al,'C'-40h      ; Control-C?
  823.         je      chkco1          ; e = yes
  824.         cmp     al,'E'-40h      ; Control-E?
  825.         je      chkco1          ; e = yes
  826.         cmp     al,'X'-40h      ; Control-X?
  827.         je      chkco4          ; e = yes
  828.         cmp     al,'Z'-40h      ; Control-Z?
  829.         je      chkco4          ; record it, take no immmediate action here
  830.         cmp     al,0            ; scan code being returned?
  831.         jne     chkcon          ; ne = no
  832.         mov     ah,dconio       ; read and discard second byte
  833.         mov     dl,0ffh
  834.         int     dos
  835.         jmp     chkcon          ; else unknown, read any more
  836. chkco1: add     al,40h          ; Make Control-C-E printable.
  837.         mov     flags.cxzflg,al ; Remember what we saw.
  838. chkco2: or      status,stat_int ; interrupted
  839.         ret                     ; act   now
  840. chkco3: or      status,stat_tmo ; cr simulates timeout
  841.         ret                     ; act   now
  842. chkco4: add     al,40h          ; make control-X-Z printable
  843.         mov     flags.cxzflg,al ; put into flags
  844.         jmp     rskp            ; do not act on them here
  845. chkco5: cmp     flags.cxzflg,'C'; control-C intercepted elsewhere?
  846.         je      chkco2          ; e = yes
  847.         jmp     rskp            ; else say no immediate action needed
  848.  
  849.  
  850. getlen  proc    near            ; compute packet length for short & long types
  851.                                 ; returns length in pack.argbk1 and length
  852.                                 ; type (0, 1, 3) in pack.argbk3
  853.                                 ; returns length of  data + checksum
  854.         mov     ax,pack.argbk1  ; LEN from packet's second byte
  855.         xor     ah,ah           ; clear unused high byte
  856.         cmp     al,3            ; regular packet has 3 or larger here
  857.         jb      getln0          ; b = long packet
  858.         sub     pack.argbk1,2   ; minus SEQ and TYPE = DATA + CHKSUM
  859.         mov     pack.argbk3,3   ; store assumed length type (3 = regular)
  860.         clc                     ; clear carry for success
  861.         ret
  862.  
  863. getln0: push    cx              ; counter for number of length bytes
  864.         mov     pack.argbk3,0   ; store assumed length type 0 (long)
  865.         mov     cx,2            ; two base-95 digits
  866.         cmp     al,0            ; is this a type 0 (long packet)?
  867.         je      getln5          ; e = yes, go find & check length data
  868. getln1: mov     pack.argbk3,1   ; store length type (1 = extra long)
  869.         mov     cx,3            ; three base 95 digits
  870.         cmp     al,1            ; is this a type 1 (extra long packet)?
  871.         je      getln5          ; e = yes, go find & check length data
  872.         pop     cx
  873.         stc                     ; set carry bit to say error (unkn len code)
  874.         ret
  875. getln5:                         ; chk header chksum and recover binary length
  876.         push    dx              ; save working reg
  877.         xor     ax,ax           ; clear length accumulator, low part
  878.         mov     pack.argbk1,ax  ; clear final length too
  879. getln7: xor     dx,dx           ; ditto, high part
  880.         mov     ax,pack.argbk1  ; length to date
  881.         mul     ninefive        ; multiply accumulation (in ax) by 95
  882.         mov     pack.argbk1,ax  ; save results
  883.         push    cx
  884.         call    inchr           ; read another serial port char into al
  885.          nop                    ; should do something here about failures
  886.          nop
  887.          nop
  888.         pop     cx
  889.         mov     ah,0
  890.         mov     byte ptr[bx],al ; store in buffer
  891.         inc     bx
  892.         add     chksum,ax
  893.         sub     al,20h          ; subtract space, apply unchar()
  894.         add     pack.argbk1,ax  ; add to overall length count
  895.         loop    getln7          ; cx preset earlier for type 0 or type 1
  896.         mov     dx,chksum       ; get running checksum
  897.         shl     dx,1            ; get two high order bits into dh
  898.         shl     dx,1
  899.         and     dh,3            ; want just these two bits
  900.         shr     dl,1            ; put low order part back
  901.         shr     dl,1
  902.         add     dl,dh           ; add low order byte to two high order bits
  903.         and     dl,03fh         ; chop to lower 6 bits (mod 64)
  904.         add     dl,20h          ; apply tochar()
  905.         push    dx
  906.         call    inchr           ; read another serial port char
  907.          nop
  908.          nop
  909.          nop
  910.         pop     dx
  911.         mov     ah,0
  912.         mov     byte ptr[bx],al ; store in buf for debug
  913.         inc     bx
  914.         add     chksum,ax
  915.         cmp     dl,al           ; our vs their checksum, same?
  916.         pop     dx              ; unsave regs (preserves flags)
  917.         pop     cx
  918.         je      getln9          ; e = checksums match, success
  919.         or      status,stat_chk ; checksum failure
  920.         stc                     ; else return carry set for error
  921.         ret
  922. getln9: clc                     ; clear carry (say success)
  923.         ret
  924. getlen  endp
  925.  
  926. ; Get char from serial port into al, with timeout and console check.
  927. ; Ret carry clear if timeout or console char, Ret carry set if EOL seen,
  928. ; Rskp on other port chars. Fairflg allows occassional reads from console
  929. ; before looking at serial port, to avoid latchups.
  930. inchr:  mov     timeit,0        ; reset timeout flag (do each char separately)
  931.         push    bx              ; save a reg
  932.         cmp     fairflg,maxpack ; look at console first every now and then
  933.         jbe     inchr1          ; be = not console's turn yet
  934.         call    chkcon          ; check console
  935.          jmp    inchr5          ; got cr or control-c/e input
  936.          nop
  937.         mov     fairflg,0       ; reset fairness flag for next time
  938. inchr1: call    prtchr          ; Is there a serial port character to read?
  939.          jmp    inchr6          ; Got one (in al); else does rskp.
  940.          nop
  941.         call    chkcon          ; check console
  942.          jmp    inchr5          ; got cr or control-c/e input
  943.          nop
  944. inchr2: cmp     flags.timflg,0  ; Are timeouts turned off?
  945.         je      inchr1          ; e = yes, just check for more input.
  946.         cmp     trans.stime,0   ; Doing time outs?
  947.         je      inchr1          ; e = no, just go check for more input.
  948.         push    cx              ; save regs
  949.         push    dx              ; Stolen from Script code.
  950.         cmp     timeit,0        ; have we gotten time of day for first fail?
  951.         jne     inchr4          ; ne = yes, just compare times
  952.         mov     ah,gettim       ; get DOS time of day
  953.         int     dos             ; ch = hh, cl = mm, dh = ss, dl = 0.01 sec
  954.         xchg    ch,cl           ; get ordering of low byte = hours, etc
  955.         mov     word ptr rptim,cx ; hours and minutes
  956.         xchg    dh,dl
  957.         mov     word ptr rptim+2,dx ; seconds and fraction
  958.         mov     bl,trans.stime  ; our desired timeout interval (seconds)
  959.         mov     bh,0            ; one byte's worth
  960.         mov     temp,bx         ; work area
  961.         mov     bx,2            ; start with seconds field
  962. inchr3: mov     ax,temp         ; desired timeout interval, working copy
  963.         add     al,rptim[bx]    ; add current tod digit interval
  964.         adc     ah,0
  965.         xor     dx,dx           ; clear high order part thereof
  966.         div     sixzero         ; compute number of minutes or hours
  967.         mov     temp,ax         ; quotient, for next time around
  968.         mov     rptim[bx],dl    ; put normalized remainder in timeout tod
  969.         dec     bx              ; look at next higher order time field
  970.         cmp     bx,0            ; done all time fields?
  971.         jge     inchr3          ; ge = no
  972.         cmp     rptim[0],24     ; normalize hours
  973.         jl      inchr3a         ; l = not 24 hours or greater
  974.         sub     rptim[0],24     ; discard part over 24 hours
  975. inchr3a:mov     timeit,1        ; say have tod of timeout
  976.  
  977. inchr4: mov     ah,gettim       ; compare present tod versus timeout tod
  978.         int     dos             ; get the time of day
  979.         sub     ch,rptim        ; hours difference, ch = (now - timeout)
  980.         je      inchr4b         ; e = same, check mmss.s
  981.         jl      inchr4d         ; l = we are early
  982.         cmp     ch,12           ; hours difference, large or small?
  983.         jge     inchr4d         ; ge = we are early
  984.         jl      inchr4c         ; l = we are late, say timeout
  985. inchr4b:cmp     cl,rptim+1      ; minutes, hours match
  986.         jb      inchr4d         ; b = we are early
  987.         ja      inchr4c         ; a = we are late
  988.         cmp     dh,rptim+2      ; seconds, hours and minutes match
  989.         jb      inchr4d         ; b = we are early
  990.         ja      inchr4c         ; a = we are late
  991.         cmp     dl,rptim+3      ; hundredths of seconds, hhmmss match
  992.         jb      inchr4d         ; b = we are early
  993. inchr4c:or      status,stat_tmo ; say timeout
  994.         pop     dx
  995.         pop     cx
  996.         jmp     inchr5          ; timeout exit
  997. inchr4d:pop     dx
  998.         pop     cx
  999.         jmp     inchr1          ; not timed out yet
  1000.  
  1001. inchr5: pop     bx              ; here with console char or timeout
  1002.         clc                     ; clear carry bit
  1003.         ret                     ; failure
  1004.  
  1005. inchr6: pop     bx              ; here with char in al from port
  1006.         and     al,parmsk       ; apply 7/8 bit parity mask
  1007.         or      al,al           ; null char?
  1008.         jnz     inchr6b         ; nz = no
  1009. inchr6a:jmp     inchr           ; ignore the null, read another char
  1010. inchr6b:cmp     al,del          ; ascii del byte?
  1011.         je      inchr6a         ; e = yes, ignore it too
  1012.         inc     rpkcnt          ; count received byte
  1013.         cmp     al,trans.reol   ; eol char we want?
  1014.         je      inchr7          ; e = yes, ret with carry set
  1015.         jmp     rskp            ; char is in al
  1016. inchr7: or      status,stat_eol ; set status appropriately
  1017.         stc                     ; set carry to say eol seen
  1018.         ret                     ; and return qualified failure
  1019.  
  1020. ; sleep for the # of seconds in al
  1021. ; Preserve all regs. Added console input forced timeout 21 March 1987 [jrd]
  1022. sleep   proc    near
  1023.         push    ax
  1024.         push    cx
  1025.         push    dx
  1026.         push    ax              ; save argument
  1027.         mov     ah,gettim       ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
  1028.         int     dos             ; get current time
  1029.         pop     ax              ; restore desired # of seconds
  1030.         add     dh,al           ; add # of seconds
  1031. sleep1: cmp     dh,60           ; too big for seconds?
  1032.         jb      sleep2          ; no, keep going
  1033.         sub     dh,60           ; yes, subtract a minute's overflow
  1034.         inc     cl              ; and add one to minutes field
  1035.         cmp     cl,60           ; did minutes overflow?
  1036.         jb      sleep1          ; no, check seconds again
  1037.         sub     cl,60           ; else take away an hour's overflow
  1038.         inc     ch              ; add it back in hours field
  1039.         jmp     sleep1          ; and keep checking
  1040. sleep2: mov     time,cx         ; store desired ending time,  hh,mm
  1041.         mov     time+2,dx       ; ss, .s
  1042. sleep3: call    chkcon          ; check console for user timeout override
  1043.          jmp    short sleep5    ; have override
  1044.          nop                    ;  three bytes for rskp
  1045.         mov     ah,gettim       ; get time
  1046.         int     dos             ; from dos
  1047.         sub     ch,byte ptr time+1 ; hours difference, ch = (now - timeout)
  1048.         je      sleep4          ; e = hours match, check mmss.s
  1049.         jl      sleep3          ; l = we are early
  1050.         cmp     ch,12           ; hours difference, large or small?
  1051.         jge     sleep3          ; ge = we are early
  1052.         jl      sleep5          ; l = we are late, exit now
  1053. sleep4: cmp     cl,byte ptr time ; check minutes, hours match
  1054.         jb      sleep3          ; b = we are early
  1055.         ja      sleep5          ; a = over limit, time to exit
  1056.         cmp     dx,time+2       ; check seconds and fraction, hhmm match
  1057.         jb      sleep3          ; b = we are early
  1058. sleep5: pop     dx
  1059.         pop     cx
  1060.         pop     ax
  1061.         ret
  1062. sleep   endp
  1063.                                 ; Packet Debug display routines
  1064. rcvdeb: cmp     flags.debug,0   ; In debug mode?
  1065.         jne     rcvde1          ; ne = yes
  1066.         test    flags.capflg,logpkt ; log packets?
  1067.         jnz     rcvde1          ; e = yes
  1068.         ret                     ; no
  1069. rcvde1: mov     debflg,'R'      ; say receiving
  1070.         jmp     deb1
  1071.  
  1072. snddeb: cmp     flags.debug,0   ; In debug mode?
  1073.         jne     sndde1          ; ne = yes
  1074.         test    flags.capflg,logpkt ; log packets?
  1075.         jnz     sndde1          ; yes
  1076.         ret                     ; no
  1077. sndde1: mov     debflg,'S'      ; say sending
  1078.  
  1079. deb1:   push    ax              ; Debug. Packet display.
  1080.         push    bx
  1081.         push    cx              ; save some regs.
  1082.         push    dx
  1083.         push    di
  1084.         test    flags.debug,logpkt      ; is debug active (vs just logging)?
  1085.         jz      deb1d           ; z = no, just logging
  1086.         cmp     fmtdsp,0        ; non-formatted display?
  1087.         je      deb1d           ; e = yes, skip extra line clearing
  1088.         cmp     debflg,'R'      ; receiving?
  1089.         je      deb1a           ; e = yes
  1090.         call    sppos           ; spack: cursor position
  1091.         jmp     deb1b
  1092. deb1a:  call    rppos           ; rpack: cursor position
  1093. deb1b:  call    clearl          ; clear the line
  1094.         mov     dx,offset crlf
  1095.         mov     ah,prstr        ; display
  1096.         int     dos
  1097.         call    clearl          ; clear debug line and line beneath
  1098. deb1e:  cmp     debflg,'R'      ; receiving?
  1099.         je      deb1c           ; e = yes
  1100.         call    sppos           ; reposition cursor for spack:
  1101.         jmp     deb1d
  1102. deb1c:  call    rppos           ; reposition cursor for rpack:
  1103. deb1d:  mov     dx,offset spmes ; spack: message
  1104.         cmp     debflg,'R'
  1105.         jne     deb2
  1106.         mov     dx,offset rpmes ; rpack: message
  1107. deb2:   call    captdol         ; record dollar terminated string in Log file
  1108.         mov     linecnt,7       ; number of columns used so far
  1109.         pop     di
  1110.         pop     dx
  1111.         pop     cx
  1112.         pop     bx
  1113.         pop     ax
  1114.         ret                     ; done
  1115.  
  1116. ; Display/log packet chars processed so far.
  1117. ; Displays chars from pktptr to bx, both are pointers.
  1118. ; Enter with bx = offset of next new char. All registers preserved
  1119. deblin: cmp     flags.debug,0   ; In debug mode?
  1120.         jne     debln0          ; ne = yes
  1121.         test    flags.capflg,logpkt ; log packets?
  1122.         jnz     debln0          ; nz = yes
  1123.         ret                     ; else  nothing to do
  1124. debln0: push    cx
  1125.         push    dx
  1126.         push    di
  1127.         mov     di,pktptr       ; starting place for debug analysis
  1128.         mov     cx,bx           ; place for next new char
  1129.         sub     cx,di           ; minus where we start = number chars to do
  1130.         cmp     cx,0
  1131.         jle     debln5          ; le = nothing to do
  1132. debln2: cmp     di,offset data+maxpack+10 ; end of buffer data?
  1133.         ja      debln5          ; a = all done
  1134.         push    cx              ; save loop counter
  1135.         cmp     linecnt,70
  1136.         jb      debln3          ; b = not yet, get next data char
  1137.         mov     dx,offset crlf  ; break line with cr/lf
  1138.         call    captdol         ; and in log file
  1139.         mov     linecnt,0       ; setup for next line
  1140. debln3: mov     dl,byte ptr [di]; get char
  1141.         test    dl,80h          ; high bit set?
  1142.         jz      debln3b         ; z = no
  1143.         push    dx              ; save char in dl
  1144.         mov     dl,7eh          ; show tilde char for high bit set
  1145.         call    captchr         ; record in Log file
  1146.         inc     linecnt         ; count displayed column
  1147.         cmp     linecnt,70      ; exhausted line count yet?
  1148.         jb      debln3a         ; b = not yet
  1149.         mov     dx,offset crlf  ; break line with cr/lf
  1150.         call    captdol         ; and in log file
  1151.         mov     linecnt,0       ; setup for next line
  1152. debln3a:pop     dx
  1153.         and     dl,7fh          ; get lower seven bits here
  1154. debln3b:cmp     dl,' '          ; control char?
  1155.         jae     debln4          ; ae = no
  1156.         add     dl,40h          ; uncontrollify the char
  1157.         push    dx              ; save char in dl
  1158.         mov     dl,5eh          ; show caret before control code
  1159.         call    captchr         ; record in Log file
  1160.         inc     linecnt         ; count displayed column
  1161.         cmp     linecnt,70      ; exhausted line count yet?
  1162.         jb      debln3c         ; b = not yet
  1163.         mov     dx,offset crlf  ; break line with cr/lf
  1164.         call    captdol         ; and in log file
  1165.         mov     linecnt,0       ; setup for next line
  1166. debln3c:pop     dx              ; recover char in dl
  1167.  
  1168. debln4: call    captchr         ; record char in dl in the log file
  1169.         inc     di              ; done with this char, point to next
  1170.         inc     linecnt         ; one more column used on screen
  1171.         pop     cx              ; recover loop counter
  1172.         loop    debln2          ; get next data char
  1173. debln5: pop     di
  1174.         pop     dx
  1175.         pop     cx
  1176.         ret
  1177.  
  1178. captdol proc    near            ; write dollar sign terminated string in dx
  1179.                                 ; to the capture file (Log file). [jrd]
  1180.         push    ax              ; save regs
  1181.         push    si
  1182.         mov     si,dx           ; point to start of string
  1183. captdo1:lodsb                   ; get   a byte into al
  1184.         cmp     al,'$'          ; at the end yet?
  1185.         je      captdo2         ; e = yes
  1186.         mov     dl,al
  1187.         call    captchr         ; Log the char
  1188.         jmp     short captdo1   ; repeat until dollar sign is encountered
  1189. captdo2:pop     si
  1190.         pop     ax
  1191.         ret
  1192. captdol endp
  1193.  
  1194. captcx  proc    near            ; record counted string, starts in di, count
  1195.                                 ;  is in cx. [jrd]
  1196.         jcxz    captc2          ; if count = zero, exit now
  1197.         push    ax              ; save regs
  1198.         push    cx
  1199.         push    si
  1200.         mov     si,di           ; get start address
  1201. captc1: lodsb                   ; get a char into al
  1202.         call    cptchr          ; record it, cptchr is in msster.asm
  1203.         loop    captc1          ; do this cx times
  1204.         pop     si
  1205.         pop     cx
  1206.         pop     ax
  1207. captc2: ret
  1208. captcx  endp
  1209.  
  1210. captchr proc    near            ; record char in dl into the Log file
  1211.         push    ax
  1212.         cmp     flags.debug,0   ; debug display active?
  1213.         jz      captch1         ; z = no.
  1214.         mov     ah,conout
  1215.         int     dos             ; display char in dl
  1216. captch1:test    flags.capflg,logpkt ; logging active?
  1217.         jz      captch2         ; z = no
  1218.         mov     al,dl           ; where cptchr wants it
  1219.         call    cptchr          ; record the char, cptchr is in msster.asm
  1220. captch2:pop     ax
  1221.         ret
  1222. captchr endp
  1223.  
  1224. ; Jumping to this location is like retskp.  It assumes the instruction
  1225. ;   after the call is a jmp addr.
  1226.  
  1227. RSKP    PROC    NEAR
  1228.         pop     bp
  1229.         add     bp,3
  1230.         push    bp
  1231.         ret
  1232. RSKP    ENDP
  1233.  
  1234. ; Jumping here is the same as a ret.
  1235.  
  1236. R       PROC    NEAR
  1237.         ret
  1238. R       ENDP
  1239.  
  1240. code    ends
  1241.         end
  1242.