home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccdos / ccxibm.asm < prev    next >
Assembly Source File  |  2020-01-01  |  143KB  |  3,066 lines

  1. ; File CCXIBM.ASM
  2. ; Kermit system dependent module for IBM-PC
  3.  
  4. ;CHINESE
  5. ifdef   MSDOS
  6.         include msxibm.dat
  7. else
  8.         include ccxibm.dat
  9. endif
  10.  
  11. code    segment public 'code'
  12.         extrn   comnd:near, dopar:near, defkey:near, lclyini:near
  13.         extrn   sleep:near, atsclr:near, scrseg:near,scrloc:near, scrsync:near
  14.         extrn   atoi:near, strlen:near, prtscr:near, scroff:near, scron:near
  15.         extrn   srchkb:near, srchkw:near, prompt:near, statc:near
  16.         assume  cs:code, ds:datas
  17.  
  18. ; local initialization
  19.  
  20. lclini  proc    near
  21.         mov     flags.comflg,1  ; assume COM1 for communications port
  22. ;;;     call    coms2           ; setup serial port modem.info for COM1
  23.         call    model           ; get model of IBM machine
  24.         call    lclyini         ; let other modules initialize too...
  25.         ret
  26. lclini  endp
  27.  
  28. ; this is called by Kermit initialization.  It checks the
  29. ; number of disks on the system, sets the drives variable
  30. ; appropriately.  Returns normally.
  31.  
  32. DODISK  PROC    NEAR
  33.         int     mconf                   ; Get equipment configuration
  34.         mov     ah,al                   ; Store AL value for a bit
  35.         and     al,01H                  ; First, look at bit 0
  36.         jz      dodsk0                  ; No disk drives -- forget it
  37.         mov     al,ah                   ; Get back original value
  38.         mov     cl,6                    ; Shift over bits 6 and 7
  39.         shr     al,cl                   ; To positions 0 and 1
  40.         inc     al                      ; Want 1 thru 4 (not 0 thru 3)
  41. dodsk0: mov     drives,al               ; Remember how many.
  42.         ret
  43. DODISK  ENDP
  44.  
  45. ; The IBM PC's. If jr then redo IBM baud rate with jr's values. [jrd]
  46. model   proc    near
  47.         mov     isps2,0                 ; PS/2 present indicator
  48.         push    es
  49.         push    ax                      ; get IBM model code at F000:FFFEh
  50.         mov     ax,0f000h               ; address ROM
  51.         mov     es,ax
  52.         mov     al,byte ptr es:[0fffeh] ; get model id byte
  53.         cmp     al,0fdh                 ; PC jr?
  54.         jne     modelx                  ; ne = no
  55.         push    ds
  56.         pop     es                      ; set es to datas segment
  57.         mov     si,offset bddat         ; regular IBM baud rate table
  58.         mov     di,offset jrbddat       ; PCjr baud rate table
  59.         mov     cl,baudlen              ; number of words to copy
  60.         mov     ch,0
  61.         cld
  62.         rep     movsw                   ; copy PCjr values to IBM table
  63.         jmp     short modelx
  64. model2: mov     ah,0ch                  ; AT and PS/2 configuration call
  65.         mov     al,0
  66.         int     15h                     ; IBM Bios
  67.         jc      modelx                  ; c = no information
  68.         cmp     word ptr es:[bx+2],040fch ; PS/2 model 50?
  69.         je      model3                  ; e = yes
  70.         cmp     word ptr es:[bx+2],050fch ; PS/2 model 60?
  71.         je      model3                  ; e = yes
  72.         cmp     byte ptr es:[bx+2],0f8h ; PS/2 model 80?
  73.         jne     modelx                  ; ne = no
  74. model3: mov     isps2,1                 ; say real PS/2 for IRQ setting
  75. modelx: pop     ax
  76.         pop     es
  77.         ret
  78. model   endp
  79.  
  80. ; show the definition of a key.  The terminal argument block (which contains
  81. ; the address and length of the definition tables) is passed in ax.
  82. ; Returns a string to print in AX, length of same in CX.
  83. ; Returns normally. Obsolete, name here for external reference only.
  84. showkey proc    near
  85.         ret                             ; return
  86. showkey endp
  87.  
  88. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  89. ; Uses byte mdmhand, the modem line status register. [jrd]
  90. shomodem proc   near
  91.         mov     ah,cmcfm                ; get a confirm
  92.         call    comnd
  93.          jmp    r                       ; no confirm
  94.          nop
  95. ;        mov     dx,offset msmsg7        ; no modem status for network
  96.         mcmsg   msmsg7,cmsmsg7
  97.         call    getmodem                ; get modem status
  98.         mov     mdmhand,al
  99.         mov     ah,prstr
  100. ;        mov     dx,offset msmsg1        ; modem ready msg
  101.         mcmsg   msmsg1,cmsmsg1
  102.         test    mdmhand,20h             ; is DSR asserted?
  103.         jz      shomd1                  ; z = no
  104. ;        mov     dx,offset msmsg2        ; say not asserted
  105.         mcmsg   msmsg2,cmsmsg2
  106. shomd1: int     dos
  107. ;        mov     dx,offset msmsg3        ; CD asserted msg
  108.         mcmsg   msmsg3,cmsmsg3
  109.         test    mdmhand,80h             ; CD asserted?
  110.         jz      shomd2                  ; z = no
  111. ;        mov     dx,offset msmsg4        ; say not asserted
  112.         mcmsg   msmsg4,cmsmsg4
  113. shomd2: int     dos
  114. ;        mov     dx,offset msmsg5        ; CTS asserted msg
  115.         mcmsg   msmsg5,cmsmsg5
  116.         test    mdmhand,10h             ; CTS asserted?
  117.         jz      shomd3                  ; z = no
  118. ;        mov     dx,offset msmsg6        ; say not asserted
  119.         mcmsg   msmsg6,cmsmsg6
  120. shomd3: mov     ah,prstr
  121.         int     dos
  122.         jmp     rskp
  123. shomodem endp
  124.  
  125. ; Get modem status and set global byte mdmhand. Preserve all registers.
  126. getmodem proc   near                    ; gets modem status upon request
  127.         cmp     portin,-1               ; done any port yet?
  128.         jne     getmod1                 ; ne = yes
  129.         mov     bl,flags.comflg         ; pass current port ident
  130.         call    comstrt                 ; do SET PORT command now
  131.          ret                            ; failed to set port
  132.          nop
  133.          nop
  134. getmod1:mov     al,0                    ; assume nothing is on
  135.         cmp     clone,'N'               ; Network?
  136.         je      getmodx                 ; e = yes, no status
  137.         cmp     clone,'B'               ; Bios?
  138.         je      getmod2                 ; e = yes
  139.         cmp     flags.comflg,0          ; null port?
  140.         je      getmodx                 ; e = yes, no status
  141.         mov     dx,mst                  ; hardware
  142.         inc     dx                      ; uart status reg
  143.         in      al,dx
  144.         jmp     short getmodx
  145. getmod2:mov     ah,3                    ; ask Bios for modem status into al
  146.         push    dx
  147.         mov     dl,flags.comflg         ; get port id
  148.         cmp     dl,'0'                  ; ascii?
  149.         jb      getmod3                 ; b = no
  150.         sub     dl,'0'                  ; remove ascii bias
  151. getmod3:int     rs232
  152.         pop     dx
  153. getmodx:mov     ah,0                    ; return status in al
  154.         ret
  155. getmodem endp
  156.  
  157. ; Clear the input buffer. This throws away all the characters in the
  158. ; serial interrupt buffer.  This is particularly important when
  159. ; talking to servers, since NAKs can accumulate in the buffer.
  160. ; Returns normally.
  161.  
  162. CLRBUF  PROC    NEAR
  163.         cli
  164.         mov     srcpnt,offset source    ; receive circular buffer
  165.         mov     count,0                 ; receive circular buffer
  166.         sti
  167.         call    prtchr                  ; empty any intermediate (net) buffers
  168.          nop                            ; got a char, clear again
  169.          nop
  170.          nop
  171.         cli
  172.         mov     srcpnt,offset source    ; receive circular buffer
  173.         mov     count,0                 ; receive circular buffer
  174.         mov     xmtcnt,0                ; network output buffer count
  175.         sti
  176.         ret
  177. CLRBUF  ENDP
  178.  
  179. ; Clear to the end of the current line.  Returns normally.
  180. ; Upgraded for Topview compatibility. [jrd]
  181. CLEARL  PROC    NEAR
  182.         push    ax
  183.         push    bx
  184.         push    dx
  185.         mov     ah,3                    ; Clear to end of line
  186.         mov     bh,0
  187.         int     video                   ; Get current cursor position into dx
  188.         mov     ax,dx                   ; Topview compatible clear line
  189.         mov     bh,ah                   ; same row
  190.         mov     bl,byte ptr low_rgt     ; last column
  191.         call    atsclr                  ; clear from ax to bx, screen coord
  192.         pop     dx
  193.         pop     bx
  194.         pop     ax
  195.         ret
  196. CLEARL  ENDP
  197.  
  198. ; This routine blanks the screen.  Returns normally.
  199. ; Upgraded to Topview compatiblity. [jrd]
  200. CMBLNK  PROC    NEAR
  201.         push    ax
  202.         push    bx
  203.         xor     ax,ax                   ; from screen loc 0,0
  204.         mov     bx,low_rgt      ; to end of text screen (lower right corner)
  205.         inc     bh                      ; include status line
  206.         call    atsclr               ; do Topview compatible clear, in msyibm
  207.         pop     bx
  208.         pop     ax
  209.         ret
  210. CMBLNK  ENDP
  211.  
  212. ; Locate: homes the cursor.  Returns normally.
  213.  
  214. LOCATE  PROC    NEAR
  215.         mov dx,0                        ; Go to top left corner of screen
  216.         jmp poscur
  217. LOCATE  ENDP
  218.  
  219. ; Position the cursor according to contents of DX:
  220. ; DH contains row, DL contains column.  Returns normally.
  221. POSCUR  PROC    NEAR
  222.         push    ax
  223.         push    bx
  224.         mov     ah,2                    ; Position cursor
  225.         mov     bh,0                    ; page 0
  226.         int     video
  227.         pop     bx
  228.         pop     ax
  229.         ret
  230. POSCUR  ENDP
  231.  
  232. ; Delete a character from the terminal.  This works by printing
  233. ; backspaces and spaces.  Returns normally.
  234.  
  235. DODEL   PROC    NEAR
  236.         mov     ah,prstr
  237.         mov     dx,offset delstr        ; Erase weird character
  238.         int     dos
  239.         ret
  240. DODEL   ENDP
  241.  
  242. ; Move the cursor to the left margin, then clear to end of line.
  243. ; Returns normally.
  244.  
  245. CTLU    PROC    NEAR
  246.         mov     ah,prstr
  247.         mov     dx,offset clrlin
  248.         int     dos
  249.         call    clearl
  250.         ret
  251. CTLU    ENDP
  252.  
  253.  
  254. BEEP    PROC    NEAR
  255.         push    ax
  256.         push    cx
  257.         mov     al,10110110B    ; Gen a short beep (long one losses data.)
  258.         out     timercmd,al     ; set Timer to to mode 3
  259.         mov     ax,1512         ; divisor, for frequency
  260.         out     timer2data,al   ; send low byte first
  261.         mov     al,ah
  262.         out     timer2data,al
  263.         in      al,ppi_port     ; get 8255 Port B setting
  264.         or      al,3            ; turn on speaker and timer
  265.         out     ppi_port,al     ; start speaker and timer
  266.         push    ax
  267.         mov     ax,40           ; 40 millisecond beep, calibrated time
  268.         call    pcwait
  269.         pop     ax
  270.         in      al,ppi_port
  271.         and     al,0fch         ; turn off speaker and timer
  272.         out     ppi_port,al
  273.         pop     cx
  274.         pop     ax
  275.         ret
  276. BEEP    ENDP
  277.  
  278. ; write a line in inverse video at the bottom of the screen...
  279. ; the line is passed in dx, terminated by a $.  Returns normally.
  280. putmod  proc    near
  281.         push    ax              ; save regs
  282.         push    bx
  283.         push    cx
  284.         push    dx              ; preserve message
  285.         mov     bl,scbattr      ; screen attributes at Kermit init time
  286.         and     bl,77h          ; get colors, omit bright and blink
  287.         rol     bl,1            ; interchange fore and background
  288.         rol     bl,1
  289.         rol     bl,1
  290.         rol     bl,1
  291.         mov     bh,0            ; preset page 0
  292.         mov     temp,bx         ; temp = page 0, reverse video
  293.         mov     dx,low_rgt      ; ending location is lower right corner
  294.         inc     dh              ;  of status line
  295.         mov     cx,dx           ; start is status left side
  296.         xor     cl,cl           ; left side
  297.         mov     ax,600h         ; scroll to clear the line
  298.         mov     bh,byte ptr temp ; set inverse video attributes
  299.         int     video
  300.         mov     dx,low_rgt      ; last text line
  301.         inc     dh              ; status line
  302.         xor     dl,dl           ; left side
  303.         call    poscur
  304.         pop     si              ; get message back
  305.         mov     cx,1            ; only one char at a time
  306.         xor     bh,bh           ; page 0
  307.         cld
  308. putmo1: lodsb                   ; get a byte
  309.         cmp     al,'$'          ; end of string?
  310.         je      putmo2
  311.         push    si              ; save si
  312.         push    ax              ; and the char
  313.         call    poscur
  314.         inc     dl              ; increment for next write
  315.         pop     ax              ; recover char
  316.         mov     ah,9            ; try this
  317.         mov     bx,temp         ; page 0, inverse video
  318.         int     video
  319.         pop     si              ; recover pointer
  320.         jmp     putmo1
  321. putmo2: pop     cx
  322.         pop     bx
  323.         pop     ax
  324.         ret
  325. putmod  endp
  326.  
  327. ; clear the mode line written by putmod.  Returns normally.
  328. clrmod  proc    near
  329.         push    ax              ; save regs
  330.         push    bx
  331.         push    cx
  332.         push    dx
  333.         mov     ax,600h         ; do a scroll up
  334.         mov     dx,low_rgt      ; ending location is lower right corner
  335.         inc     dh              ;  of status line
  336.         mov     cx,dx           ; start is status left side
  337.         xor     cl,cl           ; left side
  338. ;************************ modified in Dec.15,1989
  339.     mov ax,cx
  340.     mov bx,dx
  341.     call    atsclr
  342. ;       mov     bh,scbattr      ; use screen attributes at Kermit init time
  343. ;       int     video
  344. ;************************ modified in Dec.15,1989
  345.         pop     dx
  346.         pop     cx
  347.         pop     bx
  348.         pop     ax
  349.         ret
  350. clrmod  endp
  351.  
  352. ; put a help message on the screen.  This one uses reverse video...
  353. ; pass the message in ax, terminated by a null.  Returns normally.
  354. puthlp  proc    near
  355.         push    bx              ; save regs
  356.         push    cx
  357.         push    dx
  358.         push    si
  359.         push    ax              ; preserve this
  360.         cld
  361.         mov     bl,scbattr      ; screen attributes at Kermit init time
  362.         and     bl,77h          ; get colors, omit bright and blink
  363.         rol     bl,1            ; interchange fore and background
  364.         rol     bl,1
  365.         rol     bl,1
  366.         rol     bl,1
  367.         mov     bh,0            ; preset page 0
  368.         mov     temp,bx         ; temp = page 0, reverse video
  369.  
  370.         mov     si,ax           ; point to it
  371.         mov     dh,1            ; init counter
  372. puthl1: lodsb                   ; get a byte
  373.         cmp     al,lf           ; linefeed?
  374.         jne     puthl2          ; no, keep going
  375.         inc     dh              ; count it
  376.         jmp     puthl1          ; and keep looping
  377. puthl2: cmp     al,0            ; end of string?
  378.         jne     puthl1          ; no, keep going
  379.         mov     ax,600h         ; scroll to clear window
  380.         xor     cx,cx           ; from top left
  381.         mov     dl,4fh          ; to bottom right of needed piece
  382.         mov     bh,70h          ; inverse video
  383.         mov     bh,bl           ; inverse video
  384.         int     video
  385.         call    locate          ; home cursor
  386.         mov     bx,0070h        ; bh = page 0, bl = inverse video
  387.         mov     bx,temp
  388.         mov     cx,1            ; one char at a time
  389.         cld                     ; scan direction is forward
  390.         pop     si              ; point to string again
  391. puthl3: lodsb                   ; get a byte
  392.         cmp     al,0            ; end of string?
  393.         je      puthl4          ; yes, stop
  394.         push    si              ; save around bios call
  395.         cmp     al,' '          ; printable?
  396.         jb      puth21          ; b = no
  397.         mov     ah,9            ; write char at current cursor position
  398.         int     video           ; do the Bios int 10h call
  399.         inc     dl              ; point to next column
  400.         jmp     puth23          ; move cursor there
  401. puth21: cmp     al,cr           ; carriage return?
  402.         jne     puth22          ; ne = no
  403.         xor     dl,dl           ; set to column zero
  404.         jmp     puth23
  405. puth22: cmp     al,lf           ; line feed?
  406.         jne     puth23
  407.         inc     dh              ; go to next line
  408. puth23: mov     ah,2            ; set cursor position to dx
  409.         int     video
  410.         pop     si              ; restore pointer
  411.         jmp     puthl3          ; and keep going
  412. puthl4: mov     dh,byte ptr low_rgt+1   ; go to last line
  413.         inc     dh
  414.         xor     dl,dl
  415.         call    poscur          ; position cursor
  416.         pop     si
  417.         pop     dx
  418.         pop     cx
  419.         pop     bx
  420.         ret
  421. puthlp  endp
  422.                                         ; begin Terminal set & status code
  423.  
  424. ; SET Term parameters, especially for use with VT100 emulator. [jrd]
  425. ; Taken from work done originally by James Harvey IUPUI.
  426. ; VTS is called only by mssset to set terminal type and characteristics.
  427. ; Enter via direct jmp. Exit rskp for success, ret for failure.
  428. VTS     proc    near                    ; SET TERM whatever
  429.         mov     ah,cmkey                ; Parse another keyword
  430. ;        mov     bx,offset vthlp         ; Use this help
  431.         mcmsgb  vthlp,cvthlp
  432.         mov     dx,offset vttbl         ; Use this table
  433.         call    comnd
  434.          jmp    r
  435.          nop
  436.         cmp     bh,1H                   ; marker for terminal type?
  437.         je      vsetu0                  ; e = yes
  438.         cmp     bh,2h                   ; marker for set term color?
  439.         jne     vset1                   ; ne = no
  440.         jmp     vsetu2                  ; e = yes
  441. vset1:  cmp     bh,3h                   ; marker for character set?
  442.         je      vsetu3                  ; e = yes
  443.         cmp     bh,4h                   ; marker for roll back control?
  444.         je      vsetu4                  ; e = yes
  445.         cmp     bh,10h                  ; marker for clear-screen?
  446.         jne     vset1a                  ; ne = no
  447.         mov     ah,cmcfm                ; yes
  448.         call    comnd
  449.          jmp    r
  450.          nop
  451.         mov     vtclear,1               ; set trigger for emulator startup
  452.         jmp     rskp                    ; return successfully
  453.  
  454. vset1a: cmp     bh,8h                   ; marker for graphics type?
  455.         jne     short vsetu1            ; ne = no, dispatch on bl
  456.         jmp     vsetu8                  ; yes
  457.  
  458. vsetu0: mov     temp,bx                 ; set terminal type
  459.         mov     ah,cmcfm
  460.         call    comnd                   ; Get a confirm
  461.          jmp    r                       ; Didn't get a confirm
  462.          nop
  463.         mov     bx,temp
  464.         mov     flags.vtflg,bl          ; Set the terminal emulation type
  465.         mov     tekflg,0                ; clear Tek sub mode
  466.         jmp     rskp
  467.  
  468. vsetu1: mov     bh,0                    ; remove marker bits in bh
  469.         shl     bx,1                    ; Make bx a word index
  470.         jmp     vtrtns[bx]              ; Dispatch
  471.  
  472. vsetu3: mov     ah,cmkey                ; Set Term character set
  473.         mov     bx,0                    ; Use character set table for help
  474.         mov     dx,offset chatab        ; Use character set table
  475.         call    comnd
  476.          jmp    r                       ; failure
  477.          nop
  478.         mov     temp,bx
  479.         mov     ah,cmcfm                ; get a confirm
  480.         call    comnd
  481.          jmp    vsetu0                  ; did not get a confirm
  482.          nop
  483.         mov     ax,temp                 ; recover value
  484.         mov     vtemu.vtchset,al        ; set default character set
  485.         jmp     rskp                    ; return successfully
  486.  
  487. vsetu4: mov     ah,cmkey                ; Set Term Roll On/Off, auto roll back
  488.         mov     bx,0                    ; Use on/off table as help
  489.         mov     dx,offset ontab         ; Use on/off table
  490.         call    comnd
  491.          jmp    r                       ; bad keyword
  492.          nop
  493.         mov     temp,bx
  494.         mov     ah,cmcfm                ; get a confirm
  495.         call    comnd
  496.          jmp    r                       ; did not get a confirm
  497.          nop
  498.         mov     bx,temp
  499.         mov     vtroll,bl               ; set roll state (0=no auto rollback)
  500.         jmp     rskp                    ; return successfully
  501.  
  502.                                      ; Set Term Color foreground, background
  503. vsetu2: mov     ah,cmtxt                ; get number(s) after set term color
  504. ;        mov     dx,offset colhlp        ; use this help
  505.         mcmsg   colhlp,ccolhlp
  506.         mov     bx,offset rdbuf         ; temp buffer
  507.         mov     rdbuf,0                 ; clear the buffer
  508.         call    comnd
  509.          jmp    r
  510.          nop
  511.         cmp     ah,0                    ; text given?
  512.         jne     vsetu2a                 ; ne = yes
  513.         mov     ah,prstr
  514. ;        mov     dx,offset erms41        ; say need more parameters
  515.         mcmsg   erms41,cerms41
  516.         int     dos
  517.         jmp     rskp
  518. vsetu2a:mov     bx,vtemu.att_ptr        ; get address of attributes byte
  519.         mov     bl,[bx]                 ; get attributes
  520.         mov     byte ptr temp,bl        ; save in work temp
  521.         mov     si,offset rdbuf         ; si = place where atoi wants text
  522.         jmp     vsetu2b                 ; analyze
  523.  
  524. colbad: mov     ah,prstr                ; not in range - complain and exit
  525. ;        mov     dx,offset colerr
  526.         mcmsg   colerr,ccolerr
  527.         int     dos
  528.         jmp     rskp
  529.  
  530. vsetu2x:mov     al,byte ptr temp        ; get current attributes
  531.         mov     bx,vtemu.att_ptr        ; get address of attributes byte
  532.         mov     [bx],al                 ; store attributes
  533.         jmp     rskp                    ; and return normally
  534.  
  535. vsetu2b:mov     dx,si                   ; analyze values
  536.         call    strlen                  ; current length of text to cx
  537.         jcxz    vsetu2x                 ; z = nothing left
  538. vsetu2c:cmp     byte ptr[si],' '        ; scan off leading spaces
  539.         jne     vsetu2d                 ; ne = non-blank text found
  540.         inc     si                      ; look at next char
  541.         loop    vsetu2c                 ; cx characters to examine
  542.         jcxz    vsetu2x                 ; z = nothing left
  543. vsetu2d:mov     ah,cl                   ; put length where atoi wants it
  544.         call    atoi                    ; convert text to numeric in ax
  545.          jmp    colbad                  ; no value available
  546.          nop
  547.         cmp     ax,0                    ; reset all? regular IBM CGA refresh
  548.         je      vsetu2j                 ; e = yes
  549.         cmp     ax,1                    ; high intensity?
  550.         je      vsetu2k                 ; e = yes
  551.         cmp     ax,10                   ; fast refresh?
  552.         je      vsetu2l                 ; e = yes
  553.         cmp     ax,30                   ; check range
  554.         jb      colbad                  ; b = too small. complain
  555.         cmp     ax,37
  556.         jna     vsetu2f                 ; 30-37 is foreground color
  557.         cmp     ax,40
  558.         jb      colbad
  559.         cmp     ax,47                   ; compare as unsigned
  560.         jna     vsetu2g                 ; 40-47 is background
  561.         jmp     colbad                  ; else error
  562.  
  563. vsetu2h:inc     si                      ; skip separator
  564.         cmp     byte ptr[si-1],0        ; ended on null?
  565.         jne     vsetu2b                 ; ne = no, do more
  566.         jmp     vsetu2x                 ; e = yes, exit
  567.  
  568. vsetu2f:sub     al,30                   ; remove foreground bias
  569.         and     byte ptr temp,not 07H   ; clear foreground bits
  570.         mov     bx,ax
  571.         mov     al,colortb[bx]          ; get reversed bit pattern
  572.         or      byte ptr temp,al        ; load new bits
  573.         jmp     vsetu2h
  574.  
  575. vsetu2g:sub     al,40                   ; remove background bias
  576.         and     byte ptr temp,not 70H   ; clear background bits
  577.         mov     bx,ax
  578.         mov     al,colortb[bx]          ; get reversed bit pattern
  579.         mov     cl,4                    ; rotate 4 positions
  580.         rol     al,cl
  581.         or      byte ptr temp,al        ; load new bits
  582.         jmp     vsetu2h
  583.  
  584. vsetu2j:mov     refresh,0               ; Regular (slow) screen refresh
  585.         mov     byte ptr temp,07h       ; clear all, set white on black
  586.         jmp     vsetu2h                 ; get next value
  587. vsetu2k:or      byte ptr temp,08h       ; set high intensity
  588.         jmp     vsetu2h                 ; get next value
  589. vsetu2l:mov     refresh,1               ; Fast screen refresh
  590.         jmp     vsetu2h
  591.  
  592. vsetu8: mov     ah,cmkey                ; Set Term graphics
  593.         mov     bx,0                    ; Use graphics table as help
  594.         mov     dx,offset graftab       ; Use graphics table
  595.         call    comnd
  596.          jmp    r                       ; bad keyword
  597.          nop
  598.         mov     temp,bx
  599.         mov     ah,cmcfm                ; get a confirm
  600.         call    comnd
  601.          jmp    r                       ; did not get a confirm
  602.          nop
  603.         mov     bx,temp
  604.         mov     tekgraf,bl              ; set Tek graphics board type
  605.         jmp     rskp                    ; return successfully
  606.  
  607. ; SET Term flags. These are the (near) equivalent of VT100 Setup mode values.
  608.  
  609. flgset: mov     word ptr rdbuf,bx       ; save index
  610.         mov     ah,cmkey                ; Another keyword
  611.         mov     dx,vtable[bx]           ; The table to use
  612.         mov     bx,0                    ; Use default help
  613.         call    comnd
  614.          jmp    r
  615.          nop
  616.         mov     temp,bx                 ; Save switch value
  617.         mov     ah,cmcfm                ; Confirm it
  618.         call    comnd
  619.          jmp    r
  620.          nop
  621.         mov     dx,temp                 ; Restore switch value
  622.         mov     bx,word ptr rdbuf       ; And index
  623.         shr     bx,1                    ; Make it a byte index
  624.         mov     al,vtsflg[bx]           ; Get the flag
  625.         cmp     dx,0                    ; Set or clear?
  626.         je      flgse1                  ; Go clear it
  627.         or      vtemu.vtflgst,al        ; Set the flag
  628.         or      vtemu.vtflgop,al        ; in runtime flags too
  629.         jmp     rskp                    ; Give good return
  630.  
  631. flgse1: not     al                      ; Complement
  632.         and     vtemu.vtflgst,al        ; Clear the indicated setup flag
  633.         and     vtemu.vtflgop,al        ; Clear the indicated runtime flag
  634.         jmp     rskp                    ; Give good return
  635.  
  636. ;       SET Term Tabstops Clear ALL
  637. ;       SET Term Tabstops Clear AT n1, n2, ..., nx
  638. ;       SET Term Tabstops At n1, n2, ..., nx
  639.  
  640. tabset: cld                             ; Make sure this is clear
  641.         mov     di,offset decbuf        ; clear our temp work area here
  642.         mov     cx,132                  ; 132 columns
  643.         mov     al,0                    ; set "not touched" indicator
  644.         rep     stosb                   ; in all decbuf slots
  645.         mov     ah,cmkey                ; Parse keyword
  646. ;        mov     bx,offset clrhlp        ; help text
  647.         mcmsgb  clrhlp,cclrhlp
  648.         mov     dx,offset tabtab        ; table
  649.         call    comnd
  650.          jmp    r
  651.          nop
  652.         mov     clrset,2                ; code for set a tab
  653.         cmp     bl,0                    ; Was it set or clear?
  654.         jne     tabse1                  ; SET - go parse column number(s)
  655.         mov     clrset,1                ; code for clear at/all tab(s)
  656.         mov     ah,cmkey                ; CLEAR - parse ALL or AT
  657. ;        mov     bx,offset clrhlp        ; Use this help text
  658.         mcmsgb  clrhlp,cclrhlp
  659.         mov     dx,offset alltab        ; Parse ALL or AT
  660.         call    comnd
  661.          jmp    r
  662.          nop
  663.         cmp     bx,0                    ; ALL?
  664.         jne     tabse1                  ; ne = AT, clear at specific places
  665.         mov     ah,cmcfm                ; Confirm the ALL
  666.         call    comnd
  667.          jmp    r
  668.          nop
  669.         mov     al,1                    ; ALL, means clear all tab stops
  670.         mov     cx,132                  ; use 132 columns
  671.         mov     di,offset decbuf
  672.         cld
  673.         rep     stosb
  674.         jmp     tabcpy                  ; update active & coldstart tabs
  675.  
  676. tabse1: 
  677. ;       mov     dx,offset clrhlp        ; Tell them we want a column number
  678.         mcmsg   clrhlp,cclrhlp
  679.         mov     ah,cmtxt                ; get text w/o white space
  680.         mov     bx,offset rdbuf         ; temp buffer
  681.         call    comnd
  682.          jmp    r
  683.          nop
  684.         cmp     ah,0                    ; anything given?
  685.         jne     tabse2                  ; ne = yes
  686.         mov     ah,prstr
  687. ;        mov     dx,offset erms41        ; say need more parameters
  688.         mcmsg   erms41,cerms41
  689.         int     dos
  690.         jmp     rskp
  691. tabse2: mov     si,offset rdbuf         ; si = place where atoi wants text
  692. tabse3: mov     dx,si
  693.         call    strlen                  ; cx = current length of text
  694.         jcxz    tabcpy                  ; z = nothing left
  695.         mov     ah,cl                   ; put length where atoi wants it
  696.         call    atoi                    ; convert text to numeric in ax
  697.          jmp    tabcpy                  ;  no number available
  698.          nop
  699.         mov     bx,ax                   ; for subscripting in code below
  700.         dec     bx                      ; put column in range 0-131
  701.         cmp     bx,0                    ; check range (1-132 --> 0-131)
  702.         jl      tbsbad                  ; l = too small. complain
  703.         cmp     bl,132-1                ; more than the right most column?
  704.         jna     tabse4                  ; na = no, is ok
  705. tbsbad: mov     ah,prstr                ; not in range - complain and exit
  706. ;        mov     dx,offset tbserr
  707.         mcmsg   tbserr,ctbserr
  708.         int     dos
  709.         jmp     rskp
  710.  
  711. tabse4: mov     al,clrset               ; get value for setting or clearing
  712.         mov     decbuf[bx],al           ; store in tabs temp work array
  713.         cmp     byte ptr [si],':'       ; start-column:spacing notation?
  714.         jne     tabse3                  ; ne = no, get next tab stop
  715.         inc     si                      ; skip colon, do start:space analysis
  716.         mov     temp,bx                 ; save reg around atoi call
  717.         mov     dx,si                   ; string address for strlen
  718.         call    strlen                  ; get remaining string length into cx
  719.         jcxz    tabcpy                  ; z = no space value, all done here
  720.         mov     ah,cl                   ; ah = string length for atoi
  721.         call    atoi                    ; get space value into ax
  722.          jmp    tabcpy                  ;  no number available
  723.          nop
  724.         mov     bx,temp
  725.         mov     cx,ax                   ; "space" value
  726.         cmp     cx,0                    ; zero spacing?
  727.         jne     tabse4a                 ; ne = no
  728.         inc     cx                      ; don't get caught with zero spacing
  729. tabse4a:mov     al,clrset               ; get tab set or clear indicator
  730. tabse5: add     bx,cx                   ; new column value
  731.         cmp     bx,132-1                ; largest tab stop
  732.         ja      tabcpy                  ; a = done largest tab stop
  733.         mov     decbuf[bx],al           ; store set or clear indicator
  734.         jmp     short tabse5            ; finish spacing loop, then do tabcpy
  735.  
  736. tabcpy: mov     cx,132                  ; update all active tab stops
  737.         mov     si,vtemu.vttbst         ; in terminal emulator's active buffer
  738.         mov     di,vtemu.vttbs          ; and in the cold-start buffer
  739.         mov     bx,0                    ; subscript
  740. tabcpy1:mov     al,decbuf[bx]           ; get a table entry into al
  741.         or      al,al                   ; what is the code?
  742.         jz      tabcpy3                 ; z = do not touch
  743.         cmp     al,2                    ; set a tab?
  744.         je      tabcpy2                 ; e = set the tab
  745.         mov     byte ptr [bx+si],0      ; clear the tab
  746.         mov     byte ptr [bx+di],0      ; clear the tab
  747.         jmp     short tabcpy3
  748. tabcpy2:mov     byte ptr [bx+si],0ffh   ; set the tab
  749.         mov     byte ptr [bx+di],0ffh   ; set the tab
  750. tabcpy3:inc     bx                      ; inc subscript
  751.         loop    tabcpy1
  752.         jmp     rskp                    ; Give good return
  753.  
  754. VTS     endp                            ; end of Set Term things
  755.  
  756.               ; Terminal Status display, called within STAT0: in MSSSET
  757. VTSTAT  proc    near                    ; enter with di within sttbuf, save bx
  758.         push    bx
  759. ;       mov     bx,offset vtstbl        ; table of things to show
  760.         mcmsgb  vtstbl,cvtstbl
  761.         call    statc                   ; status common code, in mssset
  762.          nop
  763.          nop
  764.          nop
  765.         pop     bx
  766.         ret                             ; return to STAT0: in MSSSET
  767.  
  768. colstat proc    near                    ; foreground/background color status
  769.         push    si
  770. ;        mov     si,offset colst1
  771.         mcmsgsi colst1,ccolst1
  772.         cld
  773. colstd1:lodsb
  774.         cmp     al,'$'                  ; end of string?
  775.         je      colstd2                 ; e = yes
  776.         stosb
  777.         jmp     short colstd1
  778. colstd2:mov     bx,vtemu.att_ptr        ; pointer to attributes byte
  779.         mov     bl,byte ptr[bx]
  780.         mov     bh,0
  781.         push    bx
  782.         and     bx,7                    ; get foreground set
  783.         mov     al,colortb[bx]          ; get reversed bit pattern
  784.         add     al,'0'                  ; add ascii bias
  785.         stosb
  786.         pop     bx
  787. ;        mov     si,offset colst2
  788.         mcmsgsi colst2,ccolst2
  789. colstd3:lodsb
  790.         cmp     al,'$'
  791.         je      colstd4
  792.         stosb
  793.         jmp     short colstd3
  794. colstd4:mov     cl,4                    ; rotate 4 positions
  795.         shr     bl,cl
  796.         and     bx,7                    ; get background set
  797.         mov     al,colortb[bx]          ; get reversed bit pattern
  798.         add     al,'0'                  ; add ascii bias
  799.         stosb
  800.         pop     si
  801.         ret
  802. colstat endp
  803.                                         ; Tabs Status display
  804. tabstat proc    near                    ; display tabs ruler for Status
  805.         push    dx
  806.         cld
  807. tabstd2:mov     al,cr
  808.         stosb
  809. tabsta0:mov     si,vtemu.vttbst         ; active tabs address, not shadow
  810.         mov     cl,byte ptr low_rgt     ; loop screen width-1 times
  811.         xor     ch,ch                   ; clear high byte
  812.         dec     si                      ; dec for inc below
  813.         xor     ax,ax                   ; tens counter
  814. tabsta1:mov     dl,'.'                  ; default position symbol
  815.         inc     si                      ; start with position 1
  816.         inc     al
  817.         cmp     al,10                   ; time to roll over?
  818.         jb      tabsta2                 ; b = not yet
  819.         mov     al,0                    ; modulo 10
  820.         inc     ah
  821.         mov     dl,ah                   ; display a tens-digit
  822.         add     dl,'0'
  823.         cmp     dl,'9'                  ; larger than 90?
  824.         jbe     tabsta2                 ; be = no
  825.         sub     dl,10                   ; roll over to 0, 1, etc
  826. tabsta2:cmp     byte ptr [si],0         ; is tab set?
  827.         je      tabsta3                 ; e = no
  828.         mov     dl,'T'                  ; yes, display a 'T'
  829. tabsta3:push    ax
  830.         mov     al,dl
  831.         stosb
  832.         pop     ax
  833.         loop    tabsta1                 ; loop til done (cx has count)
  834.         pop     dx
  835.         ret
  836. tabstat endp
  837.  
  838. filler  proc    near                    ; use space
  839.         mov     cx,20
  840.         mov     al,' '
  841.         rep     stosb
  842.         ret
  843. filler  endp
  844. VTSTAT  endp                            ; end of Terminal set & status code
  845.  
  846. ; Compute number of iterations needed in procedure pcwait inner loop
  847. ; to do one millisecond delay increments. Uses Intel 8253/8254 timer chip
  848. ; (timer #2) to measure elapsed time assuming 1.193182 MHz clock.
  849. ; Called by serini below. For IBM PC compatible machines.
  850. ; Regs preserved. 16 April 87 [jrd]
  851. pcwtst  proc    near
  852.         push    ax
  853.         push    cx
  854.         push    dx
  855.         mov     pcwcnt,256      ; software loop, initial value
  856.         in      al,ppi_port     ; 8255 chip port B, 61h
  857.         and     al,0fch         ; speaker off (bit 1), stop timer (bit 0)
  858.         out     ppi_port,al     ; do it
  859.   ; 10 = timer 2, 11 = load low byte then high byte, 010 = mode 2, 0 = binary
  860.         mov     al,10110100B    ; command byte
  861.         out     timercmd,al     ; timer command port, 43h
  862.         xor     al,al           ; clear initial count for count-down
  863.         out     timer2data,al   ; low order byte of count preset, to port 42h
  864.         out     timer2data,al   ; high order byte, to the same place
  865.         in      al,ppi_port     ; get 8255 setting
  866.         mov     dl,al           ; remember it in dl
  867.         and     al,0fch         ; clear our control bits
  868.         or      al,1            ; start counter now (Gate = 1, speaker is off)
  869.         out     ppi_port,al     ; do it, OUT goes low
  870.                                 ; this is the test loop
  871.         mov     ax,8            ; wait 8 millisec
  872.         call    pcwait          ; call the software timer
  873.                                 ; end test loop
  874.         mov     al,dl           ; restore ppi port, stop timer
  875.         out     ppi_port,al
  876.         in      al,timer2data   ; read count down value
  877.         xchg    al,ah           ; save low order byte
  878.         in      al,timer2data   ; get high order byte
  879.         xchg    ah,al           ; put in correct sequence
  880.         neg     ax              ; subtract from zero to get elapsed tics
  881.         xor     dx,dx           ; clear high order divisor
  882.         add     ax,1193/2       ; round up
  883.         adc     dx,0            ; for very very slow machines
  884.         mov     cx,1193         ; tics per millisec
  885.         div     cx              ; count / 1193 yields millisecs, quo=ax
  886.         mov     cx,ax           ; retain whole number of milliseconds
  887.         mov     ax,pcwcnt       ; get current pcwait inner loop count
  888.         xor     dx,dx           ; clear high order field for division
  889.         shl     ax,1
  890.         rcl     dx,1
  891.         shl     ax,1
  892.         rcl     dx,1
  893.         shl     ax,1
  894.         rcl     dx,1            ; dx:ax = current counter times 8 loops
  895.         cmp     cx,0            ; no millisec? (super speed machines)
  896.         ja      pcwtst1         ; a = some
  897.         inc     cx              ; use at least one
  898. pcwtst1:div     cx              ; divide by observed milliseconds
  899.         mov     pcwcnt,ax       ; store quotient as new inner loop counter
  900.         pop     dx
  901.         pop     cx
  902.         pop     ax
  903.         ret
  904. pcwtst  endp
  905.  
  906. ;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
  907. ;; Thanks to Bernie Eiben for this one. Modified to use adjustable
  908. ; inner loop counter (pcwcnt, adjusted by proc pcwtst) by [jrd].
  909. pcwait  proc    near
  910.         push    cx
  911. pcwai0: mov     cx,pcwcnt       ; inner loop counter for 1 ms (240 @ 4.77 MHz)
  912. pcwai1: sub     cx,1            ; inner loop takes 20 clock cycles
  913.         jnz     pcwai1
  914.         dec     ax              ; outer loop counter
  915.         jnz     pcwai0          ; wait another millisecond
  916.         pop     cx
  917.         ret
  918. pcwait  endp
  919.  
  920. ; set the current port.
  921. ; Note: serial port addresses are found by looking in memory at 40:00h and
  922. ; following three words for COM1..4, resp. All UARTS are assumed to follow
  923. ; std IBM addresses relative to 03f8h for COM1, and actual address are offset
  924. ; from value found in segment 40h. Global byte flags.comflg is 1,2,3,4 for
  925. ; COM1..4, and is 'N' for Network.
  926. ; If address 02f8h is found in 40:00h then name COM1 is retained but COM2
  927. ;  addressing is used to access the UART and a notice is displayed. IRQ 3
  928. ; or IRQ 4 is sensed automatically for any COMx port.
  929. COMS    PROC    NEAR
  930.         mov     dx,offset comptab       ; table of legal comms ports
  931.         mov     bx,0                    ; no extra help text
  932.         mov     ah,cmkey                ; parse key word
  933.         call    comnd
  934.          jmp    r                       ;  failed
  935.         mov     temp,bx
  936.         cmp     bl,'N'                  ; NetBios network?
  937.         je      comstrt                 ; yes, get another item for networks
  938.         cmp     bl,'U'                  ; Ungermann Bass net?
  939.         je      comstrt                 ; e = yes
  940.         mov     ah,cmcfm                ; non-network
  941.         call    comnd                   ; Get a confirm
  942.          jmp    r                       ;  Didn't get a confirm
  943.          nop
  944.         mov     bx,temp
  945. COMSTRT:cmp     portin,-1               ; first time here?
  946.         jne     comst1                  ; ne = no
  947.         mov     portin,0                ; say have been here before
  948. comst1: mov     temp,bx
  949.         cmp     bl,'N'                  ; NetBios network?
  950.         jne     comst2                  ; ne = no
  951.         jmp     comsn                   ; yes, get another item for networks
  952. comst2: cmp     bl,'U'                  ; Ungermann Bass net?
  953.         jne     comst3                  ; ne = no
  954.         jmp     comsub
  955. comst3: cmp     flags.comflg,'N'        ; have been running on network?
  956.         jne     coms1b                  ; ne = no
  957.                                         ; turn off sources of net interrupts
  958.         mov     bx,offset can           ; cancel outstanding requests
  959.         mov     can.scb_cmd,ncancel     ; set cancel op code
  960.         cmp     lposted,1               ; listen outstanding?
  961.         jne     coms1a                  ; ne = no
  962.         mov     can.scb_baddr,offset lsn ; cancel listen
  963.         call    session
  964.         mov     lposted,0
  965. coms1a: cmp     rposted,1               ; receive outstanding?
  966.         jne     coms1b                  ; ne = no
  967.         mov     can.scb_baddr,offset rcv ; cancel receive
  968.         call    session
  969.         mov     rposted,0               ; clear interlock flag
  970.  
  971. coms1b: call    serrst                  ; close current comms port
  972.         mov     bx,temp                 ; get port number/letter
  973.         mov     flags.comflg,bl         ; remember port number
  974.         mov     bh,0
  975.         mov     bl,flags.comflg         ; get COMx number (1-4)
  976.         push    bx                      ; Set UART port addresses
  977.         mov     ax,bx                   ; get COMx (1-4)
  978.         cmp     al,'1'                  ; ascii numbered Bios port?
  979.         jb      coms3                   ; b = no
  980.         sub     al,'0'                  ; remove ascii bias for portinfo
  981. coms3:  dec     ax                      ; count ports from zero
  982.         mov     bx,type prtinfo         ; size of each portinfo structure
  983.         mul     bx                      ; times port number
  984.         add     ax,offset port1         ; plus start of COM1
  985.         mov     portval,ax              ; points to our current port struct
  986.         pop     bx                      ; restore registers
  987.         cmp     bl,' '                  ; doing forced Bios?
  988.         jb      coms4                   ; b = no, hardware
  989.         mov     clone,'B'               ; set clone flag for Bios usage
  990.         jmp     rskp                    ; all done
  991.  
  992. coms4:  push    bx                      ; save register
  993.         push    es
  994.         mov     ax,40h          ; look at RS232_base [bx] in Bios area 40:00h
  995.         mov     es,ax
  996.         dec     bl                      ; count com1 as bl = 0, etc
  997.         mov     bh,0                    ; clear high byte
  998.         shl     bx,1                    ; make bx a word index
  999.         mov     ax,es:[bx]              ; get modem base address into ax
  1000.         pop     es
  1001.         pop     bx
  1002.         or      ax,ax                   ; is address zero?
  1003.         je      comsf                   ; e = yes, no serial port
  1004. comsc:                                  ; hardware tests
  1005.         mov     modem.mddat,ax  ; set base address (also data address) 03f8h
  1006.         add     ax,3                    ; increment to command port 03fbh
  1007.         mov     modem.mdcom,ax          ; set line control register address
  1008.         mov     brkadr,ax               ; where to send break command
  1009.         add     ax,2                    ; increment to status port 03fdh
  1010.         mov     modem.mdstat,ax         ; set line-status port address
  1011.  
  1012.         call    chkport                 ; get type of UART support (for Clone)
  1013.         jnc     comsu                   ; nc = has a real 8250 uart
  1014.         add     flags.comflg,'0'        ; COMn to BIOSn
  1015.         push    ax                      ; else tell user about Bios pathway
  1016.         push    dx
  1017.         mov     ah,prstr
  1018. ;        mov     dx,offset biosmsg
  1019.         mcmsg   biosmsg,cbiosmsg
  1020.         int     dos
  1021.         pop     dx
  1022.         pop     ax
  1023.         jmp     rskp
  1024.  
  1025. comsu:  call    chkint                  ; find IRQ for the port
  1026.         jc      comsf                   ; c = not found, an error conditon
  1027.         jmp     rskp
  1028.  
  1029. comsf:  
  1030. ;        mov     dx,offset badprt        ; say port is not available
  1031.         mcmsg   badprt,cbadprt
  1032.         mov     ah,prstr
  1033.         int     dos
  1034.         mov     al,flags.comflg         ; port ident character
  1035.         cmp     al,' '                  ; binary for COM series
  1036.         jae     comsf1                  ; ae = no
  1037.         mov     dx,offset compt         ; display COM
  1038.         int     dos
  1039.         mov     ah,conout
  1040.         mov     dl,flags.comflg
  1041.         add     dl,'0'                  ; display port number
  1042.         int     dos
  1043.         jmp     comsf3
  1044. comsf1: cmp     al,'9'                  ; ascii numeric for Bios series?
  1045.         ja      comsf2                  ; a = no
  1046.         mov     dx,offset biospt        ; display BIOS
  1047.         int     dos
  1048.         mov     ah,conout
  1049.         mov     dl,flags.comflg         ; ascii port number
  1050.         int     dos
  1051.         jmp     comsf3
  1052. comsf2: 
  1053. ;       mov     dx,offset unkpt         ; unknown type
  1054.         mcmsg   unkpt,cunkpt
  1055.         int     dos
  1056. comsf3: mov     flags.comflg,0          ; bad port, reassign to null port
  1057.         mov     ah,prstr
  1058. ;        mov     dx,offset badprt2       ; the rest of the message
  1059.         mcmsg   badprt2,cbadprt2
  1060.         mov     ah,prstr
  1061.         int     dos
  1062.         stc                             ; say error
  1063.         jmp     rskp
  1064.                                         ; NetBios Network support
  1065. comsn:  mov     ah,cmfile               ; get a word (remote node name)
  1066.         mov     dx,offset nambuf        ; work buffer
  1067.         mov     word ptr nambuf,0       ; insert terminator
  1068. ;        mov     bx,offset nethlp        ; help message
  1069.         mcmsgb  nethlp,cnethlp
  1070.         call    comnd                   ; get the name
  1071.          nop
  1072.          nop
  1073.          nop
  1074.         xchg    ah,al                   ; put byte count in al
  1075.         xor     ah,ah                   ; clear junk
  1076.         mov     temp,ax                 ; save number of chars entered
  1077.         mov     ah,cmcfm
  1078.         call    comnd                   ; Get a confirm
  1079.          jmp    r                       ;  Didn't get a confirm
  1080.          nop
  1081.         call    serrst                  ; reset serial port
  1082.         call    chknet                  ; start network usage
  1083.         cmp     pcnet,0                 ; is network alive (non-zero)?
  1084.         jne     comsn4                  ; ne = yes
  1085.         stc
  1086.         jmp     rskp                    ; return failure
  1087.  
  1088. comsn4: mov     portval,offset portn ; set Network port data structure address
  1089.         mov     flags.comflg,'N'        ; Set the comm port flag
  1090.         call    chkport                 ; set type of port support
  1091.         clc                             ; return success
  1092.         jmp     rskp                    ; End NetBios
  1093.  
  1094.                                         ; Ungermann-Bass terminal port [ohl +]
  1095. comsub: mov     ah,cmcfm
  1096.         call    comnd                   ; Get a confirm
  1097.          jmp    r                       ;  Didn't get a confirm
  1098.          nop
  1099.         call    serrst                  ; reset serial port
  1100.         call    chkub                   ; check UB network presence
  1101.         jnc     comsub1                 ; nc = present
  1102.         stc
  1103.         jmp     rskp                    ; return failure
  1104.  
  1105. comsub1:call    netclose                ; better close NetBios parts NOW!
  1106.         mov     portval,offset portn ; set Network port data structure address
  1107.         mov     flags.comflg,'U'        ; Set the comm port flag
  1108.         mov     pcnet,2                 ; network is present and active
  1109.         mov     lclexit,offset ubclose  ; address to close network
  1110.         call    chkport                 ; get type of port support
  1111.         clc                             ; return success
  1112.         jmp     rskp                    ; End Ungermann Bass    [ohl -]
  1113. COMS    ENDP
  1114.  
  1115. ; Check which Interrupt ReQuest line the port uses. Technique: allow interrupt
  1116. ; on transmitter holding register empty, test for that condition first with
  1117. ; IRQ 4 and then IRQ 3. Returns with IRQ values set and carry clear if success
  1118. ; or carry set if failure. [jrd]
  1119. chkint  proc    near
  1120.         cmp     flags.comflg,2          ; COM1 or COM2?
  1121.         jbe     chkin2                  ; be = yes, use standard IRQ's
  1122.         mov     modem.mddis,MDMINTC     ; IRQ 4 test. mask to disable IRQ 4
  1123.         mov     modem.mden,MDMINTO      ; mask to enable IRQ 4
  1124.         mov     modem.mdmeoi,20h        ; use general in case we guess wrong
  1125.         mov     modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch)
  1126.         mov     intkind,0               ; clear interrupt cause
  1127.         call    serini                  ; setup port for IRQ 4
  1128.         jc      chkint2                 ; c = failure
  1129.         mov     dx,modem.mddat
  1130.         inc     dx                      ; interrupt enable reg (3f9h)
  1131.         mov     al,2                    ; set xmtr holding reg empty interrupt
  1132.         out     dx,al
  1133.         mov     ax,1                    ; wait one millisec for interrupt
  1134.         call    pcwait                  ;  to occur
  1135.         test    intkind,2               ; check cause of interrupt, ours?
  1136.         jz      chkint2                 ; z = no, try other IRQ
  1137.         call    serrst                  ; reset port
  1138.         mov     modem.mdmeoi,EOICOM     ; use specific EOI for IRQ4 level
  1139.         clc                             ; this setup worked
  1140.         ret
  1141.                                         ; IRQ 3 test
  1142. chkint2:call    serrst                  ; reset port
  1143.         mov     modem.mddis,MDINTC2     ; mask to disable IRQ 3
  1144.         mov     modem.mden,MDINTO2      ; mask to enable IRQ 3
  1145.         mov     modem.mdmeoi,20h        ; use general in case we guess wrong
  1146.         mov     modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1147.         mov     intkind,0               ; clear interrupt cause
  1148.         call    serini                  ; setup port for IRQ 3
  1149.         jc      chkin2                  ; c = failure
  1150.         mov     dx,modem.mddat
  1151.         inc     dx                      ; interrupt enable reg (3f9h)
  1152.         mov     al,2                    ; set xmtr holding reg empty interrupt
  1153.         out     dx,al
  1154.         mov     ax,1                    ; wait one millisec for interrupt
  1155.         call    pcwait                  ;  to occur
  1156.         test    intkind,2               ; check cause of interrupt, ours?
  1157.         jz      chkin2                  ; z = no, so no interrupts for port
  1158.         call    serrst                  ; reset port
  1159.         mov     modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1160.         clc                             ; this setup worked
  1161.         ret
  1162.  
  1163. chkin2: call    serrst                  ; reset port, auto test did not work
  1164.         cmp     flags.comflg,1          ; COM1?
  1165.         je      chkin4                  ; e = yes, use IRQ 4
  1166.         cmp     isps2,0                 ; IBM PS/2 Model 50 or above?
  1167.         jne     chkin3                  ; ne = yes, other COMs use IRQ 3
  1168.         cmp     flags.comflg,3          ; COM2, COM3, or COM4?
  1169.         je      chkin4                  ; e = COM3, use IRQ 4
  1170.         jmp     short chkin3            ; else COM2 or COM4, use IRQ 3
  1171. chkin4: cmp     modem.mddat,02f8h       ; really COM2 material for PCjr?
  1172.         je      chkin3                  ; e = yes, use COM2 addresses
  1173.         mov     modem.mdmeoi,EOICOM     ; use specific EOI for IRQ4 level
  1174.         mov     modem.mddis,MDMINTC     ; IRQ 4 test. mask to disable IRQ 4
  1175.         mov     modem.mden,MDMINTO      ; mask to enable IRQ 4
  1176.         mov     modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch)
  1177.         jmp     short chkin5
  1178. chkin3: mov     modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1179.         mov     modem.mddis,MDINTC2     ; mask to disable IRQ 3
  1180.         mov     modem.mden,MDINTO2      ; mask to enable IRQ 3
  1181.         mov     modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1182. chkin5: clc
  1183.         ret
  1184. chkint  endp
  1185.  
  1186. ; Test presently selected serial port for having a real 8250 UART.
  1187. ; Return carry clear and clone = 0 if 8250 present,
  1188. ;  else carry set and clone = 'B' for system Bios or
  1189. ;  carry set and clone = 'N' for network.
  1190. ; Method is to check UART's Interrupt Identification Register for high
  1191. ; five bits being zero; IBM does it this way. Assumes port structure
  1192. ; has been initialized with addresses of UART.  21 Feb 1987 [jrd]
  1193. ; 29 May 1987 Add double check by reading Line Status Register. [jrd]
  1194.  
  1195. chkport proc    near
  1196.         cmp     portval,offset portn    ; network?
  1197.         je      chkporn                 ; e = yes
  1198.         push    ax
  1199.         push    dx
  1200.         cmp     flags.comflg,0          ; undefined port?
  1201.         je      chkpor1                 ; e = yes, assume Bios clone
  1202.         mov     dx,modem.mdcom  ; address of UART line control reg (3FBh/2FBh)
  1203.         sub     dx,1            ; Interupt Identification Register address
  1204.         in      al,dx                   ; read UART's IIR
  1205.         test    al,0f8h                 ; are any of high 5 bits set?
  1206.         jnz     chkpor1                 ; nz = yes, not an 8250
  1207.         mov     dx,modem.mdstat         ; line status register
  1208.         in      al,dx                ; read to clear UART BI, FE, PE, OE bits
  1209.         jmp     $+2                     ; pause, for chip access timing
  1210.         in      al,dx                   ; these bits should be cleared
  1211.         test    al,8eh                  ; are they cleared?
  1212.         jnz     chkpor1                 ; nz = no, not an 8250
  1213.         mov     clone,0                 ; clear clone flag
  1214.         pop     dx
  1215.         pop     ax
  1216.         clc                             ; clear carry (say 8250)
  1217.         ret
  1218. chkpor1:pop     dx
  1219.         pop     ax
  1220.         mov     clone,'B'               ; set clone flag
  1221.         stc                             ; set carry (say no 8250)
  1222.         ret
  1223. chkporn:push    ax                      ; Networking
  1224.         mov     al,flags.comflg         ; get port letter
  1225.         mov     clone,al
  1226.         pop     ax
  1227.         stc                             ; set carry (say no 8250)
  1228.         ret
  1229. chkport endp
  1230. ;;;;;;;;;;;;;;;;;;;;;; end of part one of msxibm.asm
  1231. ;;;;;;;;;;;;;;;;;;;;;; start part two of msxibm.asm
  1232.  
  1233. ; Set the baud rate for the current port, based on the value
  1234. ; in the portinfo structure.  Returns normally.
  1235. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1236.  
  1237. DOBAUD  PROC    NEAR
  1238.         cmp     portin,-1               ; port not used yet?
  1239.         jne     dobd3                   ; ne = no, go get rate
  1240.         mov     bl,flags.comflg         ; pass current port ident
  1241.         call    comstrt                 ; do SET PORT command now
  1242.          ret                            ; failed to set port
  1243.          nop
  1244.          nop
  1245. dobd3:  push    ax                      ; save some regs
  1246.         push    bx
  1247.         push    dx
  1248.         call    chkport         ; check port for real 8250 UART (clone = 0)
  1249.         cmp     flags.comflg,'N'        ; Netbios?
  1250.         je      dobd1                   ; e = yes, do nothing here
  1251.         cmp     flags.comflg,'U'        ; UB network?
  1252.         je      dobd1                   ; e = yes
  1253.         mov     bx,portval              ; pointer to port data structure
  1254.         mov     temp,ax                 ; Don't overwrite previous rate
  1255.         mov     ax,[bx].baud            ; Check if new rate is valid
  1256.         shl     ax,1                    ; make a word index
  1257.         mov     bx,offset bddat         ; Start of table
  1258.         cmp     clone,'B'               ; running on clone?
  1259.         jne     dobd0a                  ; ne = no
  1260.         mov     bx,offset clbddat       ; use Bios speed parameters for clone
  1261. dobd0a: add     bx,ax
  1262.         mov     ax,[bx]                 ; The data to output to port
  1263.         cmp     ax,0FFH                 ; Unimplemented baud rate
  1264.         jne     dobd0
  1265.         mov     ah,prstr
  1266. ;        mov     dx,offset badbd         ; Give an error message
  1267.         mcmsg   badbd,cbadbd
  1268.         int     dos
  1269.         jmp     dobd1
  1270.  
  1271. dobd0:  cmp     clone,0                 ; running on a real uart?
  1272.         je      dobd2                   ; e = the real thing
  1273.         mov     dx,0            ; assume port 1 Clone: find current port
  1274.         mov     dl,flags.comflg         ; get coms port (1..4)
  1275.         or      dl,dl                   ; zero (undefined port)?
  1276.         jz      dobd1                   ; z = yes, just exit
  1277.         and     dl,7                    ; use lower three bits
  1278.         dec     dl                      ; count ports as 0..3 for Bios
  1279.         mov     ah,0                    ; set serial port
  1280.         int     rs232                   ; Bios: set the parameters
  1281.         jmp     dobd1                   ; and exit
  1282.  
  1283. dobd2:  mov     temp,ax                 ; Remember value to output
  1284.         mov     dx,modem.mdcom          ; LCR -- Initialize baud rate
  1285.         in      al,dx                   ; get it
  1286.         mov     bl,al                   ; make a copy
  1287.         or      ax,80H          ; turn on DLAB bit to access divisor part
  1288.         out     dx,al
  1289.         mov     dx,modem.mddat
  1290.         mov     ax,temp                 ; set the baud rate divisor, low byte
  1291.         out     dx,al
  1292.         inc     dx                      ; next address for high part
  1293.         mov     al,ah                   ; set high part of divisor
  1294.         out     dx,al
  1295.         mov     dx,modem.mdcom          ; LCR again
  1296.         mov     al,bl                   ; get original setting from bl
  1297.         out     dx,al                   ; restore it
  1298. dobd1:  pop     dx                      ; restore regs
  1299.         pop     bx
  1300.         pop     ax
  1301.         ret
  1302. DOBAUD  ENDP
  1303.  
  1304. ; Get the current baud rate from the serial card and set it
  1305. ; in the portinfo structure for the current port.  Returns normally.
  1306. ; This is used during initialization.
  1307. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1308.  
  1309. GETBAUD PROC    NEAR
  1310.         cmp     portin,-1               ; port not used yet?
  1311.         jne     getb4                   ; ne = no, go get rate
  1312.         mov     bl,flags.comflg         ; pass current port ident
  1313.         call    comstrt                 ; do SET PORT command now
  1314.          ret                            ; failed to set port
  1315.          nop
  1316.          nop
  1317. getb4:  cmp     clone,0                 ; non-clone
  1318.         je      getbud                  ; e = yes, real thing
  1319.         ret                             ; have semi-clone, no bios feedback
  1320. getbud: push    ax                      ; save some regs
  1321.         push    bx
  1322.         push    cx
  1323.         push    dx
  1324.         mov     dx,modem.mdcom       ; Get current Line Control Register value
  1325.         in      al,dx
  1326.         mov     bl,al                   ; Save it
  1327.         or      ax,80H                ; Turn on to access baud rate generator
  1328.         out     dx,al
  1329.         mov     dx,modem.mddat          ; Divisor latch
  1330.         inc     dx
  1331.         in      al,dx                   ; Get hi order byte
  1332.         mov     ah,al                   ; Save here
  1333.         dec     dx
  1334.         in      al,dx                   ; Get lo order byte
  1335.         push    ax
  1336.         mov     dx,modem.mdcom          ; Line Control Register
  1337.         mov     al,bl                   ; Restore old value
  1338.         out     dx,al
  1339.         pop     ax
  1340.         cmp     ax,0FFFFH               ; Who knows what this is
  1341.         je      getb2
  1342.         mov     bx,offset bddat         ; Find rate's offset into table
  1343.         mov     cl,0                    ; Keep track of index
  1344. getb0:  cmp     ax,[bx]
  1345.         je      getb1
  1346.         inc     cl
  1347.         cmp     cl,baudlen              ; At the end of the list
  1348.         jge     getb2
  1349.         add     bx,2
  1350.         jmp     getb0
  1351. getb1:  mov     ch,0
  1352.         mov     bx,portval
  1353.         mov     [bx].baud,cx            ; Set baud rate
  1354.         jmp     getb3
  1355. getb2:  mov     ah,prstr
  1356. ;        mov     dx,offset erms40
  1357.         mcmsg   erms40,cerms40
  1358.         int     dos
  1359. getb3:  pop     dx                      ; restore regs
  1360.         pop     cx
  1361.         pop     bx
  1362.         pop     ax
  1363.         ret
  1364. GETBAUD ENDP
  1365.  
  1366. ; Get Char from serial port buffer.
  1367. ; skip returns if no character available at port,
  1368. ; otherwise returns with char in al, # of chars in buffer in dx.
  1369. ; Revised 22 May 1986, and again slightly 2 August 1986 by [jrd]
  1370. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1371. ; 25 April 1987 Add Netbios support, remove test for NUL and DEL. [jrd]
  1372. PRTCHR  PROC    NEAR
  1373.         cmp     holdscr,0               ; Holdscreen in effect?
  1374.         jne     prtch0a                 ; ne = yes, do not read
  1375.         call    chkxon                  ; see if we need to xon
  1376.         cmp     clone,'B'               ; running on a semi-clone?
  1377.         je      prtch6                  ; e = yes
  1378.         cmp     clone,'N'               ; running on NetBios network?
  1379.         je      prtchn                  ; e = yes
  1380.         cmp     clone, 'U'              ; running Ungermann-Bass port? [ohl]
  1381.         jne     prtch0                  ; ne = no
  1382. prtchn: test    xofsnt,usron            ; user level xoff sent?
  1383.         jnz     prtch0a                 ; nz = yes, suppress reading here
  1384.         cmp     count,mntrgl            ; below low water mark?
  1385.         ja      prtch1                  ; a = no, read current buffer
  1386.         cmp     clone,'U'               ; UB network?
  1387.         jne     prtchn1                 ; ne = no
  1388.         call    ubrecv                  ; do a UB receive
  1389.         jmp     short prtch0
  1390. prtchn1:call    receive                 ; do a NetBios receive (asynchronous)
  1391.         jc      prtch0a                 ; c = failure
  1392. prtch0: cmp     count,0                 ; any characters available?
  1393.         jnz     prtch1                  ; nz = yes, get one
  1394. prtch0a:mov     dx,0                    ; return count of zero
  1395.         jmp     rskp                    ; No data - check console
  1396. prtch1: push    si                      ; save si
  1397.         cli             ; interrupts off, to keep srcpnt & count consistent
  1398.         mov     si,srcpnt           ; address of next available slot in buffer
  1399.         sub     si,count            ; minus number of unread chars in buffer
  1400.         cmp     si,offset source        ; located before start of buf?
  1401.         jae     prtch2                  ; ae = no
  1402.         add     si,bufsiz               ; else do arithmetic modulo bufsiz
  1403. prtch2: mov     al,byte ptr [si]        ; get a character into al
  1404.         dec     count                   ; one less unread char now
  1405.         sti                             ; interrupts back on now
  1406.         pop     si
  1407.         mov     dx,count                ; return # of chars in buffer
  1408.         jmp     prtch12                 ; screen delivered characters
  1409.  
  1410. prtch6:                                 ; Semi-clone, use Bios calls
  1411.         mov     dx,0            ; assume port 1 Clone: find current port
  1412.         mov     dl,flags.comflg         ; get port number (1..4)
  1413.         or      dl,dl                   ; zero (no such port)?
  1414.         jz      prtch8                  ; z = yes, don't access it
  1415.         and     dl,7                    ; use low three bits
  1416.         dec     dl                      ; address ports as 0..3 for Bios
  1417. prtch7: mov     ah,3                    ; check port status
  1418.         int     rs232                   ; Clone Bios call
  1419.         test    ah,mdminp               ; data ready?
  1420.         jnz     prtch9                  ; nz = yes, get one
  1421. prtch8: mov     dx,0                    ; return count of zero
  1422.         mov     count,dx
  1423.         jmp     rskp                    ; No data
  1424. prtch9: mov     ah,2                    ; receive a char into al
  1425.         int     rs232                   ; Clone Bios call
  1426.         test    ah,8ch                  ; timeout, framing error, parity error?
  1427.         jnz     prtch8                  ; nz = error, no char
  1428.         mov     dx,1
  1429.         mov     count,dx                ; one char received into al
  1430.         cmp     al,flowoff              ; acting on Xoff?
  1431.         jne     prtch10                 ; ne = no, go on
  1432.         cmp     xofsnt,0                ; have we sent an outstanding XOFF?
  1433.         jne     prtch8                  ; ne = yes, ignore (possible echo)
  1434.         mov     xofrcv,bufon            ; Set the flag saying XOFF received
  1435.         jmp     prtch8                  ;  and exit
  1436. prtch10:cmp     al,flowon               ; acting on Xon?
  1437.         jne     prtch12                 ; ne = no, go on
  1438.         mov     xofrcv,off              ; Clear the XOFF received flag
  1439.         jmp     short prtch8            ; no data to return
  1440. prtch12:test    flags.debug,logses      ; debug mode?
  1441.         jnz     prtch14                 ; nz = yes, pass all chars
  1442.         cmp     rxtable+256,0           ; translation turned off?
  1443.         jne     prtch14                 ; ne = table is on, pass all chars
  1444.         cmp     al,0                    ; NUL?
  1445.         je      prtch13                 ; e = yes, ignore it
  1446.         cmp     tekflg,0                ; Tek emulation active?
  1447.         jne     prtch14                 ; ne = yes, pass DEL
  1448.         cmp     al,DEL                  ; DEL char
  1449.         jne     prtch14                 ; ne = no, pass char
  1450. prtch13:mov     dx,0
  1451.         jmp     rskp                    ; no chars
  1452. prtch14:ret                             ; return char in al
  1453. PRTCHR  ENDP
  1454.  
  1455. ; Network Receive packet routine. Request a net packet with no-wait option.
  1456. ; Return carry clear if success. If failure, reset serial port (Server mode
  1457. ; reinits serial port) and return carry set. No entry setup needed.
  1458. RECEIVE PROC    NEAR                    ; receive network session pkt
  1459.         cmp     pcnet,1                 ; net ready yet?
  1460.         jbe     receiv3                 ; be = no, declare a broken session
  1461.         cmp     rposted,1               ; is a request outstanding now?
  1462.         jae     receiv4                 ; ae = yes, don't do another
  1463.         mov     rposted,1               ; say posting a receive now
  1464.         mov     rcv.scb_length, length rcvbuf ; length of input buffer
  1465.         mov     rcv.scb_cmd,nreceive+nowait   ; receive, no wait
  1466.         push    bx
  1467.         mov     bx,offset rcv           ; setup pointer to scb
  1468.         call    session
  1469.         pop     bx                      ; tests below SHOULD take time
  1470.         cmp     rcv.scb_err,0           ; success?
  1471.         je      receiv4                 ; e = yes
  1472.         cmp     rcv.scb_err,npending    ; pending receive?
  1473.         je      receiv4                 ; e = yes
  1474.         push    ax                      ; wait one millisec before retesting
  1475.         push    cx
  1476.         mov     ax,1
  1477.         call    pcwait
  1478.         pop     cx
  1479.         pop     ax
  1480.         cmp     rcv.scb_err,06h         ; message incomplete?
  1481.         je      receiv4                 ; e = is ok (response posted later)
  1482.         cmp     rcv.scb_err,0        ; success now? (here for latency effects)
  1483.         je      receiv4                 ; e = yes
  1484.         cmp     rcv.scb_err,18h         ; session ended abnormally?
  1485.         jbe     receiv3                 ; e = yes, b = other normal errors
  1486.         push    ax                      ; save regs around error display
  1487.         push    dx
  1488.         mov     ah,prstr
  1489. ;        mov     dx,offset recmsg        ; give error message
  1490.         mcmsg   recmsg,crecmsg
  1491.         int     dos
  1492.         mov     al,rcv.scb_err          ; get error code
  1493.         call    hexout                  ; show error code
  1494.         pop     dx
  1495.         pop     ax
  1496.                                         ; Error return
  1497. receiv3:mov     pcnet,1                 ; say session is broken
  1498.         call    serrst                  ; reset serial port
  1499.         test    flags.remflg,dserver    ; server mode?
  1500.         jz      receiv3a                ; z = no
  1501.         call    serini                  ; reinitialize it for new session
  1502. receiv3a:stc                            ; say failure to receive
  1503.         ret
  1504. receiv4:clc                             ; carry clear = success
  1505.         ret
  1506. RECEIVE ENDP
  1507.  
  1508. ; Network Receive post processing interrupt routine.
  1509. ; Copy chars from rcvbuf to circular buffer source, act on xon/xoff,
  1510. ; clear rposted interlock flag. At entry, CS is our code segment,
  1511. ; es:bx points to scb, netbios stack, interrupts are off.
  1512. RPOST   PROC    NEAR            ; network receive post interrupt routine
  1513.         push    ds              ; transfers chars from net buf rcvbuf to
  1514.         push    ax              ; main circular buffer source
  1515.         push    bx
  1516.         push    cx
  1517.         push    dx
  1518.         push    si
  1519.         mov     ax,datas                ; reestablish datas segment
  1520.         mov     ds,ax
  1521.         mov     cx,rcv.scb_length       ; get returned byte count
  1522.         jcxz    rpost6                  ; z = nothing there
  1523.         mov     dh,flowon             ; flow control characters, for quick ref
  1524.         mov     dl,flowoff
  1525.         mov     si,offset rcvbuf        ; source of text
  1526.         mov     bx,srcpnt               ; address of buffer storage slot
  1527.         cld
  1528. rpost1: lodsb                           ; get byte from rcvbuf to al
  1529.         or      dx,dx                   ; doing flow control?
  1530.         jz      rpost3                  ; z = no
  1531.         mov     ah,al                   ; get copy of character
  1532.         and     ah,parmsk               ; strip parity, if any, before testing
  1533.         cmp     ah,dl                   ; acting on Xoff?
  1534.         jne     rpost2                  ; ne = Nope, go on
  1535.         cmp     xofsnt,0                ; have we sent an XOFF?
  1536.         jne     rpost5                  ; ne = yes, ignore this XOFF char
  1537.         mov     xofrcv,bufon        ; Set the flag saying buffer XOFF received
  1538.         jmp     rpost5                  ;  and skip this character
  1539. rpost2: cmp     ah,dh                   ; acting on Xon?
  1540.         jne     rpost3                  ; ne = no, go on
  1541.         mov     xofrcv,off              ; Clear the XOFF received flag
  1542.         jmp     rpost5                  ;  and skip this character
  1543.  
  1544. rpost3: mov     byte ptr [bx],al       ; store the new char in buffer "source"
  1545.         inc     bx
  1546.         cmp     bx,offset source + bufsiz ; beyond end of buffer?
  1547.         jb      rpost4                  ; b = not past end
  1548.         mov     bx,offset source        ; wrap buffer around
  1549. rpost4: cmp     count,bufsiz            ; filled already?
  1550.         jae     rpost5                  ; ae = yes
  1551.         inc     count                   ; no, add a char
  1552. rpost5: loop    rpost1
  1553.         mov     srcpnt,bx               ; update pointer to next free slot
  1554. rpost6: mov     rposted,0               ; clear interlock flag
  1555.         pop     si
  1556.         pop     dx
  1557.         pop     cx
  1558.         pop     bx
  1559.         pop     ax
  1560.         pop     ds
  1561.         iret                            ; return from interrupt
  1562. RPOST   endp
  1563.  
  1564. ; Ungermann-Bass NETCI port receive characters routine.  Receive one or more
  1565. ; characters.  Calls the Rpost routine to transfer character to main source
  1566. ; circular buffer.  Return carry clear if success.
  1567. UBRECV  PROC    near
  1568.         push    ax
  1569.         push    bx
  1570.         push    cx
  1571.         push    es
  1572.         mov     ax, datas
  1573.         mov     es, ax                  ; es:bx will point to rcvbuf
  1574.         mov     ax, nciread             ; function 1 (receive) port 0    [ohl]
  1575.         mov     bx, offset rcvbuf
  1576.         mov     cx, length rcvbuf
  1577.         int     netci                   ; get characters                 [ohl]
  1578.         stc
  1579.         jcxz    ubrec1                  ; cx = z = nothing to do
  1580.         mov     rcv.scb_length, cx      ; prepare for rpost call         [ohl]
  1581.         mov     bx, offset rcv
  1582.         pushf                           ; simulate interrupt             [ohl]
  1583.         push    cs                      ; rpost is an interrupt routine (iret)
  1584.         call    rpost                   ; do Near call with preset stack
  1585.         clc
  1586. ubrec1: pop     es
  1587.         pop     cx
  1588.         pop     bx
  1589.         pop     ax
  1590.         ret
  1591. UBRECV  ENDP
  1592.  
  1593. ; Put the char in AH to the serial port.  This assumes the
  1594. ; port has been initialized.  Should honor xon/xoff.  Skip returns on
  1595. ; success, returns normally if the character cannot be written.
  1596. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  1597. ; 25 April 1987 Add Netbios support [jrd]
  1598. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  1599. ; prevent confusion of flow control logic at top of outchr; used by receiver
  1600. ; buffer high/low water mark flow control code. [jrd]
  1601. OUTCHR  PROC    NEAR
  1602.         cmp     flowoff,0               ; Are we doing flow control
  1603.         je      outch2                  ; No, just continue
  1604.         cmp     ah,flowoff              ; sending xoff?
  1605.         jne     outch1                  ; ne = no
  1606.         mov     xofsnt,usron            ; indicate user level xoff being sent
  1607.         jmp     outch1b
  1608. outch1: cmp     ah,flowon               ; user sending xon?
  1609.         jne     outch1b                 ; ne = no
  1610.         mov     xofsnt,off           ; say an xon has been sent (cancels xoff)
  1611. outch1b:cmp     xofrcv,off              ; Are we being held (xoff received)?
  1612.         je      outch2                  ; e = no - it's OK to go on
  1613.         cmp     flags.timflg,0          ; is timer off?
  1614.         je      outch2                  ; e = yes, no timeout period
  1615.         push    cx                      ; save reg
  1616.         mov     ch,trans.rtime          ; receive timeout interval (sec)
  1617.         mov     cl,0                    ;  convert to 4 millsec increments
  1618.         jcxz    outch1c                 ; z = no timeout wanted
  1619.  
  1620. outch1a:cmp     xofrcv,off              ; Are we being held (xoff received)?
  1621.         je      outch1c                 ; e = no - it's OK to go on
  1622.         push    ax
  1623.         mov     ax,4                    ; 4 millisec wait loop
  1624.         call    pcwait
  1625.         pop     ax
  1626.         loop    outch1a                 ; and try it again
  1627.         mov     xofrcv,off              ; timed out, force it off and fall thru
  1628. outch1c:pop     cx                      ; end of flow control section
  1629.                      ; OUTCH2 is entry point for sending without flow control
  1630. OUTCH2: mov     al,ah                   ; Parity routine works on AL
  1631.         call    dopar                   ; Set parity appropriately
  1632.         mov     ah,al                   ; Don't overwrite character with status
  1633. outch3: cmp     clone,0                 ; real uart?
  1634.         je      outch3a                 ; e = yes
  1635.         cmp     clone,'N'               ; network?
  1636.         je      outch8                  ; e = yes, using netbios
  1637.         cmp     clone,'U'               ; Ungermann Bass network?
  1638.         je      outch8                  ; e = yes
  1639.         jmp     outch6                  ; default for others ('B' clones)
  1640. outch3a:push    cx                      ; Save registers
  1641.         push    dx
  1642.         sub     cx,cx
  1643. outch3b:mov     dx,modem.mdstat         ; Get port status
  1644.         in      al,dx
  1645.         test    al,20H                  ; Transmitter ready?
  1646.         jnz     outch4                  ; Yes
  1647.         jmp     $+2                     ; use time, prevent overdriving UART
  1648.         jmp     $+2
  1649.         loop    outch3b
  1650.          jmp    outch5                  ; Timeout
  1651. outch4: mov     al,ah                   ; Now send it out
  1652.         mov     dx,modem.mddat          ; use a little time
  1653.         jmp     $+2
  1654.         out     dx,al
  1655.         pop     dx                      ; exit success
  1656.         pop     cx
  1657.         jmp     rskp
  1658. outch5: pop     dx                      ; exit failure
  1659.         pop     cx
  1660.         ret
  1661.                                 ; finish up for semi-clones, use Bios calls
  1662. outch6: push    cx                      ; Clone: find current port
  1663.         push    dx
  1664.         mov     dx,0                    ; assume port 1
  1665.         mov     dl,flags.comflg         ; get port number (1..4)
  1666.         or      dl,dl                   ; zero (no such port)?
  1667.         jz      outch5                  ; z = yes, don't access it
  1668.         and     dl,7                    ; use lower three bits
  1669.         dec     dl                      ; address ports as 0..3 for Bios
  1670.         mov     al,ah                   ; Now send it out
  1671.         mov     ah,1                    ; send char
  1672.         int     rs232                   ; Clone: bios send
  1673.         pop     dx                      ; exit success
  1674.         pop     cx
  1675.         jmp     rskp
  1676. outch8:                         ; Network sending, buffered and single char
  1677.         push    bx
  1678.         mov     bx,xmtcnt               ; count of chars in buffer
  1679.         mov     xmtbufx[bx],ah          ; put char in buffer
  1680.         pop     bx
  1681.         inc     xmtcnt                  ; count of items in this buffer
  1682.         cmp     xmtcnt,length xmtbuf    ; is buffer full now?
  1683.         jae     outch9                  ; ae = buffer is full, send it now
  1684.         cmp     ah,trans.seol           ; end of packet?
  1685.         je      outch9                  ; e = yes, send buffer
  1686.         cmp     ah,flowon               ; flow control?
  1687.         je      outch9                  ; e = yes, always expedite
  1688.         cmp     ah,flowoff              ; ditto for flow off
  1689.         je      outch9
  1690.         cmp     ttyact,0                ; are we in Connect mode?
  1691.         je      outch10                 ; e = no, wait for more before sending
  1692. outch9: cmp     clone, 'U'              ; check for UB port      [ohl]
  1693.         je      outch12                 ; e = yes                [ohl]
  1694.         call    send                    ; NetBios network send routine
  1695.         jc      outch11                 ; c = error
  1696. outch10:jmp     rskp                    ; good  exit
  1697. outch11:ret                             ; bad   exit
  1698.  
  1699. outch12:call    ubsend                  ; UB network send        [ohl]
  1700.         jmp     rskp                    ; good exit              [ohl]
  1701. OUTCHR  ENDP
  1702.  
  1703. ; Network Send packet routine. Send xmt scb with no-wait option. Waits
  1704. ; up to 6 seconds for current Send to complete before emitting new Send.
  1705. ; Failure to Send resets serial port (Server mode allows reiniting of serial
  1706. ; port). Returns carry clear for success, carry set for failure.
  1707. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  1708. SEND    PROC    NEAR                    ; Network. Send session packet
  1709.         cmp     pcnet,1                 ; network ready yet?
  1710.         ja      send0b                  ; a = net is operational
  1711.         je      send0c                  ; e = net but no session, fail
  1712.         jmp     send3a                  ; no net, fail
  1713. send0c: jmp     send3                   ; net but no session
  1714. send0b: cmp     sposted,0               ; is a send outstanding now?
  1715.         je      send1                   ; e = no, go ahead
  1716.         push    cx                      ; Timed test for old send being done
  1717.         mov     ch,trans.rtime          ; receive timeout other side wants
  1718.         mov     cl,80h                  ; plus half a second
  1719.         shl     cx,1                    ; sending timeout * 512
  1720. send0:  cmp     sposted,0               ; is a send outstanding now?
  1721.         je      send0a                  ; e = no, clean up and do send
  1722.         push    cx                      ; save cx
  1723.         push    ax                      ; and ax
  1724.         mov     ax,2                    ; wait 2 milliseconds
  1725.         call    pcwait                  ;  between retests
  1726.         pop     ax
  1727.         pop     cx                      ; loop counter
  1728.         loop    send0                   ; repeat test
  1729.         pop     cx                      ; recover cx
  1730.         jmp     send3a                  ; get here on timeout, can't send
  1731. send0a: pop     cx                      ; recover cx and proceed to send
  1732.  
  1733. send1:  cmp     xmtcnt,0                ; number of items to send
  1734.         jne     send1a                  ; ne = some
  1735.         clc                             ; else don't send null packets
  1736.         ret
  1737. send1a: push    bx                      ; save bx
  1738.         mov     bx,xmtcnt               ; buffer length
  1739.         mov     xmt.scb_length,bx       ; tell buffer length
  1740.         push    cx
  1741.         push    si
  1742.         push    di
  1743.         push    es
  1744.         push    ds
  1745.         pop     es                      ; set es to datas segment
  1746.         mov     si,offset xmtbufx       ; external buffer
  1747.         mov     di,offset xmtbuf        ; copy for network packets
  1748.         mov     cx,bx                   ; buffer length
  1749.         shr     cx,1                    ; divide by two (words), set carry
  1750.         jnc     send2                   ; nc = even number of bytes
  1751.         movsb                           ; do single move
  1752. send2:  cmp     cx,0
  1753.         jle     send2a                  ; le = none to do
  1754.         rep     movsw                   ; copy the data
  1755. send2a: pop     es
  1756.         pop     di
  1757.         pop     si
  1758.         pop     cx
  1759.         mov     xmtcnt,0                ; say xmtbufx is available again
  1760.         mov     xmt.scb_cmd,nsend+nowait ; send, don't wait for completion
  1761.         mov     sposted,1               ; say send posted
  1762.         mov     bx,offset xmt           ; set pointer to scb
  1763.         call    session
  1764.         pop     bx                      ; recover pointer to scb
  1765.                                         ; success or failure?
  1766.         cmp     xmt.scb_err,0           ; good return?
  1767.         je      send4                   ; e = yes
  1768.         cmp     xmt.scb_err,npending    ; pending?
  1769.         je      send4                   ; e = yes
  1770.         cmp     xmt.scb_err,18h         ; session ended abnormally?
  1771.         jbe     send3                   ; e = yes, b = other normal errors
  1772.         push    ax
  1773.         push    dx                      ; another kind of error, show message
  1774.         mov     ah,prstr
  1775. ;        mov     dx,offset sndmsg        ; say send failed
  1776.         mcmsg   sndmsg,csndmsg
  1777.         int     dos
  1778.         mov     al,xmt.scb_err          ; show error code (hex)
  1779.         call    hexout
  1780.         pop     dx
  1781.         pop     ax
  1782.                                         ; Error return
  1783. send3:  mov     pcnet,1                 ; say session is broken
  1784.         call    serrst                  ; reset serial port
  1785.         test    flags.remflg,dserver    ; server mode?
  1786.         jz      send3a                  ; z = no
  1787.         call    nethangup               ; Server: purge old NAKs etc
  1788. send3a: call    serini                  ; reinitialize it for new session
  1789.         stc                             ; set carry for failure to send
  1790.         ret
  1791. send4:  clc
  1792.         ret
  1793. SEND    ENDP
  1794.  
  1795. ; Network Send packet completion interrupt routine. At entry CS is our
  1796. ; code segment, es:bx points to scb, netbios stack, interrupts are off.
  1797. SPOST   PROC    NEAR                    ; post routine for Send packets
  1798.         push    ds
  1799.         push    ax
  1800.         mov     ax,datas
  1801.         mov     ds,ax
  1802.         mov     sposted,0               ; clear send interlock
  1803.         pop     ax
  1804.         pop     ds
  1805.         iret
  1806. SPOST   ENDP
  1807.  
  1808. ; Ungermann-Bass NETCI port send packet routine. [ohl] +++
  1809. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  1810. ubsend  proc    near
  1811.         push    ax
  1812.         push    bx
  1813.         push    cx
  1814.         push    es
  1815.         mov     cx, xmtcnt              ; number of chars                [ohl]
  1816.         jcxz    ubsend1                 ; dont send zero chars           [ohl]
  1817.         mov     bx, offset xmtbufx      ; buffer address in es:bx        [ohl]
  1818.         mov     ax, datas
  1819.         mov     es, ax
  1820. ubsend2:
  1821.         mov     ax, nciwrit             ; write function, port 0         [ohl]
  1822.         int     netci
  1823.         cmp     cx,xmtcnt               ; check that all characters sent [ohl]
  1824.         je      ubsend1                 ; e = yes                        [ohl]
  1825.         add     bx, cx                  ; point to remaining chars       [ohl]
  1826.         sub     xmtcnt,cx               ; count of remaining characters  [ohl]
  1827.         mov     cx,xmtcnt               ; need count in cx too
  1828.         jmp     short   ubsend2         ; try again to send              [ohl]
  1829. ubsend1:mov     xmtcnt,0
  1830.         pop     es
  1831.         pop     cx
  1832.         pop     bx
  1833.         pop     ax
  1834.         ret
  1835. ubsend  endp                            ;  [ohl] ---
  1836.  
  1837.  
  1838. ; dispatch prebuilt network session scb, enter with bx pointing to scb.
  1839. ; returns status in al (and ah too). Allows STARLAN Int 2ah for netint.
  1840. SESSION PROC    NEAR
  1841.         push    es                      ; save es around call
  1842.         push    ds
  1843.         pop     es                      ; make es:bx point to scb in datas seg
  1844.         mov     ax,exnbios              ; funct 4 execute netbios, for Int 2ah
  1845.         int     netint                  ; use network interrupt
  1846.         pop     es                      ; saved registers
  1847.         ret                             ; exit with status in ax
  1848. SESSION ENDP
  1849.  
  1850. ; Make a virtual circuit Session, given preset scb's from proc chknet.
  1851. ; For Server mode, does a Listen to '*', otherwise does a Call to indicated
  1852. ; remote node. Updates vcid number in scb's. Shows success or fail msg.
  1853. ; Updates network status byte pcnet to 2 if session is established.
  1854. ; Does nothing if a session is active upon entry; otherwise, does a network
  1855. ; hangup first to clear old session material from adapter board. This is
  1856. ; the second procedure to call in initializing the network for usage.
  1857. SETNET  PROC    NEAR                    ; Network, make a connection
  1858.         cmp     lposted,1               ; Listen pending?
  1859.         je      setne0                  ; e = yes, exit now
  1860.         cmp     pcnet,1                 ; session active?
  1861.         jbe     setne1                  ; be = no
  1862. setne0: ret
  1863.                                         ; No Session
  1864. setne1: call    nethangup               ; clear old session material
  1865.         test    flags.remflg,dserver    ; Server mode?
  1866.         jz      setne2                  ; z = no, file xfer or Connect
  1867.                                         ; Server mode, post a Listen (async)
  1868.         mov     lsn.scb_rname,'*'       ; accept anyone
  1869.         mov     ax,500
  1870.         call    pcwait                  ; 0.5 sec wait
  1871.         push    bx
  1872.         mov     lposted,1               ; set listen interlock flag
  1873.         mov     lsn.scb_cmd,nlisten+nowait ; do LISTEN command, no wait
  1874.         mov     bx,offset lsn
  1875.         call    session
  1876.         pop     bx
  1877.         ret
  1878. setne2:                                 ; Non-server (Client) mode
  1879.         push    bx                      ; save reg
  1880.         test    nettype,starlan         ; STARLAN?
  1881.         jz      setne2a                 ; z = no
  1882.         cmp     xmt.scb_vrlen,0         ; yes, using long name support?
  1883.         je      setne2a                 ; e = no
  1884.         push    es                      ; save reg
  1885.         push    ds
  1886.         pop     es                      ; make es:bx point to xmt scb
  1887.         mov     bx,offset xmt           ; use xmt scb for the call
  1888.         mov     xmt.scb_cmd,ncall       ; CALL_ISN, vrname + vrlen are ready
  1889.         int     5bh                     ; STARLAN CALL Int 5bh, wait
  1890.         pop     es                      ; restore regs
  1891.         pop     bx
  1892.         jmp     short setne3            ; finish up
  1893.  
  1894. setne2a:                                ; Regular Netbios Call
  1895.         mov     xmt.scb_cmd,ncall       ; CALL, wait for answer
  1896.         mov     bx,offset xmt           ; setup scb pointer
  1897.         call    session
  1898.         pop     bx                      ; restore register
  1899.  
  1900. setne3: push    dx                      ; common Call completion, show status
  1901.         test    xmt.scb_err,0ffh        ; is there a non-zero return code?
  1902.         jnz     setne3a                 ; nz = yes, do bad return
  1903.         or      al,al                   ; check error return
  1904.         jnz     setne3a                 ; nz = bad connection
  1905.         jmp     short setne4            ; good connection so far
  1906. setne3a:
  1907. ;       mov     dx,offset nbadset       ; say can't reach remote node
  1908.         mcmsg   nbadset,cnbadset
  1909.         mov     ah,prstr
  1910.         int     dos
  1911.         call    saynode                 ; show remote host node name
  1912.         jmp     setne4c
  1913.                                         ; keep results of Call (vcid)
  1914. setne4: mov     al,xmt.scb_vcid         ; local session number
  1915.         mov     rcv.scb_vcid,al         ; for receiver too
  1916.         mov     can.scb_vcid,al         ; for sending Breaks
  1917.         mov     pcnet,2                 ; say session has started
  1918.         test    flags.remflg,dregular+dquiet ; regular or quiet display?
  1919.         jnz     setne4c                 ; nz = yes, show only no-connect msg
  1920. ;        mov     dx,offset ngodset       ; say good connection
  1921.         mcmsg   ngodset,cngodset
  1922.         mov     ah,prstr
  1923.         int     dos
  1924.         call    saynode                 ; show remote host name
  1925. setne4c:pop     dx
  1926.         cmp     pcnet,1                 ; check connection again
  1927.         ja      setne5                  ; a = good so far
  1928.         stc                             ; set carry for failure
  1929.         ret
  1930. setne5: clc                             ; carry clear for success
  1931.         ret
  1932. SETNET  ENDP
  1933.  
  1934. saynode proc    near            ; display node name on screen, si=name ptr
  1935.         push    ax
  1936.         push    cx
  1937.         push    dx
  1938.         push    si
  1939.         mov     ah,conout
  1940.         mov     si,offset nambuf        ; remote node string
  1941.         mov     cx,64                   ; up to 64 bytes long
  1942. saynod1:cld
  1943.         lodsb                           ; get remote node name char into al
  1944.         mov     dl,al
  1945.         int     dos                     ; display it
  1946.         cmp     al,' '                  ; was it a space?
  1947.         jbe     saynod2                 ; be = yes, quit here
  1948.         loop    saynod1                 ; do all 16 chars
  1949. saynod2:mov     ah,prstr
  1950.         mov     dx,offset crlf
  1951.         int     dos
  1952.         pop     si
  1953.         pop     cx
  1954.         pop     cx
  1955.         pop     ax
  1956.         ret
  1957. saynode endp
  1958.  
  1959. LPOST   PROC    FAR             ; Interrupt Post routine for Listen call
  1960.         push    ds              ; update vcid and calling node name in scb's
  1961.         push    cx
  1962.         push    es
  1963.         push    si
  1964.         push    di
  1965.         mov     cx,datas                ; reestablish datas segment
  1966.         mov     ds,cx
  1967.         mov     es,cx
  1968.         mov     si,offset lsn.scb_rname ; copy remote name to rcv and xmt scbs
  1969.         push    si
  1970.         mov     di,offset rcv.scb_rname
  1971.         mov     cx,8                    ; 16 byte field
  1972.         cld
  1973.         rep     movsw
  1974.         mov     cx,8
  1975.         pop     si
  1976.         push    si
  1977.         mov     di,offset xmt.scb_rname
  1978.         rep     movsw
  1979.         mov     cx,8
  1980.         pop     si
  1981.         mov     di,offset nambuf        ; and to nambuf for display
  1982.         rep     movsw
  1983.         mov     cl,lsn.scb_vcid         ; local session number
  1984.         mov     rcv.scb_vcid,cl
  1985.         mov     xmt.scb_vcid,cl
  1986.         mov     can.scb_vcid,cl
  1987.         mov     lposted,0               ; clear interlock flag
  1988.         mov     pcnet,2                 ; say net ready due to a Listen
  1989.         pop     di
  1990.         pop     si
  1991.         pop     es
  1992.         pop     cx
  1993.         pop     ds
  1994.         iret                            ; return from interrupt
  1995. LPOST   ENDP
  1996.  
  1997.  
  1998. NETHANGUP PROC  NEAR                 ; disconnect network session, keep names
  1999.         cmp     pcnet,0                 ; network started?
  2000.         je      nethang1                ; e = no
  2001.         cmp     clone, 'U'              ; Ungermann-Bass port? [ohl]
  2002.         je      nethang2                ; e = yes [ohl]
  2003.         push    bx                      ; NetBios network
  2004.         mov     bx,offset can
  2005.         mov     can.scb_cmd,ncancel     ; set cancel op code
  2006.         mov     can.scb_baddr,offset lsn ; cancel listens
  2007.         mov     lposted,0               ; say no listen
  2008.         call    session
  2009.         mov     can.scb_baddr,offset rcv ; cancel receives
  2010.         call    session
  2011.         mov     rposted,0               ; say no receives posted
  2012.         mov     can.scb_baddr,offset xmt ; cancel sends
  2013.         call    session
  2014.         mov     sposted,0               ; say no sends posted
  2015.         mov     xmtcnt,0                ; reset output buffer counter
  2016.         mov     xmt.scb_cmd,nhangup     ; hangup, and wait for completion
  2017.         mov     bx,offset xmt
  2018.         call    session
  2019.         pop     bx
  2020.         mov     pcnet,1                 ; say network but no session
  2021.         call    serrst                  ; reset the serial port for reiniting
  2022. nethang1:ret
  2023.                                         ; UB network [ohl] +++
  2024. nethang2:call   ubclose                 ; close connection if any [ohl]
  2025.         mov     xmtcnt,0
  2026.         mov     pcnet,1
  2027.         ret                             ;  [ohl] ---
  2028. NETHANGUP ENDP
  2029.  
  2030. ; Ungermann Bass. Do a disconnect from the current connection.
  2031. ubclose proc    near
  2032.         push    ax
  2033.         push    cx
  2034.         cmp     nettype,netone          ; UB network has been activated?
  2035.         jz      ubclos1                 ; z = no
  2036.         mov     ax, ncistat             ; get status                     [ohl]
  2037.         int     netci
  2038.         cmp     ch, 1                   ; check if we have a connection  [ohl]
  2039.         jne     ubclos1                 ; ne = no                        [ohl]
  2040.         mov     ax, ncicont             ; control function               [ohl]
  2041.         mov     cx, ncidis              ; say disconnect                 [ohl]
  2042.         int     netci
  2043. ubclos2:call    ubrecv                  ; read response from net cmdintpr[ohl]
  2044.         jnc     ubclos2                 ; continue till no chars         [ohl]
  2045. ubclos1:and     nettype,not netone      ; remove network type
  2046.         mov     pcnet,0                 ; say no network
  2047.         pop     cx
  2048.         pop     dx
  2049.         ret
  2050. ubclose endp
  2051.  
  2052. ; Called when Kermit exits. Name passed to mssker by proc chknet
  2053. ; in word lclexit.
  2054. NETCLOSE PROC   NEAR                    ; close entire network connection
  2055.         cmp     pcnet,0                 ; network ever used?
  2056.         je      netclo1                 ; e = no, so don't touch it
  2057.         call    nethangup               ; close connections
  2058.         test    nettype,netbios         ; NetBios activated?
  2059.         jz      netclo1                 ; z = no
  2060.         push    bx
  2061.         mov     bx,offset xmt
  2062.         mov     xmt.scb_cmd,ndelete     ; delete our local Kermit name
  2063.         call    session                 ;  from net adapter board
  2064.         pop     bx
  2065.         mov     pcnet,0                 ; say no network
  2066.         and     nettype,not netbios     ; remove network kind
  2067. netclo1:ret
  2068. NETCLOSE ENDP
  2069.  
  2070. ; Start connection process to network. Obtains Network board local name
  2071. ; and appends '.K' to form Kermit's local name (removed when Kermit exits).
  2072. ; If no local name is present then use name 'mskermit.K'.
  2073. ; Sets local name in scb's for xmt, rcv, lsn. (Does not need DOS 3.x)
  2074. ; Sets NETDONE pointer to procedure netclose for Kermit exit.
  2075. ; Verifies existance of interrupt 5ch support, verifies vendor specific
  2076. ; support for BREAK and other features, sets network type bit in nettype,
  2077. ; sets BREAK support in nsbrk, hangsup old session if new node name given,
  2078. ; fills in local and remote node names and name number in scbs (including ISN
  2079. ; names for STARLAN), and sets network status byte pcnet to 0 (no net) or
  2080. ; to 1 (net ready). This is the first procedure called to init network usage.
  2081. ; Byte count of new host name is in temp from COMS.
  2082. chknet  proc    near
  2083.         cmp     clone,'U'               ; Ungermann Bass network?
  2084.         jne     chknea                  ; ne = no
  2085.         mov     pcnet,0                 ; force reactivation of UB net
  2086. chknea: cmp     pcnet,2                 ; session active now?
  2087.         jb      chknec                  ; b = no
  2088.         cmp     temp,0                  ; byte count of new name, if any
  2089.         je      chkneb                  ; e = none, resume old session
  2090. ;        mov     dx,offset naskpmt       ; prompt for New or Resume
  2091.         mcmsg   naskpmt,cnaskpmt
  2092.         call    prompt
  2093.         mov     dx,offset nettab        ; table of answers
  2094.         mov     bx,0                    ; help for the question
  2095.         mov     ah,cmkey                ; get answer keyword
  2096.         call    comnd
  2097.          jmp r                          ; failed
  2098.          nop
  2099.         mov     rdbuf,bl                ; save keyword action value here
  2100.         mov     ah,cmcfm                ; get a confirm
  2101.         call    comnd
  2102.          jmp    r                       ; no confirm
  2103.          nop
  2104.         cmp     rdbuf,0                 ; New session?
  2105.         je      chkneb                  ; e = yes
  2106.         clc
  2107.         ret                             ; resume old one
  2108. chkneb: jmp     chknet1                 ; skip presence tests
  2109.  
  2110. chknec:                         ; setup addresses and clear junk in scb's
  2111.         cmp     pcnet,0                 ; have we been here already?
  2112.         je      chkned                  ; e = no
  2113.         jmp     chknet1                 ; yes, skip init part
  2114. chkned: mov     xmtcnt,0                ; say buffer is empty
  2115.         mov     nsbrk,0                 ; assume no BREAK across network
  2116.         and     nettype,not netbios     ; say no NetBios network yet
  2117.  
  2118.         push    bx
  2119.         push    es                      ; Test for Netbios presence, IBM way
  2120.         mov     ah,35h                  ; DOS get interrupt vector
  2121.         mov     al,netint               ; the netbios vector
  2122.         int     dos                     ; returns vector in es:bx
  2123.         mov     ax,es
  2124.         cmp     ax,0f000h               ; rom bios segment??
  2125.         jb      chknee                  ; b = not likely, else Bios has
  2126.         mov     ax,0                    ;  trapped this vector to dummy iret
  2127.         mov     bx,0                    ; fake null vector
  2128. chknee: or      bx,ax                   ; is vector present?
  2129.         pop     es
  2130.         pop     bx
  2131.         jz      chknet0                 ; z = no
  2132.         mov     xmt.scb_cmd,7fh ; presence test, 7fh is illegal command code
  2133.         mov     xmt.scb_err,0           ; clear response field
  2134.         push    bx
  2135.         mov     bx,offset xmt           ; address of the session control block
  2136.         call    session                 ; execute operation
  2137.         pop     bx
  2138.         mov     al,xmt.scb_err          ; get response
  2139.         cmp     xmt.scb_err,3       ; 'illegal function', so adapter is ready
  2140.         jne     chknet0                 ; ne = failure
  2141.         push    bx
  2142.         push    es                      ; Test for Netbios presence, IBM way
  2143.         mov     ah,35h                  ; DOS get interrupt vector
  2144.         mov     al,2ah                  ; the netbios vector 2ah
  2145.         int     dos                     ; returns vector in es:bx
  2146.         mov     ax,es
  2147.         cmp     ax,0f000h               ; rom bios segment??
  2148.         jb      chknef                  ; b = not likely
  2149.         mov     ax,0
  2150.         mov     bx,0                    ; fake null vector
  2151. chknef: or      bx,ax                   ; is vector present?
  2152.         pop     es
  2153.         pop     bx
  2154.         jz      chknet0                 ; z = no, no NetBios network
  2155.         or      nettype,netbios         ; say have NetBios network
  2156.                                 ; AT&T STARLAN board check (0ddh=magic #)
  2157.         mov     ah,0                    ; vendor installation check on int 2ah
  2158.         mov     al,0                    ; do error retry
  2159.         int     2ah                     ; session level interrupt
  2160.         cmp     ah,0ddh                 ; 0ddh = magic number, success?
  2161.         jne     chknet1                 ; ne = no
  2162.         or      nettype,starlan         ; say using STARLAN, have int 2ah
  2163.         push    bx
  2164.         push    es                      ; Test for vector
  2165.         mov     ah,35h                  ; DOS get interrupt vector
  2166.         mov     al,5bh                  ; 5bh = STARLAN netbios ext'd vector
  2167.         int     dos                     ; returns vector in es:bx
  2168.         mov     ax,es
  2169.         or      bx,ax                   ; is vector present?
  2170.         pop     es
  2171.         pop     bx
  2172.         jz      chknet1                 ; z = no
  2173.         mov     nsbrk,1                 ; network BREAK supported
  2174.         jmp     chknet1
  2175.  
  2176. chknet0:mov     pcnet,0                 ; no network yet
  2177.         push    ax
  2178.         push    dx
  2179.         mov     ah,prstr
  2180. ;        mov     dx,offset nonetmsg      ; say network is not available
  2181.         mcmsg   nonetmsg,cnonetmsg
  2182.         int     dos
  2183.         pop     dx
  2184.         pop     ax
  2185.         stc                             ; set carry for failure
  2186.         ret                             ; and exit now
  2187.  
  2188.                                         ; net ready to operate
  2189. chknet1:cmp     temp,0                  ; byte count of new name, from COMS
  2190.         jne     chkne1e                 ; ne = new name given
  2191.         jmp     chknet2                 ; nothing, so leave names intact
  2192. chkne1e:cmp     pcnet,2                 ; is session active now?
  2193.         jb      chkne1d                 ; b = no
  2194.         call    nethangup               ; hangup net to clear old connection
  2195. chkne1d:                                ; start fresh connection
  2196.         push    si
  2197.         push    di
  2198.         push    es
  2199.         push    ds
  2200.         pop     es                      ; make es:di point to datas segment
  2201.         cld
  2202.         mov     cx,8                    ; 16 bytes for a node name
  2203.         mov     ax,'  '                 ; first, fill with spaces
  2204.         mov     di,offset xmt.scb_rname ; remote name field, clear it
  2205.         rep     stosw
  2206.         test    nettype,starlan         ; STARLAN?
  2207.         jz      chkne1b                 ; z = no
  2208.                                         ; begin STARLAN section
  2209.         mov     xmt.scb_vrname,0        ; STARLAN var length name ptr
  2210.         mov     xmt.scb_vrname+2,0      ; segement of name
  2211.         mov     xmt.scb_vrlen,0         ; and its length
  2212.         mov     cx,temp                 ; count of characters in new name
  2213.         cmp     cx,16                   ; > 16 chars in remote node name?
  2214.         ja      chkne1a                 ; a = yes, too long for Netbios
  2215.         mov     al,'/'                  ; scan for slashes in name
  2216.         mov     di,offset nambuf        ; source of text
  2217.         push    es                      ; save es around scan
  2218.         push    ds
  2219.         pop     es                      ; point es at datas segment
  2220.         cld
  2221.         repne   scasb                   ; look for the slash
  2222.         pop     es
  2223.         jne     chkne1b         ; ne = none, do regular Netbios name storage
  2224. chkne1a:                                ; STARLAN ISN long remote name support
  2225.         mov     xmt.scb_vrname,offset nambuf    ; STARLAN var length name ptr
  2226.         mov     xmt.scb_vrname+2,datas          ; segment of remote name
  2227.         mov     cx,temp                 ; get name length again (in cl)
  2228.         mov     xmt.scb_vrlen,cl        ; indicate its length
  2229.         jmp     chkne1c                 ; copy blanks in remote name field
  2230.                                         ; end STARLAN section
  2231.  
  2232. chkne1b:mov     cx,temp                 ; Regular Netbios form, name length
  2233.         mov     si,offset nambuf        ; source of text
  2234.         mov     di,offset xmt.scb_rname ; destination is remote name
  2235.         rep     movsb                   ; copy text to transmitter's scb
  2236.         mov     cx,16
  2237. chkne1c:mov     cx,8                    ; 8 words
  2238.         mov     si,offset xmt.scb_rname ; from here
  2239.         mov     di,offset rcv.scb_rname ; to receiver's scb also
  2240.         rep     movsw
  2241.         pop     es
  2242.         pop     di
  2243.         pop     si
  2244.  
  2245. chknet2:cmp     pcnet,0                 ; started net?
  2246.         je      chknet2c                ; e = no
  2247.         ret                             ; else quit here
  2248. chknet2c:
  2249.         mov     ah,prstr
  2250. ;        mov     dx,offset netmsg1       ; say checking node name
  2251.         mcmsg   netmsg1,cnetmsg1
  2252.         int     dos
  2253.         push    word ptr xmt.scb_rname  ; save first two bytes (user spec)
  2254.         mov     byte ptr xmt.scb_rname,'*'      ; call to local name
  2255.         push    bx
  2256.         mov     xmt.scb_cmd,naustat     ; get Network Adapter Unit status
  2257.         mov     bx,offset xmt
  2258.         call    session
  2259.         pop     bx
  2260.         pop     word ptr xmt.scb_rname  ; restore remote name first two bytes
  2261. chknet2a:
  2262.         push    es                      ; save registers
  2263.         push    di
  2264.         push    si
  2265.         push    cx
  2266.         push    ds
  2267.         pop     es                      ; set es:di to datas segment
  2268.         mov     si,offset xmtbuf+60 ; where local name is returned (1st entry)
  2269.         cmp     word ptr xmtbuf+58,0    ; is local name empty?
  2270.         jne     chknet2b                ; ne = no, use name from table
  2271.         mov     si,offset deflname      ; else use default local name
  2272. chknet2b:
  2273.         mov     di,offset xmt.scb_lname ; where to put it in scb
  2274.         mov     cx,14                   ; 16 bytes minus extension of '.K'
  2275.         cld                             ; append extension of '.K' to loc name
  2276. chknet3:cmp     byte ptr[si],' ' ; find first space (end of regular node name)
  2277.         jbe     chknet4                 ; be = found one (or control code)
  2278.         movsb                           ; copy local name to scb
  2279.         loop    chknet3                 ; continue though local name
  2280. chknet4:cmp     word ptr [di-2],'K.'    ; is extension '.K' present already?
  2281.         je      chknet4a;;;5                    ; e = yes, nothing to add
  2282.         cmp     word ptr [di-2],'k.'    ; check lower case too
  2283.         je      chknet4a;;;5                    ; e = yes, nothing to add
  2284.         mov     word ptr [di],'K.'      ; append our extension of '.K'
  2285.         add     di,2                    ; step over our new extension
  2286.         sub     cx,2
  2287.                                         ; complete field with spaces
  2288.         add     cx,2                    ; 15th and 16th chars
  2289. chknet4a:jcxz   chknet5                 ; z = nothing to add
  2290.         mov     al,' '                  ; space as padding
  2291.         rep     stosb
  2292. chknet5:mov     si,offset xmt.scb_lname
  2293.         mov     di,offset rcv.scb_lname ; put in receiver scb too
  2294.         mov     cx,8
  2295.         rep     movsw
  2296.         mov     cx,8
  2297.         mov     si,offset xmt.scb_lname
  2298.         mov     di,offset lsn.scb_lname ; in Listen scb also
  2299.         rep     movsw
  2300.         pop     cx
  2301.         pop     si
  2302.         pop     di
  2303.         pop     es
  2304. chknet6:
  2305.         push    bx                      ; Put our new local name in NAU
  2306.         mov     xmt.scb_cmd,nadd        ; ADD NAME, wait
  2307.         mov     bx,offset xmt
  2308.         call    session
  2309.         pop     bx
  2310.         mov     al,xmt.scb_err          ; get error code
  2311.         cmp     al,0                    ; success?
  2312.         jne     chknet60                ; [zqf]
  2313.         jmp     chknet7                 ; e = yes
  2314. chknet60:
  2315.         cmp     al,0dh                  ; duplicate name in local table?
  2316.         je      chknet6a                ; e = yes
  2317.         cmp     al,16h                  ; name used elsewhere?
  2318.         je      chknet6a                ; e = yes
  2319.         cmp     al,19h                  ; name conflict?
  2320.         je      chknet6a                ; e = yes
  2321.         push    ax
  2322.         mov     ah,prstr                ; another kind of error
  2323. ;        mov     dx,offset chkmsg1       ; say can't construct local name
  2324.         mcmsg   chkmsg1,cchkmsg1
  2325.         int     dos
  2326.         pop     ax
  2327.         call    hexout                  ; display it (in al)
  2328.         mov     ah,prstr
  2329.         mov     dx,offset crlf
  2330.         int     dos
  2331.         mov     pcnet,0                 ; say no connection today
  2332.         stc                             ; set carry for failure
  2333.         ret
  2334. chknet6a:
  2335.         mov     ah,prstr                ; ask for another name
  2336. ;        mov     dx,offset chkmsg2       ; prompt message
  2337.         mcmsg   chkmsg2,cchkmsg2
  2338.         int     dos
  2339.         mov     ah,conout               ; show name itself
  2340.         push    cx
  2341.         mov     cx,16                   ; 16 bytes in name field
  2342.         mov     si,offset xmt.scb_lname
  2343. chknet6c:
  2344.         lodsb                           ; get name char into al
  2345.         mov     dl,al
  2346.         int     dos
  2347.         mov     byte ptr[si-1],' '      ; clear old name as we go
  2348.         loop    chknet6c
  2349.         pop     cx
  2350.         mov     ah,prstr
  2351. ;        mov     dx,offset chkmsg3       ; rest of prompt
  2352.         mcmsg   chkmsg3,cchkmsg3
  2353.         int     dos
  2354.  
  2355.         mov     ah,0ah                  ; read buffered line from stdin
  2356.         mov     dx,offset xmtbuf+58     ; where to put text (xmtbuf+60=text)
  2357.         mov     xmtbuf+58,15            ; buf capacity, including cr at end
  2358.         mov     xmtbuf+59,0             ; say text in buffer = none
  2359.         int     dos
  2360.         jc      chknet6b                ; c = error
  2361.         cmp     xmtbuf+59,0             ; any bytes read?
  2362.         je      chknet6b                ; e = no, exit failure
  2363.         mov     ah,prstr                ; say rechecking name
  2364. ;        mov     dx,offset netmsg1
  2365.         mcmsg   netmsg1,cnetmsg1
  2366.         int     dos
  2367.         jmp     chknet2a                ; go reinterpret name
  2368. chknet6b:
  2369.         stc                             ; set carry for failure
  2370.         ret
  2371.  
  2372. chknet7:mov     pcnet,1                 ; network is present (but not active)
  2373.         mov     al,xmt.scb_num          ; name number
  2374.         mov     rcv.scb_num,al
  2375.         mov     lsn.scb_num,al
  2376.         mov     lclexit,offset netclose ; address to close network
  2377.         push    ax
  2378.         push    cx
  2379.         push    dx
  2380. ;        mov     dx,offset netmsg2        ; say net going
  2381.         mcmsg   netmsg2,cnetmsg2
  2382.         mov     ah,prstr
  2383.         int     dos
  2384.         mov     si,offset rcv.scb_lname ; display our local name
  2385.         mov     ah,conout
  2386.         mov     cx,16
  2387.         cld
  2388. chknet9:lodsb                           ; byte from si to al
  2389.         mov     dl,al
  2390.         int     dos                     ; display it
  2391.         loop    chknet9
  2392.         mov     ah,prstr
  2393.         mov     dx,offset crlf          ; add cr/lf
  2394.         int     dos
  2395.         pop     dx
  2396.         pop     cx
  2397.         pop     ax
  2398.         clc                             ; carry clear for success
  2399.         ret
  2400. chknet  endp
  2401.  
  2402. ;                                       ; [ohl] ++++
  2403. ; Verifies existance of interrupt 6Bh support, verifies vendor specific
  2404. ; support for BREAK and other features, sets network type bit in nettype,
  2405. ; sets BREAK support in nsbrk and sets network status byte pcnet to 0
  2406. ; (no net) or to 1 (net ready). This is the first procedure called to
  2407. ; init Ungermann-Bass NETCI terminal port network usage.
  2408. chkub  proc    near
  2409.         push    bx
  2410.         push    es                      ; Test for vector
  2411.         mov     ah,35h                  ; DOS get interrupt vector
  2412.         mov     al,6bh                  ; 6bh = Net/One command interpreter
  2413.                                         ;  interface, with break support
  2414.         int     dos                     ; returns vector in es:bx
  2415.         mov     ax,es                   ; is vector in rom bios??? [jrd]
  2416.         cmp     ax,0f000h               ; rom bios starts here
  2417.         jb      chkub2                  ; b = not likely
  2418.         mov     ax,0                    ; yes, say no network
  2419.         mov     es,ax                   ; fake a null vector
  2420.         mov     bx,ax
  2421. chkub2: mov     ax,es
  2422.         or      bx,ax                   ; is vector present?
  2423.         jz      chkub0                  ; z = no
  2424.         mov     al,0ffh                 ; test value (anything non-zero)
  2425.         mov     ah,2                    ; function code for testing net board
  2426.         int     netci
  2427.         or      al,al                   ; al = 0 means board is ok
  2428.         jnz     chkub0                  ; nz = not ok
  2429.         pop     es
  2430.         pop     bx
  2431.         mov     nsbrk,1                 ; network BREAK supported
  2432.         or      nettype,netone          ; say have Net/One
  2433.         clc                             ; return success
  2434.         ret
  2435.  
  2436. chkub0: pop     es                      ; clean stack from above
  2437.         pop     bx
  2438.         push    ax
  2439.         push    dx
  2440.         mov     ah,prstr
  2441. ;        mov     dx,offset nonetmsg      ; say network is not available
  2442.         mcmsg   nonetmsg,cnonetmsg
  2443.         int     dos
  2444.         pop     dx
  2445.         pop     ax
  2446.         stc                             ; set carry for failure
  2447.         ret                             ; and exit now
  2448. chkub  endp                             ; [ohl] ----
  2449.  
  2450. hexout  proc    near                    ; display byte in al as hex value
  2451.         push    ax                      ; all regs preserved
  2452.         push    cx
  2453.         push    dx
  2454.         mov     cx,2                    ; two nibbles
  2455. hexout1:push    cx                      ; save counter
  2456.         mov     cl,4                    ; high nibble
  2457.         ror     al,cl                   ; put in low order field
  2458.         mov     dl,al
  2459.         xchg    ch,al                   ; save al byte in ch
  2460.         and     dl,0fh                  ; four bits
  2461.         cmp     dl,9                    ; too big?
  2462.         jbe     hexout2                 ; be = no
  2463.         add     dl,'A'-'9'-1            ; bump up to A-F
  2464. hexout2:add     dl,'0'
  2465.         mov     ah,conout
  2466.         int     dos
  2467.         xchg    ch,al                   ; recover data byte
  2468.         pop     cx
  2469.         loop    hexout1                 ; do second nibble
  2470.         mov     dl,'H'                  ; add a final hex ident
  2471.         int     dos
  2472.         pop     ax
  2473.         pop     cx
  2474.         pop     dx
  2475.         ret
  2476. hexout  endp
  2477.  
  2478. ; local routine to see if we have to transmit an xon
  2479. chkxon  proc    near
  2480.         cmp     flowon,0                ; doing flow control?
  2481.         je      chkxo1                  ; no, skip all this
  2482.         test    xofsnt,usron            ; did user send an xoff?
  2483.         jnz     chkxo1                  ; nz = yes, don't contradict it here
  2484.         test    xofsnt,bufon            ; have we sent a buffer level xoff?
  2485.         jz      chkxo1                  ; z = no, forget it
  2486.         cmp     count,mntrgl            ; below (low water mark) trigger?
  2487.         jae     chkxo1                  ; no, forget it
  2488.         mov     ah,flowon               ; ah gets xon
  2489.         and     xofsnt,off              ; remember we've sent the xon
  2490.         call    outch2              ; send via non-flow controlled entry point
  2491.          nop
  2492.          nop
  2493.          nop                            ; in case it skips
  2494. chkxo1: ret
  2495. chkxon  endp
  2496.  
  2497. ; IHOSTS - Initialize the host by sending XON, or equivalent, and enter the
  2498. ; cycle of clear input buffer, wait 1 second, test if buffer empty then exit
  2499. ; else repeat cycle. Requires that the port be initialized before hand.
  2500. ; Ihosts is used by the local send-file routine just after initializing
  2501. ; the serial port.
  2502. ; 22 March 1986 [jrd]
  2503. ; 22 June 1986 Don't send null char if not using flow control. [jrd]
  2504.  
  2505. IHOSTS  PROC    NEAR
  2506.         push    ax              ; save the registers
  2507.         push    cx
  2508.         push    dx
  2509.         mov     xofrcv,off      ; clear old xoff received flag
  2510.         mov     xofsnt,off      ; and old xoff sent flag
  2511.         mov     ah,flowon       ; put Go-ahead flow control char in ah
  2512.         or      ah,ah           ; check for null char
  2513.         jz      ihosts1         ; z = null, don't send it
  2514.         call    outchr          ; send it (release Host's output queue)
  2515.          nop                    ; outchr can do skip return
  2516.          nop
  2517.          nop
  2518. ihosts1:call    clrbuf          ; clear out interrupt buffer
  2519.         pop     dx              ; empty buffer. we are done here
  2520.         pop     cx
  2521.         pop     ax
  2522.         ret
  2523. IHOSTS  ENDP
  2524.  
  2525. ; IHOSTR - initialize the remote host for our reception of a file by
  2526. ; sending the flow-on character (XON typically) to release any held
  2527. ; data. Called by receive-file code just after initializing the serial
  2528. ; port. 22 March 1986 [jrd]
  2529. ; 22 June 1986 Don't send null char if not using flow control. [jrd]
  2530. IHOSTR  PROC    NEAR
  2531.         push    ax              ; save regs
  2532.         push    cx
  2533.         mov     xofrcv,off      ; clear old xoff received flag
  2534.         mov     xofsnt,off      ; and old xoff sent flag
  2535.         mov     ah,flowon       ; put Go-ahead flow control char in ah
  2536.         or      ah,ah           ; check for null char
  2537.         jz      ihostr1         ; z = null, don't send it
  2538.         call    outchr          ; send it (release Host's output queue)
  2539.          nop                    ; outchr can do skip return
  2540.          nop
  2541.          nop
  2542. ihostr1:pop     cx
  2543.         pop     ax
  2544.         ret
  2545. IHOSTR  ENDP
  2546.  
  2547. ; Send a break out the current serial port.  Returns normally.
  2548. ; Do both regular and long Break. 6 March 1987 [jrd]
  2549.  
  2550. SENDBR  PROC    NEAR
  2551.         push    cx              ; Regular Break entry point
  2552.         mov     cx,275          ; 275 milliseconds in regular Break
  2553.         call    sendbw          ; call worker routine to do it
  2554.         pop     cx
  2555.         clc                     ; don't exit Connect mode
  2556.         ret
  2557. SENDBL: push    cx              ; Long Break entry point
  2558.         mov     cx,1800         ; 1.8 second long break
  2559.         call    sendbw          ; call worker routine to do it
  2560.         pop     cx
  2561.         clc                     ; don't exit Connect mode
  2562.         ret
  2563.                                 ; worker - send Break for cx millisec
  2564. sendbw: test    clone,0ffh      ; running on a semi-clone?
  2565.         jnz     sendbw2         ; nz = yes, can't do this via Bios
  2566.         push    ax
  2567.         push    dx
  2568.         mov     dx,brkadr       ; Port address
  2569.         in      al,dx           ; Get current setting
  2570.         push    ax              ; save setting on the stack
  2571.         or      al,brkval       ; Set send-break bit(s)
  2572.         out     dx,al           ; Start the break
  2573.         mov     ax,cx           ; # of ms to wait
  2574.         call    pcwait          ; hold break for desired interval
  2575.         pop     ax              ; restore Line Control Register
  2576.         out     dx,al           ; Stop the break
  2577.         pop     dx
  2578.         pop     ax
  2579.         ret
  2580. sendbw2:
  2581.         cmp     clone, 'U'      ; is it an UB NETCI port?                [ohl]
  2582.         je      sendbw6         ; e = yes                                [ohl]
  2583.         cmp     clone,'N'       ; is this a NetBios network port?
  2584.         jne     sendbw4         ; ne = no
  2585.         cmp     nsbrk,0         ; is network able to send a break?
  2586.         je      sendbw4         ; e = no
  2587.         test    nettype,starlan ; STARLAN: network break supported?
  2588.         jz      sendbw4         ; z = no
  2589.         push    bx
  2590.         push    es              ; save es around call
  2591.         push    ds
  2592.         pop     es              ; make es:bx point to scb in datas segment
  2593.         mov     bx,offset can   ; use Cancel control block
  2594.         mov     can.scb_cmd,netbrk ; send net Break command
  2595.         int     5bh             ; use network Break interrupt
  2596.         pop     es              ; saved registers
  2597.         pop     bx
  2598. sendbw4:ret
  2599. sendbw6:                        ; UB port send break             [ohl] +++
  2600.         push    ax
  2601.         push    cx
  2602.         mov     ax, ncicont + 0 ; call control, use 0 for network port num [ohl]
  2603.         mov     cl, ncibrk      ; request break                          [ohl]
  2604.         int     netci           ; Net/One command interface int. (6Bh)   [ohl]
  2605.         pop     cx
  2606.         pop     ax
  2607.         ret                     ;  [ohl] ---
  2608. SENDBR  ENDP
  2609.  
  2610. ; Initialization for using serial port.  This routine performs
  2611. ; any initialization necessary for using the serial port, including
  2612. ; setting up interrupt routines, setting buffer pointers, etc.
  2613. ; Doing this twice in a row should be harmless (this version checks
  2614. ; a flag and returns if initialization has already been done).
  2615. ; SERRST below should restore any interrupt vectors that this changes.
  2616. ;
  2617. ; Revised slightly by Joe R. Doupnik 22 Dec 1985 to prevent interrupts
  2618. ; being enabled until we're done, to stop interrupts from occurring when
  2619. ; TX holding buffer becomes empty (a useless interrupt for us), and to
  2620. ; shorten the time between enabling interrupts and our exit.
  2621. ; Returns carry clear if success, else carry set.
  2622. SERINI  PROC    NEAR
  2623.         call    pcwtst                  ; recalibrate pcwait loop timer
  2624.         cmp     portin,0                ; Did we initialize port already?
  2625.         jle     serin0                  ; le = no, not yet
  2626.         jmp     serin4                  ; Yes, update flow and leave
  2627. serin0: cmp     portin,-1               ; have we run SET PORT or equiv?
  2628.         jne     serin5                  ; ne = yes, continue
  2629.         mov     bl,flags.comflg         ; pass current port ident
  2630.         call    comstrt                 ; do SET PORT now
  2631.          ret                            ; failed, exit now
  2632.          nop
  2633.          nop
  2634. serin5: cmp     clone,0                 ; non-clone
  2635.         je      serin2                  ; e = yes, real thing
  2636.         jmp     serin3                  ; else use Bios. Finish initialization
  2637.  
  2638. serin2: cmp     clone,'N'               ; Network port?
  2639.         jne     serin2a                 ; ne = no
  2640.         jmp     serin3                  ; yes
  2641. serin2a:push    bx
  2642.         push    es
  2643.         in      al,21H                  ; Interrupt controller
  2644.         mov     savirq,al               ; save state here for restoration
  2645.         or      al,modem.mddis          ; Inhibit IRQ 3 or IRQ 4
  2646.         out     21H,al
  2647.         mov     al,byte ptr modem.mdintv ; desired interrupt vector
  2648.         mov     ah,35H                  ; Int 21H, function 35H = Get Vector
  2649.         int     dos                     ; get vector into es:bx
  2650.         mov     word ptr savsci,bx    ; save address offset of original vector
  2651.         mov     word ptr savsci+2,es    ;  and its segment
  2652.         mov     al,byte ptr modem.mdintv ; interrupt number for IRQ 4 or IRQ 3
  2653.         mov     dx,offset serint        ; offset of our interrupt routine
  2654.         push    ds                      ; save ds around next DOS call
  2655.         mov     bx,cs                   ; compose full address of our routine
  2656.         mov     ds,bx                   ; segment is the code segment
  2657.         mov     ah,25H                  ; set interrupt address from ds:dx
  2658.         int     dos
  2659.         pop     ds
  2660.         mov     al,rs232                ; interrupt number for Bios serial port
  2661.         mov     ah,35H                  ; get vector into es:bx
  2662.         int     dos
  2663.         mov     word ptr sav232,bx      ; save offset
  2664.         mov     word ptr sav232+2,es    ; save segment
  2665.         mov     dx,offset serdum        ; offset of our interrupt routine
  2666.         push    ds                      ; save ds around next DOS call
  2667.         mov     bx,cs                   ; compose full address of our routine
  2668.         mov     ds,bx                   ; segment is the code segment
  2669.         mov     ah,25H                  ; set interrupt address from ds:dx
  2670.         int     dos
  2671.         pop     ds
  2672.         pop     es
  2673.         pop     bx
  2674.         mov     portin,1                ; Remember port has been initialized
  2675.         cli                             ; Disable interrupts
  2676.         cld                             ; Do increments in string operations
  2677.         mov     ax,modem.mdstat
  2678.         mov     mst,ax                  ; Use this address for status
  2679.         mov     ax,modem.mddat
  2680.         mov     mdat,ax                 ; Use this address for data.
  2681.         mov     al,modem.mdmeoi
  2682.         mov     mdeoi,al                ; Use to signify end-of-interrupt.
  2683.         in      al,21H                  ; Set up 8259 interrupt controller
  2684.         and     al,modem.mden   ; Enable INT3 or INT4. (bit=0 means enable)
  2685.         out     21H,al                  ; rewrite interrupt mask byte
  2686.         mov     dx,modem.mdcom  ; Set up the serial card Line Control Reg.
  2687.         in      al,dx                   ; get present settings
  2688.         mov     savlcr,al               ; save them for restoration
  2689.         mov     al,3                    ; 8 data bits. DLAB = 0
  2690.         out     dx,al
  2691.         mov     dx,modem.mddat     ; data and command port, read and flush any
  2692.         in      al,dx                   ; char in UART's receive buffer
  2693.         inc     dx                ; increment to interrupt enable register 3f9h
  2694.         mov     al,1                    ; Set up interrupt enable register
  2695.         out     dx,al                   ;  for Data Available only
  2696.         add     dx,3                ; increment to modem control register 3fch
  2697.         mov     al,0bh            ; assert DTR, RTS, not OUT1, and OUT2
  2698.         out     dx,al             ; OUT2 high turns on interrupt driver chip
  2699.         sti                       ; Allow interrupts (AFTER next instr)
  2700.         jmp     short serin4            ; finish up
  2701.  
  2702. serin3: cmp     flags.comflg,'N'        ; Network?
  2703.         jne     serin4                  ; ne = no
  2704.         call    setnet                  ; setup network session and pcnet flag
  2705.         jnc     serin4                  ; nc = success
  2706.         ret                             ; fail, carry set, leave portin at 0
  2707.  
  2708. serin4: push    bx
  2709.         mov     bx,portval              ; get port data structure
  2710.         mov     parmsk,0ffh             ; parity mask, assume parity is None
  2711.         cmp     [bx].parflg,parnon      ; is it None?
  2712.         je      serin1                  ; e = yes
  2713.         mov     parmsk,07fh             ; no, pass lower 7 bits as data
  2714. serin1: mov     bx,[bx].flowc           ; get flow control chars
  2715.         mov     flowoff,bl              ; xoff or null
  2716.         mov     flowon,bh               ; xon or null
  2717.         mov     xofrcv,off              ; clear xoff received flag
  2718.         pop     bx
  2719.         mov     portin,1                ; say initialized
  2720.         clc                             ; carry clear for success
  2721.         ret                             ; We're done
  2722. SERINI  ENDP
  2723.  
  2724. ; Reset the serial port.  This is the opposite of serini.  Calling
  2725. ; this twice without intervening calls to serini should be harmless.
  2726. ; Moved push/pop es code to do quicker exit before interrupts enabled. [jrd]
  2727. ; Returns normally.
  2728. ; 22 June 1986 Leave OUT1 low to avoid resetting Hayes 1200B's. [jrd]
  2729. ; 21 Feb 1987 Add support for Bios calls (Clone) [jrd]
  2730. ; 17 May 1987 Redo for COM3/4 support [jrd]
  2731. SERRST  PROC    NEAR
  2732.         cmp     portin,0                ; Reset already?
  2733.         jg      srst3                   ; g = no
  2734.         ret                             ; e = yes, l=not used yet, just leave
  2735. srst3:  test    clone,0ffh              ; running on a non-compatible UART?
  2736.         jz      srst4                   ; z = no, real UART
  2737.         jmp     srst1                   ; nz = yes (Bios or Net)
  2738. srst4:  push    word ptr savsci         ; save original interrupt owner
  2739.         push    word ptr savsci+2       ; offset and segment
  2740.         mov     word ptr savsci,offset nulint ; redirect to our null routine
  2741.         mov     ax,cs                   ; segment of null routine is code
  2742.         mov     word ptr savsci+2,ax
  2743.         mov     cx,0                    ; loop counter
  2744. srst2:  mov     dx,modem.mdstat         ; status register
  2745.         in      al,dx
  2746.         jmp     $+2                     ; chip access delay
  2747.         test    al,40h                  ; both xmtr output registers empty?
  2748.         loopz   srst2                   ; z = no, wait for them a while
  2749.         mov     dx,modem.mddat          ; modem base address 3f8h
  2750.         add     dx,1                    ; point at int enable reg 3f9h
  2751.         mov     al,0
  2752.         out     dx,al                   ; disable interrupts from this source
  2753.         jmp     $+2                     ; let stray interrupts occur now
  2754.         jmp     $+2
  2755.         add     dx,2                    ; point at Line Control Register 3fbh
  2756.         mov     al,savlcr               ; saved bit pattern
  2757.         and     al,not 80h              ; force DLAB bit to 0
  2758.         out     dx,al                   ; restore line control state
  2759.                 ; clear modem's delta status bits and reassert DTR etc
  2760.         inc     dx              ; increment to modem control register 3fch
  2761.         mov     al,03h          ; reassert DTR,RTS,but not OUT1 and not OUT2
  2762.         out     dx,al           ;  OUT2 low to turn off interrupt drivers
  2763.         jmp     $+2             ; pause, in case stray interrupt is generated
  2764.         jmp     $+2             ; which is more than likely, hence nulint.
  2765.         add     dx,2                    ; modem status register 3feh
  2766.         in      al,dx                   ; clear status register by reading it
  2767.         jmp     $+2
  2768.         mov     mdmhand,al              ; save here for Show Modem
  2769.         cli                             ; Disable interrupts
  2770.         in      al,21H                  ; Interrupt controller
  2771.         or      al,modem.mddis          ; Inhibit IRQ 3 or IRQ 4
  2772.         pop     word ptr savsci+2       ; recover original int owner's addr
  2773.         pop     word ptr savsci
  2774.         sti                             ; replace original IRQ intrpt vector
  2775.         push    bx
  2776.         mov     al,byte ptr modem.mdintv ; vector number to do
  2777.         mov     dx,word ptr savsci      ; offset part
  2778.         push    ds
  2779.         mov     bx,word ptr savsci+2    ; segment part
  2780.         mov     ds,bx                   ; ds:dx has interrupt vector
  2781.         mov     ah,25H                  ; set interrupt vector
  2782.         int     dos                     ; replaced
  2783.         pop     ds
  2784.         mov     al,rs232        ; Bios serial port interrupt vector to restore
  2785.         mov     dx,word ptr sav232      ; offset part
  2786.         push    ds
  2787.         mov     bx,word ptr sav232+2    ; segment part
  2788.         mov     ds,bx
  2789.         mov     ah,25h                  ; set interrupt vector
  2790.         int     dos
  2791.         pop     ds
  2792.         pop     bx
  2793.         cli
  2794.         mov     ah,savirq               ; saved Interrupt state
  2795.         and     ah,modem.mddis          ; pick out our IRQ bit
  2796.         in      al,21h                  ; get current intrpt controller state
  2797.         jmp     $+2
  2798.         xor     al,modem.mddis          ; remove our IRQ bit
  2799.         or      al,ah                   ; set previous state
  2800.         out     21h,al                  ; reset IRQ 3 or 4 to original state
  2801.         sti
  2802.                                         ; non-UART processes
  2803. srst1:  cmp     pcnet,0                 ; a network active?
  2804.         je      srst9                   ; e = no
  2805.         cmp     flags.comflg,'N'        ; NetBios network?
  2806.         jne     srst9                   ; ne = no
  2807.         cmp     rposted,0               ; receive outstanding?
  2808.         je      srst9                   ; e = no
  2809.         mov     can.scb_baddr,offset rcv ; cancel receives
  2810.         push    bx
  2811.         mov     bx,offset can
  2812.         call    session
  2813.         pop     bx
  2814.         mov     ax,1
  2815.         call    pcwait                  ; wait one millisec
  2816.         cmp     rcv.scb_err,0           ; success?
  2817.         jne     srst9                   ; ne = no, leave interlock set
  2818.         mov     rposted,0               ; say no receives posted
  2819. srst9:  mov     portin,0                ; Reset flag
  2820.         ret                             ; All done
  2821. SERRST  ENDP
  2822.  
  2823. ; Null interrupt routine, to handle strays
  2824. nulint  proc    near
  2825.         push ax
  2826.         push dx
  2827.         mov al,20h                      ; general EOI
  2828.         mov dx,intcon1                  ; to 8259 interrupt controller
  2829.         out dx,al                       ; clear controller chip
  2830.         pop dx
  2831.         pop ax
  2832.         iret
  2833. nulint  endp
  2834.  
  2835. ; Dummy Interrupt 14H to defeat DOS interference with serial port when CTTY
  2836. ; and Kermit use the port simultaneously. If ports differ then chain DOS to
  2837. ; original Int 14H Bios code. Else return dummy status=ok reports and
  2838. ; Backspace for Read, ignore char for Write.
  2839. ; Entered with AH = function request, AL = char to be sent, DX = com port num
  2840. ; CS is our code segment, DS is DOS's, SS is ours or DOS's, interrupts off.
  2841. ; 25 June 1987 [jrd]
  2842. SERDUM  PROC    FAR
  2843.         push    ds                      ; preserve all registers
  2844.         push    ax
  2845.         mov     ax,seg datas            ; get our data segment
  2846.         mov     ds,ax
  2847.         mov     al,flags.comflg         ; get port id (COM1 = 1, COM2 = 2)
  2848.         and     al,7                    ; use lower three bits
  2849.         dec     al                      ; DOS counts COM1 as 0, etc
  2850.         cmp     dl,al           ; referencing same port as Kermit is using?
  2851.         pop     ax                      ; recover request parameters
  2852.         jne     serdu1                  ; ne = no, chain to Bios routine
  2853.         pop     ds
  2854.         cmp     ah,0                    ; initialization request?
  2855.         je      serdu3                  ; e = yes, return dummy status=ok rpt
  2856.         cmp     ah,1                    ; send char in al?
  2857.         jne     serdu2                  ; ne = no
  2858.         mov     ah,60h                  ; yes, set line status=ok in ah
  2859.         iret
  2860. serdu2: cmp     ah,2                    ; receive char (and wait for it)?
  2861.         jne     serdu3                  ; ne = no, return dummy report
  2862.         mov     al,bs                   ; yes, return ascii BS to DOS
  2863.         mov     ah,0                    ; ah = errors (none here)
  2864.         iret
  2865. serdu3: mov     ax,60b0h                ; dummy status report:xmtr empty, CD,
  2866.         iret                            ;  DSR, and CTS are on
  2867.  
  2868. serdu1: pop     tempdum                 ; save old ds
  2869.         push    word ptr sav232+2       ; push Bios int 14H handler segment
  2870.         push    word ptr sav232         ; push Bios int 14H handler offset
  2871.         push    tempdum                 ; recover old ds
  2872.         pop     ds
  2873.         ret                             ; do a ret far (chain to Bios)
  2874. SERDUM  ENDP
  2875.  
  2876. ; Serial port interrupt routine.  This is not accessible outside this
  2877. ; module, handles serial port receiver interrupts.
  2878. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's.
  2879. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  2880. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  2881. ; done modulo size of Source. All pointer management is handled here.
  2882. ; Control-G char substituted for char(s) lost in overrun condition.
  2883. ; Upgraded to read cause of interrupt from interrupt ident reg (accepts only
  2884. ;  data ready), chain to old interrupt if source is not our device.
  2885. ; 9 Feb 1988 Add storage of interrupt cause in intkind. [jrd]
  2886.  
  2887. SERINT  PROC  FAR
  2888.         push    ax                      ; save registers
  2889.         push    dx                      ;
  2890.         push    ds
  2891.         mov     ax,seg datas
  2892.         mov     ds,ax                   ; address data segment
  2893.         mov     dx,mdat                 ; modem base address
  2894.         add     dx,2            ; increment to Interrupt Identification Reg
  2895.         in      al,dx                   ; get interrupt cause
  2896.         mov     intkind,al              ; save cause here
  2897.         test    al,1            ; interrupt available if this bit is zero
  2898.         jz      srintc                  ; z = interrupt is from our source
  2899.         pop     tempsci                 ;  save old ds
  2900.         pop     dx              ;  clean the stack and prepare for ret far
  2901.         pop     ax              ;  to old int handler (same as a jump there)
  2902.         push    word ptr savsci+2       ; old handler segment
  2903.         push    word ptr savsci         ; old handler offset
  2904.         push    tempsci                 ; recover old ds
  2905.         pop     ds
  2906.         ret                             ; do far return (chain to old handler)
  2907. srintc: mov     al,mdeoi                ; allow interrupt controller to run
  2908.         out     intcon1,al              ; Send End-of-Interrupt to 8259
  2909.         test    intkind,4               ; data ready?
  2910.         jnz     srint0a                 ; nz = yes, else ignore
  2911. srint0: sti                             ; else turn on interrupts
  2912.         jmp     retint                  ;  and exit now (common jump point)
  2913.  
  2914. srint0a:mov     dx,mst                  ; Asynch status port
  2915.         in      al,dx
  2916.         and     al,mdmover              ; select overrun bit
  2917.         mov     ah,al                   ; save it for later
  2918.         mov     dx,mdat
  2919.         in      al,dx                   ; read the received character into al
  2920.         mov     dh,al              ; dh = working copy. Check null, flow cntl
  2921.         and     dh,parmsk               ; strip parity temporarily, if any
  2922. ;;;;;   jz      srint0                  ; if null ignore char
  2923. srint0b:cmp     flowoff,0               ; flow control active?
  2924.         je      srint2                  ; e = no
  2925.         cmp     dh,flowoff              ; acting on Xoff?
  2926.         jne     srint1                  ; ne = Nope, go on
  2927.         cmp     xofsnt,0                ; have we sent an outstanding XOFF?
  2928.         jne     srint0                  ; ne = yes, ignore (possible echo)
  2929.         mov     xofrcv,bufon            ; Set the flag saying XOFF received
  2930.         jmp     srint0                  ;  and exit
  2931. srint1: cmp     dh,flowon               ; acting on Xon?
  2932.         jne     srint2                  ; ne = no, go on
  2933.         mov     xofrcv,off              ; Clear the XOFF received flag
  2934.         jmp     srint0                  ;  and exit
  2935. srint2: push    bx                      ; save register
  2936.         or      ah,ah                   ; overrun?
  2937.         jz      srint2a                 ; z = no
  2938.         mov     ah,al                   ; yes, save present char
  2939.         mov     al,bell                 ; insert control-G for missing char
  2940. srint2a:mov     bx,srcpnt               ; address of buffer storage slot
  2941.         mov     byte ptr [bx],al       ; store the new char in buffer "source"
  2942.         inc     srcpnt                  ; point to next slot
  2943.         inc     bx
  2944.         cmp     bx,offset source + bufsiz ; beyond end of buffer?
  2945.         jb      srint3                  ; b = not past end
  2946.         mov     srcpnt,offset source    ; wrap buffer around
  2947. srint3: cmp     count,bufsiz            ; filled already?
  2948.         jae     srint4                  ; ae = yes
  2949.         inc     count                   ; no, add a char
  2950. srint4: or      ah,ah                   ; anything in overrun storage?
  2951.         jz      srint4a                 ; z = no
  2952.         mov     al,ah                   ; recover any recent char from overrun
  2953.         xor     ah,ah                   ; clear overrun storage
  2954.         jmp     srint2a                 ; yes, go store real second char
  2955. srint4a:pop     bx                      ; restore reg
  2956.         sti                          ; ok to allow interrupts now, not before
  2957.         cmp     count,mntrgh            ; past the high trigger point?
  2958.         jbe     retint                  ; be = no, we're within our limit
  2959.         test    xofsnt,bufon        ; Has an XOFF been sent by buffer control?
  2960.         jnz     retint                  ; nz = Yes
  2961.         mov     al,flowoff              ; get the flow off char (Xoff or null)
  2962.         or      al,al                   ; don't send nul chars
  2963.         jz      retint                  ; z = null, nothing to send
  2964.         call    dopar                   ; Set parity appropriately
  2965.         mov     ah,al                  ; Don't overwrite character with status
  2966.         push    cx                      ; save reg
  2967.         xor     cx,cx                   ; loop counter
  2968. srint5: mov     dx,modem.mdstat         ; Get port status
  2969.         in      al,dx
  2970.         test    al,20H                  ; Transmitter ready?
  2971.         jnz     srint6                  ; nz = yes
  2972.         jmp     $+2                     ; use time, prevent overdriving UART
  2973.         loop    srint5                  ; else wait loop, cx times
  2974.          jmp    srint7                  ; Timeout
  2975. srint6: mov     al,ah                   ; Now send out the flow control char
  2976.         mov     dx,modem.mddat
  2977.         jmp     $+2
  2978.         out     dx,al
  2979.         mov     xofsnt,bufon       ; Remember we sent an XOFF at buffer level
  2980. srint7: pop     cx                      ; restore reg
  2981. retint: pop     ds
  2982.         pop     dx
  2983.         pop     ax
  2984.         iret
  2985. SERINT  ENDP
  2986.  
  2987. DTRLOW  PROC    NEAR            ; Global proc to Hangup the Phone or Network
  2988.                                 ; by making DTR and RTS low (phone). [jrd]
  2989.         mov     ah,cmtxt        ; allow text, to be able to display help
  2990.         mov     bx,offset rdbuf         ; dummy buffer
  2991. ;        mov     dx,offset hnghlp        ; help message
  2992.         mcmsg   hnghlp,chnghlp
  2993.         call    comnd                   ; get a confirm
  2994.          jmp    r
  2995.          nop
  2996.         cmp     clone,'0'               ; running on a semi-clone?
  2997.         jb      dtrlow2                 ; b = no
  2998.         cmp     clone,'4'
  2999.         jb      dtrlow1                 ; b = yes, can't access modem lines
  3000. dtrlow2:call    serhng                  ; drop DTR and RTS
  3001.         cmp     taklev,0                ; in a Take file or macro?
  3002.         jne     dtrlow1                 ; ne = yes, no message
  3003.         mov     ah,prstr                ; give a nice message
  3004. ;        mov     dx,offset hngmsg
  3005.         mcmsg   hngmsg,chngmsg
  3006.         int     dos
  3007. dtrlow1:jmp     rskp
  3008. DTRLOW  ENDP
  3009.  
  3010. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  3011. ; to terminate the connection. 29 March 1986 [jrd]
  3012. ; 5 April 1987 Add 500 millisec wait with lines low before returning. [jrd]
  3013. ; Calling this twice without intervening calls to serini should be harmless.
  3014. ; If network then call nethangup procedure to hangup the session without
  3015. ; losing local name information.
  3016. ; Returns normally.
  3017.  
  3018. serhng  proc    near    ; clear modem's delta status bits and lower DTR & RTS
  3019.         cmp     clone,'U'               ; Ungermann Bass network?
  3020.         je      shng2                   ; e = yes
  3021.         cmp     clone,'N'               ; network?
  3022.         jne     shng1                   ; ne = no
  3023. shng2:  cmp     pcnet,0                 ; network operational?
  3024.         je      shng1                   ; e = no
  3025.         call    nethangup               ; break the session
  3026.         call    serrst                  ; reset port so can be opened again
  3027.         ret
  3028. shng1:  call    serrst                  ; reset port so serini can set DTR
  3029.         cli                             ; Disable interrupts
  3030.         push    ax
  3031.         push    dx
  3032.         mov     dx,modem.mddat          ; serial port base address
  3033.         add     dx,4                    ; increment to control register
  3034.         mov     al,08h                 ; reassert OUT2, un-assert DTR,RTS,OUT1
  3035.         out     dx,al
  3036.         jmp     $+2
  3037.         add     dx,2                    ; increment to modem status register
  3038.         in      al,dx                   ; Clear Status reg by reading it
  3039. shngx:  sti                             ; Enable interrupts
  3040.         mov     ax,500                  ; 500 millisec, for pcwait
  3041.         call    pcwait              ; keep lines low for at least 500 millisec
  3042.         pop     dx
  3043.         pop     ax
  3044.         clc
  3045.         ret
  3046. serhng  endp
  3047.  
  3048. ; Jumping to this location is like retskp.  It assumes the instruction
  3049. ;   after the call is a jmp addr.
  3050.  
  3051. RSKP    PROC    NEAR
  3052.         pop     bp
  3053.         add     bp,3
  3054.         push    bp
  3055.         ret
  3056. RSKP    ENDP
  3057.  
  3058. ; Jumping here is the same as a ret
  3059.  
  3060. R       PROC    NEAR
  3061.         ret
  3062. R       ENDP
  3063.  
  3064. code    ends
  3065.         end
  3066.