home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msr313src.zip / msxibm.asm < prev    next >
Assembly Source File  |  1993-07-12  |  232KB  |  7,126 lines

  1. ; File MSXIBM.ASM
  2. ; Kermit system dependent module for IBM-PC
  3.     include mssdef.h
  4. ;  Copyright (C) 1985, 1993, Trustees of Columbia University in the 
  5. ;  City of New York.  Permission is granted to any individual or institution
  6. ;  to use this software as long as it is not sold for profit.  This copyright
  7. ;  notice must be retained.  This software may not be included in commercial
  8. ;  products without written permission of Columbia University.
  9. ;
  10. ; Edit History
  11. ; 27 August 1992 version 3.13
  12. ; 6 Sept 1991 version 3.11
  13. ; Last edit 3 June 1993
  14. ; Add Beame and Whiteside TCP/IP support, adapted from James Sturdevant.
  15. ; Add LAT support for Interconnections Inc TES v3 over LAT transport.
  16. ;  Nettype is lat, letter ident is 'I', teslat is none zero.
  17. ; August 1992 Split each comms path into separate structures
  18. ; Feb 1992 Add multiple internal TCP/IP Telnet sessions
  19. ; 2 Feb 1991 Add support for user specified IRQs 2..15.
  20. ; 29 August Add direct Interconnections Inc TES support.
  21. ; 12 August Add Novell TELAPI network interface.
  22. ; 11 March 1990 Add 75/1200 baud split speed from Dan Norstedt.
  23. ; 30 Sept 1989 Incorporate Opennet networking material from Fred Richter.
  24. ; 30 Sept 1989 Fred Richter (FGR) Intel Corp, Hauppauge NY
  25. ;  polyof!inthap!fred or fred@polyof.poly.edu
  26. ;  Added support for Intel Opennet Networking Virtual Terminal Services
  27. ;  added "set port opennet xxx", also modified (slightly)
  28. ;  the Netbios code (rpost) to always have the next Netbios receive posted
  29. ;  as a small efficiency gain. Added error checking for received Netbios
  30. ;  packets (there was none for async receives), also fix problem when the
  31. ;  receives are canceled, where the data was being accepted anyway.
  32. ; 3 Sept 1989 Add DECnet CTERM and LAT support, plus Novell Int 6Bh.
  33. ; 9 July 1989 Add automatic usage of National Semiconductor 16550A UART in
  34. ;  receiver fifo mode. Thanks to Dan Norstedt, danne@kicki.stacken.kth.se,
  35. ;  and Campbell Scientific, Logan Utah for urging and supporting information.
  36. ; 17 June 1989 Add transparent interrupt driven support for IBM's Extended
  37. ;  Bios via SET PORT BIOSn.
  38. ; 8 June 1989 Add Wyse-700 support from (Mikko Laanti (mjl).
  39. ; 6 March 1989 Add SET TERMINAL REPLAY FILESPEC command.
  40. ; 21 Jan 1989 Avoid initializing a port until the port is accessed for regular
  41. ;  use, baud rate setting, or modem status. portin=-1 means unaccessed.
  42. ; 2 Dec 1988 Preserve UART parity etc bits in Line Control Reg.
  43. ; 30 Nov 1988 Add SET TERM CLEAR screen clear command (uses byte VTCLEAR).
  44. ; 26 Nov 1988 Add SET TERM TAB SET/CLEAR AT start-col:spacing notation.
  45. ; 21 Nov 1988 Version 2.32
  46. ; 25 Oct 1988 Add Ungermann Bass network board status check in proc chkub,
  47. ;  thanks to Fritz Buetikofer and Rene Rehmann in Switzerland.
  48. ; 9 Oct 1988 Add byte vtemu.vtchset to hold choices for VT102 emulator
  49. ;  character sets (US, UK, or Alternate-ROM). Tnx to Baruch Cochavy. The value
  50. ;  of vtemu.vtchset must match definitions in emulator file mszibm.asm.
  51. ; 5 Oct 1988 Add SET TERMINAL DIRECTION command and status display line.
  52. ; 21 August 1988 Move tests for NUL and DEL received chars to prtchr routine
  53. ;  for uniform application of tests.
  54. ; 28 July 1988 Add more UB details from Henrik Levkowetz. Double check serial
  55. ;  port address for 02f8h with COM1, for PCjr, and shift to COM2 addresses.
  56. ; 16 July 1988 Use null interrupt routine, nulint, when resetting serial port
  57. ;  because setting OUT2 low generates stray ints on some UARTs. [jrd]
  58. ; 1 July 1988 Version 2.31
  59. ; 12 June 1988 Add small changes to handle network session failures, and
  60. ;  add carry set if serini fails to init port.
  61. ; 29 May 1988 Add Ungermann Bass NetOne NETCI support from Henrik Levkowetz
  62. ;  [ohl]. Revise same to test for actual network presence and to avoid
  63. ;  interference with NetBios operations. Use "SET PORT UB-Net1"
  64. ; 23 May 1988 Hangup now resets serial port so can be re-inited with DTR high
  65. ; 21 May 1988 Tweak serrst to allow stray interrupts while resetting UART,
  66. ;  clear outstanding network requests when changing ports.
  67. ; 6 May 1988 Introduce xmtbufx for explict network double buffering of
  68. ;   xmitted data.
  69. ; 28 April 1988 fix set port bios register problem.
  70. ; 18 April 1988 Network: do another READ when char count < low water mark.
  71. ;  If BIOSn is selected skip test of Bios 40:0h for port presence.
  72. ; 3 April 1988 Ignore NUL and DEL at serial port unless DEBUG or TRANSLATE
  73. ;  INPUT are active, but pass DEL if Tek mode is active. Replace netdone
  74. ;  with new lclexit global word to shut net when Kermit exits.
  75. ; 22 March 1988 Add global byte Tekgraf which forces graphics board type
  76. ;   0=auto-sensing, 1=cga, 2=ega, 3=VGA, 5=Hercules, 5=ATT. Tekgraf stored
  77. ;   and set in this file by Set Term Graphics <board type>. [jrd]
  78. ; 6 March 1988 Ignore received XOFF's if we have already sent one. [jrd]
  79. ; 27 Feb 1988 Add global routine getmodem to return modem status in al. [jrd]
  80. ; 9 Feb 1988 Automaticallly find Interrupt ReQuest level for a port.
  81. ;   No Modem Status for network. [jrd]
  82. ; 25 Jan 1988 Revise outchr waiting on XON to use 4 millisec increments. [jrd]
  83. ; 1 Jan 1988 version 2.30
  84. ; 24 Dec 1987 Revise selection of COM1 to use COM1 name but COM2 addresses
  85. ;  if base address of 02f8 (COM2) is found in 40:00h and display notice.
  86. ;  Restore state of IRQ interrupt line when finished with serial port. [jrd]
  87. ; 31 Oct 1987 Add terminal type Tek4010, with Tek submode Tekflg. [jrd]
  88. ; 24 Oct 1987 Enhance clrbuf to empty any intermediate (net) buffers. [jrd]
  89. ; 19 Oct 1987 Fix stray tab-set at column 32. [jrd]
  90. ; 2 Oct 1987 Add PCjr baud rate table, from Ted Medin. [jrd]
  91. ; 6 Sept 1987 Allow serial port serint to send xoff when buffer fills even
  92. ;  though user may have sent xoff by hand. [jrd]
  93. ; 27 Aug 1987 Skip timeout test in OUTCHR if receive timeout is zero. [jrd]
  94. ; 23 August 1987 Add vtemu.vtflgop to hold runtime terminal settings so that
  95. ;  a reset command restores them to the Setup values, vtemu.vtflgst. Show
  96. ;  displays the vtemu.vtflgop operational values. [jrd]
  97. ; 17 August 1987 Make timing adjustments for Token Passing and single buffered
  98. ;  network adapter boards. Byte netdbfr indicates presence of double buffering;
  99. ;  it is set in chknet as a vendor option. To test your boards force dbl buf
  100. ;  then look for missing 256 byte parts of long packets sent out; missing parts
  101. ;  mean new material overwrote not-yet-sent old == single buffering. [jrd]
  102. ; 8 August 1987 Add interrupt chaining in serint. [jrd]
  103. ; 23 July 1987 Clear xofsnt and xofrcv xon/xoff flags in ihost(s/r). [jrd]
  104. ; 9 July 1987 Cure confusion about COM1/2 for IBM PCjr (address of regular
  105. ;  COM2 in 40:0h slot for COM1) with info from John Neufeld. [jrd]
  106. ; 2 July 1987 Route NetBios cancels through separate scb for systems, such
  107. ;  as Novell NetWare, which object to having active scbs touched. [jrd]
  108. ; 25 June 1987 Add trapping of Int 14H (Bios RS232 procedure) to allow
  109. ;  CTTY command to function without too much inteference from DOS. [jrd]
  110. ; 17 June 1987 Enlarge tab setting to full 132 columns at all times. [jrd]
  111. ; 11 June 1987 Add Set Term Roll on/off to control auto roll back of screen
  112. ;  when new characters are displayed; default is off (no unwinding). [jrd]
  113. ; 20 May 1987 Remove rejection of NULL and DEL chars, let callers do it. [jrd]
  114. ; 16 May 1987 Add distinction between user typed and receiver threshold
  115. ;  controlled sending of XOFF. User level overrides buffer control.[jrd]
  116. ;  Add COM3 and COM4 support: examine memory 40:00h->40:07h for selected
  117. ;  port COM1..4, resp. If word is null then set flags.comflg to 0 to say
  118. ;  undefined port. Otherwise, use that word in seg 40h as base of UART i/o
  119. ;  ports. Assume IRQ4 for COM1 and COM3 (same except for port addresses)
  120. ;  and IRQ4 for  COM2 and COM4 (again, same except for port addresses).
  121. ;  Serial port info sturcture (not values) assumed identical for all ports.
  122. ; 25 April 1987 Add Netbios compatible local area network support. [jrd]
  123. ;  Set Port command expanded to syntax SET PORT NET nodename. Use nodename
  124. ;  if acting as a client to named remote node, leave blank if running in
  125. ;  Server mode. Byte 'ttyact' is controlled by msster.asm to indicate Connect
  126. ;  mode is being used. Byte 'netdone' (stored in mssker.asm) holds offset of
  127. ;  network hangup procedure 'netclose' to be done when leaving Kermit. Hangup
  128. ;  command extended to to network hangup as well. Network uses IBM Netbios
  129. ;  standard calls (Int 5Ch) and allows for extensions of AT&T STARLAN for
  130. ;  longer node names via Int 2Bh (the later is tested before use). Virtual
  131. ;  circuits are employed. The Redirector is not necessary. Kermit can operate
  132. ;  as either a terminal (does a CALL at Connect mode startup), a file receiver
  133. ;  (does a CALL at startup), or a Kermit server (does an anonomous LISTEN at
  134. ;  startup, hence no nodename). Clients should Set Timer Off.
  135. ; Note -
  136. ; When the Bios is used for serial port i/o the modem signals DSR and CTS
  137. ; must be asserted low before the Bios will access the hardware. Jumpers
  138. ; from pin 20 (DTR) to pin 6 (DSR) and from pin 4 (RTS) to pin 5 (CTS)
  139. ; will probably be necessary.
  140. ;       From Glenn Everhart (who suggested using the Bios alternative)
  141. ;
  142.     public    serini, serrst, clrbuf, outchr, coms
  143.     public    dodel, ctlu, cmblnk, locate, prtchr, baudst, clearl
  144.     public    getbaud, beep, shomodem, getmodem, mdmhand
  145.     public    count, xofsnt, puthlp, putmod, clrmod, poscur, holdscr
  146.     public    sendbr, sendbl, machnam, setktab, setkhlp, lclini, showkey
  147.     public    ihosts, ihostr, dtrlow, serhng, comptab, pcwait
  148.     public    portval, bdtab, ubhold, dupflg, setnbios, peekcom
  149.     public    sescur, seslist, sesdisp, tcpstart, savexoff, savexlen
  150.     public    parmsk, flowon, flowoff, flowcnt
  151.  
  152. off    equ    0
  153. bufon    equ    1        ; buffer level xon/xoff on-state control flag
  154. usron    equ    2        ; user level xon/xoff on-state control flag
  155.  
  156. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full
  157. mntrgl    equ    bufsiz/4    ; Low point = 1/4 buffer full
  158. nbuflen    equ    512        ; bytes in each network buffer (two of them)
  159.                 ;  DEC-LAT requires 259 (256 + 3 extra)
  160.  
  161. BRKBIT    EQU    040H        ; Send-break bit. 
  162. TIMERCMD EQU    43h        ; 8253/4 Timer chip command port
  163. TIMER2DATA EQU    42h        ; 8253/4 Timer 2 data port
  164. PPI_PORT EQU    61h        ; 8255 prog peripheral chip control port
  165. VIDEO    EQU    10H        ; Bios Video display software interrupt
  166. RS232    EQU    14H        ; Bios RS232 serial port s/ware interrupt
  167.  
  168. ; constants used by serial port handler
  169. MDMINP    EQU    1        ; Input ready bit
  170. MDMOVER    EQU    2        ; Receiver overrun
  171.                 ; 1200/75 baud split speed constants
  172. cnt75b    equ    47721/3        ; One bit of 75 baud at 1.193 Mhz clock
  173. precomp    equ    cnt75b/8    ; Precomp 12%, allows 3ms latency w 12% jitter
  174.  
  175. _TEXT    segment
  176.     extrn    ktcpopen:far, ktcpclose:far, ktcpswap:far, ktcpcom:far
  177. _TEXT    ends
  178.  
  179. data     segment
  180.     extrn    flags:byte, trans:byte, ttyact:byte, comand:byte
  181.     extrn    lclsusp:word, lclrest:word, lclexit:word, rxtable:byte
  182.     extrn    rdbuf:byte, taklev:byte, tekflg:byte, scbattr:byte
  183.     extrn    low_rgt:word, diskio:byte, crt_cols:byte, tekflg:byte
  184.     extrn    dosnum:word, portirq:byte, dosctty:byte, decbuf:byte
  185.     extrn    tcpdata:word, tcphost:byte, tv_mode:byte, repflg:byte
  186.     extrn    takadr:word, taklev:byte, vtinited:byte, kbdflg:byte
  187.     extrn    yflags:byte, ftogmod:dword, apctrap:byte, protlist:byte
  188.     extrn    vtcpage:word
  189.  
  190. ; Modem information
  191. mdminfo    struc
  192. mddat    dw    03f8h        ; data register, base address (03f8h)
  193. mdiir    dw    03fah        ; interrupt identification register (03fah)
  194. mdstat    dw    03fdh        ; line status register (03fdh)
  195. mdcom    dw    03bfh        ; line control register (03fbh)
  196. mden    db    not (1 shl 4)    ; mask to enable interrupt
  197. mddis    db    (1 shl 4)    ; mask to disable interrupt
  198. mdmeoi    db    60h+4        ; specific EOI
  199. mdintv    dw    8+4        ; saved interrupt vector (0ch is IRQ 4)
  200. mdmintc    dw    20h        ; interrupt controller control (20h or 0a0h)
  201. mdminfo    ends
  202. modem    mdminfo <>
  203.  
  204. setktab    db    0        ; superceded by msuibm code, return 0 here
  205. setkhlp    db    '$'        ; and add empty help string
  206. holdscr    db    0        ; Hold-Screen, non-zero to stop reading
  207. savsci    dd    0        ; old serial port interrupt vector
  208. sav232    dd    0        ; Original Bios Int 14H address, in Code seg
  209. savirq    db    0        ; Original Interrupt mask for IRQ
  210. savier    db    0        ; original UART Int enable bits (03f9)
  211. savstat db    0        ; orginal UART control reg  (03fch)
  212. savlcr    db    0        ; Original Line Control Reg (3fbh) contents
  213. dupflg    db    0        ; full (0) or half (1) duplex on port
  214. quechar    db    0        ; queued char for outchr (XOFF typically)
  215. intkind    db    0        ; cause of serial port interrupt
  216. isps2    db    0        ; non-zero if real IBM PS/2
  217. erms40    db    cr,lf,'?Warning: Unrecognized Speed',cr,lf,'$'
  218. badbd    db    cr,lf,'Unimplemented speed$'
  219. badprt    db    cr,lf,'?Warning: unknown address for port. Assuming \x0$'
  220. biosmsg    db    cr,lf,'?Warning: unknown hardware for port.'
  221.     db    ' Using the Bios as BIOS$'
  222. badirq    db    cr,lf,'?Warning: unable to verify IRQ. Assuming $'
  223. msmsg1    db    cr,lf,'  Modem is not ready: DSR is off$'
  224. msmsg2    db    cr,lf,'  Modem is ready:     DSR is on$'
  225. msmsg3    db    cr,lf,'  no Carrier Detect:  CD  is off$'
  226. msmsg4    db    cr,lf,'  Carrier Detect:     CD  is on$'
  227. msmsg5    db    cr,lf,'  no Clear To Send:   CTS is off$'
  228. msmsg6    db    cr,lf,'  Clear To Send:      CTS is on$'
  229. msmsg7    db    cr,lf,'  Modem is not used by the Network$'
  230. msmsg8    db    cr,lf,'  COM1 address:       Port \x$'
  231. msmsg9    db    ', IRQ $'
  232. msmsg10    db    ', 16550A UART FIFO$'
  233. hngmsg    db    cr,lf,' The phone or network connection should have hung up'
  234.     db    cr,lf,'$'
  235. hnghlp    db    cr,lf,' The modem control lines DTR and RTS for the current'
  236.     db    ' port are forced low (off)'
  237.     db    cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  238.     db    ' high (on) when it exits.',cr,lf
  239.     db    ' For networks, the active session is terminated.',cr,lf,'$'
  240.  
  241. machnam    db    'IBM-PC$'
  242. crlf    db    cr,lf,'$'
  243. delstr  db    BS,BS,'  ',BS,BS,'$'     ; Delete string
  244. clrlin  db    BS,BS,'  ',cr,'$'    ; Clear line (just the cr part)
  245. portin    db    -1        ; Has comm port been initialized, -1=not used
  246. xofsnt    db    0        ; Say if we sent an XOFF
  247. xofrcv    db    0        ; Say if we received an XOFF
  248. pcwcnt    dw    800        ; number of loops for 1 millisec in pcwait
  249. fifo    db    0        ; non-zero if 16550A UART (FIFO mode)
  250. temp    dw    0
  251. temp2    dw    0
  252. tempsci dw    0        ; temp storage for serint
  253. tempdum    dw    0        ; temp storage for serdum
  254. timeract db    0        ; timer in use by a routine, flag
  255. clomsg    db    ' A network session may be active; exit anyway [Yes/No]? ',0
  256. clotab    db    2        ; close net on exit table
  257.     mkeyw    'yes',0
  258.     mkeyw    'no',1
  259.  
  260. comptab    db    24            ; communications port options
  261.     mkeyw    'Bios1','0'+1        ; '0' is to flag value as forced Bios
  262.     mkeyw    'Bios2','0'+2
  263.     mkeyw    'Bios3','0'+3
  264.     mkeyw    'Bios4','0'+4
  265.     mkeyw    'COM1',1        ; these go straight to the hardware
  266.     mkeyw    'COM2',2
  267.     mkeyw    'COM3',3
  268.     mkeyw    'COM4',4
  269.     mkeyw    '1',1            ; straight to the hardware
  270.     mkeyw    '2',2
  271.     mkeyw    '3',3
  272.     mkeyw    '4',4
  273.     mkeyw    '3Com(BAPI)','C'    ; 3Com BAPI interface
  274.     mkeyw    'BWTCP','b'        ; [JRS] Beame & Whiteside TCP
  275.     mkeyw    'DECnet','D'        ; DECnet-DOS LAT and CTERM
  276.     mkeyw    'EBIOS','E'        ; IBM/YALE EBIOS Int 14h interceptor
  277.     mkeyw    'NetBios','N'        ; Netbios
  278.     mkeyw    'Novell(NASI)','W'    ; Novell NetWare NASI/NACS
  279.     mkeyw    'OpenNET','O'        ; Intel OpenNET support (FGR)
  280.     mkeyw    'TCP/IP','t'        ; Telnet, internal
  281.     mkeyw    'TELAPI','T'        ; Novell TELAPI
  282.     mkeyw    'TES','I'        ; TES, Interconnections Inc
  283.     mkeyw    'UB-Net1','U'        ; Ungermann Bass Net One
  284.     mkeyw    '   ',0            ; port is not present, for Status
  285.  
  286. ; port structure:
  287. ; baud rate index, local echo, parity flag, if flow control active (both ways),
  288. ; if need handshake after pkts, default handshake char, flow control char pair
  289. ; half/full duplex, port ready, send, receive, close procedures
  290.     ; UART hardware
  291. port1    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,uartsnd,uartrcv,serrst>
  292. port2    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,uartsnd,uartrcv,serrst>
  293. port3     prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,uartsnd,uartrcv,serrst>
  294. port4    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,uartsnd,uartrcv,serrst>
  295.     ; IBM PC Bios and EBIOS
  296. portb1    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,biossnd,biosrcv>
  297. portb2    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,biossnd,biosrcv>
  298. portb3     prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,biossnd,biosrcv>
  299. portb4    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,biossnd,biosrcv>
  300.  
  301. portval    dw    port1            ; Default is to use port 1
  302.  
  303. bdtab    db    21            ; Baud rate table
  304.     mkeyw    '45.5',0
  305.     mkeyw    '50',1
  306.     mkeyw    '75',2
  307.     mkeyw    '110',3
  308.     mkeyw    '134.5',4
  309.     mkeyw    '150',5
  310.     mkeyw    '300',6
  311.     mkeyw    '600',7
  312.     mkeyw    '1200',8
  313.     mkeyw    '1800',9
  314.     mkeyw    '2000',10
  315.     mkeyw    '2400',11
  316.     mkeyw    '4800',12
  317.     mkeyw    '9600',13
  318.     mkeyw    '14400',14
  319.     mkeyw    '19200',15
  320.     mkeyw    '28800',16
  321.     mkeyw    '38400',17
  322.     mkeyw    '57600',18
  323.     mkeyw    '115200',19
  324.     mkeyw    '75/1200',20    ; split speed, use this index for Bsplit
  325.  
  326. Bsplit    equ    20        ; 75/1200 baud, split-speed  [pslms]
  327.  
  328. ; this table is indexed by the baud rate definitions given in bdtab.
  329. ; Unsupported baud rates should contain 0FFh.
  330.  
  331. bddat    label    word
  332.     dw    9E4H        ; 45.5 baud
  333.     dw    900H        ; 50 baud
  334.     dw    600H        ; 75 baud
  335.     dw    417H        ; 110 baud
  336.     dw    359H        ; 134.5 baud
  337.     dw    300H        ; 150 baud
  338.     dw    180H        ; 300 baud
  339.     dw    0C0H        ; 600 baud
  340.     dw    60H        ; 1200 baud
  341.     dw    40H        ; 1800 baud
  342.     dw    3AH        ; 2000 baud
  343.     dw    30H        ; 2400 baud
  344.     dw    18H        ; 4800 baud
  345.     dw    0CH        ; 9600 baud
  346.     dw    08h        ; 14400 baud
  347.     dw    06H        ; 19200 baud
  348.     dw    04h        ; 28800 baud
  349.     dw    03H        ; 38400 baud
  350.     dw    02h        ; 57600 baud
  351.     dw    01h        ; 115200 baud
  352.     dw    5fh        ; Split 75/1200, 1200+1.1 percent error
  353. baudlen    equ    ($-bddat)/2    ; number of entries above
  354.  
  355. ; this table is indexed by the baud rate definitions given in
  356. ; pcdefs.  Unsupported baud rates should contain FF.
  357. ; Bits are for Bios speed, no parity, 8 data bits.
  358. clbddat   label   word
  359.         dw      0FFH            ; 45.5 baud  -- Not supported
  360.         dw      0FFH            ; 50 baud
  361.         dw      0FFH            ; 75 baud
  362.         dw      03H        ; 110 baud
  363.         dw      0FFH            ; 134.5 baud
  364.         dw      23H        ; 150 baud
  365.         dw      43H        ; 300 baud
  366.         dw      63H        ; 600 baud
  367.         dw      83H        ; 1200 baud
  368.         dw      0ffH        ; 1800 baud
  369.         dw      0FFH        ; 2000 baud
  370.         dw      0a3H        ; 2400 baud
  371.         dw      0c3H        ; 4800 baud
  372.         dw      0e3H        ; 9600 baud
  373.         dw      0FFH        ; 14400 baud
  374.         dw      0FFH        ; 19200 baud
  375.         dw      0FFH        ; 28800 baud
  376.         dw      0FFH        ; 38400 baud
  377.     dw    0FFH        ; 57600 baud
  378.     dw    0FFH        ; 115200 baud
  379.     dw    0FFh        ; Split 75/1200
  380.  
  381. defcom    dw    03f8h,02f8h,03e8h,02e8h     ; default COMn port addresses
  382.  
  383. ;;;;;;;;;;;;;; start of per session save area
  384.     even
  385. savexoff label    word
  386. source    db    bufsiz+2 DUP(?)    ; Buffer for data from port (+ 2 guard bytes)
  387. srcpnt    dw    source        ; Pointer in buffer
  388. count    dw    0        ; Number of chars in int buffer
  389. lastread db    0        ; last read char, for NVT
  390. parmsk    db    0ffh        ; parity mask, 0ffh for no parity, 07fh with
  391. flowoff    db    0        ; flow-off char, Xoff or null (if no flow)
  392. flowon    db    0        ; flow-on char, Xon or null
  393. flowcnt    db    0        ; holds flowc (!= 0 using any flow control)
  394. xmtcnt    dw    0        ; occupancy in current output buffer
  395. xmtbufx    db    nbuflen+3 dup (0) ; external version of xmtbuf (dbl buffers)
  396. ; TCP/IP Telnet internal
  397. port_tn    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,ubsend,ubrecv,tcpclose>
  398.  
  399. savexlen dw    ($-savexoff)
  400. ;;;;;;;;;;;;;;; end of per session save
  401.  
  402. xmtbuf    db    nbuflen dup (0) ; network buffer for transmitter
  403. rcvbuf    db    nbuflen+3 dup (0) ; network buffer for receiver
  404.  
  405. ; variables for serial interrupt handler
  406. mst    dw    0        ; Modem status address
  407. mdat    dw    0        ; Modem data address
  408. miir    dw    0        ; modem interrupt ident register
  409. mdeoi    db    0        ; End-of-Interrupt value
  410. mdmhand    db    0        ; Modem status register, current
  411. mdintc    dw    0        ; interrupt control address
  412.  
  413. ; Information structures for IBM Netbios compatible Local Area Networks
  414.                 ; network constants
  415. netint    equ    5ch        ; Netbios interrupt
  416. nadd    equ    30h        ; Add name
  417. ncall    equ    10h        ; CALL, open a virtual circuit session
  418. ncancel    equ    35h        ; Cancel command in scb buffer
  419. ndelete    equ    31h        ; Delete Name
  420. nhangup    equ    12h        ; Hangup virtual circuit session
  421. nlisten    equ    11h        ; Listen for session caller
  422. naustat    equ    33h        ; Network Adapter Unit, get status of
  423. nreceive equ    15h        ; Receive on virtual circuit
  424. nreset    equ    32h        ; Reset NAU and tables
  425. nsend    equ    14h        ; Send on virtual circuit
  426. nsestat    equ    34h        ; Session, get status of
  427. netbrk    equ    70h        ; STARLAN Int 5bh send Break
  428. nowait    equ    80h        ; no-wait, command modifier
  429. npending equ    0ffh        ; Pending request
  430. exnbios    equ    0400h        ; Int 2ah exec netbios call, error retry
  431.  
  432.                 ; nettype word bits
  433. netbios    equ    0001h        ; NetBios
  434. netone    equ    0002h        ; Ungermann-Bass Net/One
  435. decnet    equ    0004h        ; DECnet CTERM
  436. declat    equ    0008h        ; DECnet LAT
  437. bapi    equ    0010h        ; 3Com BAPI
  438. ebios    equ    0020h        ; EBIOS, IBM and YALE
  439. telapi    equ    0040h        ; TELAPI, Novell
  440. tes    equ    0080h        ; TES, Interconnections Inc and Novell
  441. tcpnet    equ    0100h        ; TCP/IP (internal)
  442. acsi    equ    0200h        ; EBIOS, ACSI direct to NetBios pathway
  443. bwtcp    equ    0400h        ; [JRS] Beame & Whiteside TCP
  444.  
  445. nettype    dw    0        ; kind of local area net (vendor bit field)
  446.  
  447. ;xncall    equ    74h        ; [ohl] Net/One extended call function
  448. netci    equ    6Bh        ; [ohl] Net/One command interface interrupt,
  449.                 ; [ohl]  used for the following functions:
  450. nciwrit equ    0000h        ; [ohl] Net/One write function
  451. nciread equ    0100h        ; [ohl] Net/One read function
  452. ncistat equ    0700h        ; [ohl] Net/One status function
  453. ncicont equ    0600h        ; [ohl] Net/One control function
  454. ncibrk    equ    02h        ; [ohl] Net/One code for a break
  455. ncidis    equ    04h        ; [ohl] Net/One code for disconnect
  456. ncihld    equ    06h        ; [ohl] code for placing a connection on hold
  457. bapiint    equ    14h        ; 3Com BAPI, interrupt (Bios replacment)
  458. bapicon    equ    0a0h        ; 3Com BAPI, connect to port
  459. bapidisc equ    0a1h        ; 3Com BAPI, disconnect
  460. bapiwrit equ    0a4h        ; 3Com BAPI, write block
  461. bapiread equ    0a5h        ; 3Com BAPI, read block
  462. bapibrk    equ    0a6h        ; 3Com BAPI, send short break
  463. bapistat equ    0a7h        ; 3Com BAPI, read status (# chars to be read)
  464. bapihere equ    0afh        ; 3Com BAPI, presence check
  465. bapieecm equ    0b0h        ; 3Com BAPI, enable/disable ECM char
  466. bapiecm    equ    0b1h        ; 3Com BAPI, trap Enter Command Mode char
  467. bapiping equ    0b2h        ; KERMIT BAPI extension, Telnet, Ping host
  468.                 ;
  469. telport    equ    23        ; TELAPI Telnet port
  470. telopen    equ    0e0h        ; xtelopen a connection
  471. telclose equ    0e1h        ; xtelclose a connection
  472. telread    equ    0e2h        ; xtelread char(s)
  473. telwrite equ    0e3h        ; xtelwrite chars
  474. telioctl equ    0e4h        ; xtelioctl, ioctl the port
  475. telreset equ    0e5h        ; xtelreset, reset the whole TELAPI package
  476. telunload equ    0e6h        ; xtelunload, unload TELAPI TSR
  477. tellist    equ    0e7h        ; xtellist, list current sessions and status
  478. telattach equ    0e8h        ; xtelattach, session to COM port # 0..3
  479. telportosn equ    0e9h        ; xtelportosn, return session id for port
  480. telunreac equ    -51        ; network is unreachable
  481. telinuse equ    -56        ; socket already in use
  482. teltmo    equ    -60        ; timeout on connection attempt
  483. telrefuse equ    -61        ; connection refused
  484. teldwnhost equ    -64        ; host is down
  485. telunkhost equ    -67        ; unknown host
  486. telfull    equ    -301        ; all sessions are in use
  487.                 ; TELAPI messages and misc data
  488. telhlp    db    'Internet address nnn.nnn.nnn.nnn$'
  489. telmsg1    db    cr,lf,'?Badly constructed Internet address: $'
  490. telmsg2    db    cr,lf,'?No connection. Status = -$'
  491. telmsg51 db    cr,lf,'?Network is unreachable$'
  492. telmsg56 db    cr,lf,'?Socket already in use$'
  493. telmsg60 db    cr,lf,'?Timeout on connection attempt$'
  494. telmsg61 db    cr,lf,'?Connection refused$'
  495. telmsg64 db    cr,lf,'?Host is down$'
  496. telmsg67 db    cr,lf,'?Unknown host$'
  497. telmsg301 db    cr,lf,'?All sessions are in use$'
  498. telhostid db    2 dup (0)    ; TELAPI Telnet internal host session ident
  499.  
  500. IAC    equ    255        ; B&W TCP/IP Telnet Options codes
  501. DONT    equ    254
  502. DO    equ    253
  503. WONT    equ    252
  504. WILL    equ    251
  505. SB    equ    250
  506. SE    equ    240
  507. TELOPT_ECHO    equ 1
  508. TELOPT_SGA    equ 3
  509. TELOPT_STATUS    equ 5
  510. TELOPT_TTYPE    equ 24
  511. TELOPT_NAWS    equ 31
  512. NTELOPTS    equ 24
  513. sgaflg    db    0        ; B&W TCP/IP, supress go ahead flag
  514. option1 db    0        ; B&W TCP/IP, Telnet Options byte1
  515. option2    db    0        ; B&W TCP/IP, Telnet Options byte1
  516. optstate db    0        ; B&W TCP/IP, Telnet Options state variable
  517. bwtcpnam    db    'TCP-IP10',0    ; [JRS] name of Beame & Whiteside TCP driver
  518. bwhandle    dw    0        ; [JRS] handle for Beame & Whiteside TCP driver
  519.                 ;
  520. testalk    equ    4        ; TES invoke interactive cmd interpreter
  521. tesbwrite equ    6        ; TES block write
  522. tesbread equ    7        ; TES block read
  523. tesinstal equ    0a0h        ; TES installation/status report
  524. teslist    equ    0a1h        ; TES get list of sessions, with status    
  525. tesgets    equ    0a2h        ; TES get list of server names
  526. tesnews    equ    0a3h        ; TES start a new session
  527. tesholds equ    0a4h        ; TES hold currently active connection
  528. tesresume equ    0a5h        ; TES resume a session (1..9)
  529. tesdrop    equ    0a6h        ; TES drop a session
  530. tesnexts equ    0a7h        ; TES skip to next active session
  531. tesexec    equ    0a8h        ; TES send string to cmd interpreter
  532. tesport    dw    0        ; TES low byte = intercepted port
  533. tesquiet db    'ACTION NONE',0 ; TES Stop command prompting
  534. tesses    db    0        ; TES session number (1..9 is legal)
  535. tesname    db    50 dup (0)    ; TES host name asciiz
  536. teshelp    db    cr,lf,'?Host name or "*" to see available hosts'
  537.     db    ' or press ENTER to resume a connection$'
  538. tesnlist db    cr,lf,'  Active TES hosts:$'
  539. tesnhost db    cr,lf,'?No existing connection.'
  540.     db    ' Please select a host with  SET PORT TES host$'
  541. teslat    db    0        ; non-zero if using TES over LAT
  542. ;; pcnet values:    0    no network available at all
  543. ;;            1    network board reports itself as present
  544. ;;            2    and session is in progress
  545. ;; extrn byte pcnet is  defined in msster.
  546.  
  547. ; NetBios (StarGROUP and Opennet)
  548. port_nb    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,send,receive,nbclose>
  549. ; Ungermann Bass, 3ComBAPI, TELAPI
  550. port_ub    prtinfo    <-1,0,defpar,3,0,defhand,floxon,0,0,ubsend,ubrecv,ubclose>
  551. ; DECnet LAT and CTERM and TES-LAT
  552. port_dec prtinfo <-1,0,defpar,3,0,defhand,floxon,0,0,decsnd,decrcv,decclose>
  553. ; TES
  554. port_tes prtinfo <-1,0,defpar,3,0,defhand,floxon,0,0,tessnd,tesrcv,tesclose>
  555.  
  556. scbst struc            ; Session (Network) Control Block [PCnet comp]
  557.     scb_cmd        db 0    ; command code for Netbios Int 5ch
  558.     scb_err        db 0    ; error return or request is pending
  559.     scb_vcid    db 0    ; virtual circuit ident number
  560.     scb_num        db 0    ; local name-number
  561.     scb_baddr    dw 0    ; buffer address, offset
  562.             dw data ;  and segment
  563.     scb_length    dw 0    ; length of buffer data
  564.     scb_rname    db '*               ' ; remote name, 16 chars space
  565.     scb_lname    db '                ' ; local name      filled 
  566.             db 0    ; Receive timeout (0.5 sec units), want 0
  567.             db 0    ; Send timeout (0.5 sec units), want 0
  568.     scb_post    dw 0    ; interrupt driven post address, offset
  569.             dw code ;  and segment
  570.             db 0    ; LAN_num (adapter #), set to zero for STARLAN
  571.     scb_done    db 0    ; command complete status
  572.                 ; the 14 bytes below are normally 'reserved'
  573.                 ; STARLAN uses 5 for long/special call names
  574.                 ;  together with STARLAN specific Int 5bh
  575.     scb_vrname    dw 0,0    ; Variable length call name ptr offset,segment
  576.     scb_vrlen    db 0    ; length of vrname
  577.             db 9 dup (0)    ; reserved
  578. scbst    ends            ; 64 bytes overall
  579. rcv    scbst    <,,,,rcvbuf,,length rcvbuf,,,,,rpost>; declare scb for rcvr
  580. xmt    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,spost>;  for xmtr
  581. lsn    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,lpost>;  for server listen
  582. can    scbst    <>                     ;  for cancels
  583.                     ; DECnet material
  584. decint    equ    69h            ; CTERM interrupt
  585. dpresent equ    100h            ; CTERM Installation check
  586. dsend    equ    101h            ; CTERM send byte
  587. dread    equ    102h            ; CTERM read byte
  588. dcstat    equ    103h            ; CTERM status
  589. ddstat    equ    104h            ; CTERM Decnet status
  590. dopen    equ    105h            ; CTERM open session
  591. dclose    equ    106h            ; CTERM close session
  592. dgetscb    equ    10ah            ; CTERM get SCB size
  593.  
  594. latint    equ    6ah            ; LAT interrupt
  595. latsend equ    1            ; LAT send byte
  596. latread    equ    2            ; LAT read byte
  597. latstat    equ    3            ; LAT status
  598. latsendb equ    4            ; LAT send block (v4)
  599. latreadb equ    5            ; LAT read block (v4)
  600. latinfo    equ    6            ; LAT get miscellaneous information
  601. latsrv    equ    0d500h            ; LAT get next service name
  602. latopen    equ    0d0ffh            ; LAT open
  603. latclose equ    0d000h            ; LAT close
  604. latbreak equ    0d100h            ; LAT send a BREAK
  605. latscbget equ    0d800h            ; LAT get SCB interior to LAT
  606. latscbfree equ    0d801h            ; LAT free SCB interior to LAT
  607. latcpyems equ    0d900h            ; LAT copy to/from SCB in EMS or not
  608.  
  609. decneth    dw    0            ; CTERM session handle
  610. decseg    dw    0            ; segment of CTERM SCB memory block
  611. lathand    dw    0            ; LAT session handle, high byte = 0ffh
  612. latseg    dw    0            ; LAT SCB seg in our memory
  613. latversion db    4            ; LAT major version number
  614. latscbptr dd    0,0,0            ; LAT, pointer to SCB
  615.  
  616. lcbst    struc                ; LAT control block structure V4
  617.     service    db    17 dup (0)    ; 0 service     (number is offset)
  618.         db    10 dup (0)    ; 17 node, for future use
  619.     lat_pwd    dd    0        ; 27 password buffer ptr
  620.     pwd_len    db    0        ; 31 length of the buffer
  621.         db    22 dup (0)    ; 32 reserved
  622.     stopped    dd    0        ; 54 session stopped post routine addr
  623.     overflow dd    0        ; 58 service table overflow post addr
  624.     xnotify    dd    0        ; 62 transmit post routine addr
  625.     rnotify    dd    0        ; 66 receive post routine addr
  626.     sstatus    dw    0        ; 70 session status
  627.         db    270 dup (0)    ; 72 reserved
  628.     slotqty    db    2        ; 342 number receive data slots
  629.     slotused db    0        ; 343 number occupied slots
  630.     slotnr    db    0        ; 344 index of next rcv slot to use
  631.     slotcur    db    0        ; 345 index of current rcv slot
  632.     slotptr dw    0        ; 346 ptr to first received char
  633.     slottbl    dw    0        ; 348 ptrs to bufs for slot 1
  634.         dw    0        ; 350 and for slot 2
  635.     slotbf1 db    259 dup (0)    ; 352 first receive buffer
  636.     slotbf2 db    259 dup (0)    ; 611 second receive buffer
  637. lcbst    ends                ; total of 870 bytes
  638.  
  639. latservice db    17 dup (0)        ; LAT host name
  640. latpwd    db    16 dup (0),0        ; LAT password, terminator
  641. decmsg1    db    cr,lf,'Cannot create DECnet session.$'
  642. decmsg3    db    ' DECnet Error $'
  643. decmsg4    db    cr,lf,' CTERM ready$'
  644. decmsg5    db    cr,lf,' LAT ready$'
  645.                 ; end of DECnet and TES-LAT
  646.  
  647. pcnet    db    0        ; Network is functioning
  648. nambuf    db    65 dup (0)    ; network long name storage (STARLAN)
  649. newnambuf db    0        ; non-zero if new entry into namebuf above
  650. internet db    4 dup (0)    ; TELAPI Internet address, binary
  651. telses    dw    0        ; TELAPI session number
  652. sposted    db    0        ; send interlock, 0 if no send posted
  653. rposted    db    0        ; rcv interlock, 0 if no receive posted
  654. lposted    db    0        ; listen outstanding (if non-zero)
  655. netdbfr    db    0        ; non-zero if net board is double buffered
  656. lnamestat db    0        ; status of local name 0 = default,
  657.                 ;  1 = specified by user, 2 = locked in
  658. deflname db    'mskermit.K      ' ; default local name, 16 bytes
  659. ivt1str    db    'iVT1',0    ; FGR - OpenNet VT handshake string
  660. inettyp    db    0        ; FGR - network type 'N' or 'O'
  661. nsbrk    dw    0        ; net can send Break
  662. starlan    db    0        ; non-zero if StarLAN net
  663. chkmsg1    db    cr,lf,'?Cannot construct a local Kermit name, error = $'
  664. setnbad db    cr,lf,'?Local Kermit NetBIOS name is already fixed.$'
  665. chkmsg2    db    cr,lf,lf,' Name $'
  666. chkmsg3    db    ' is already in use. Please enter another of',cr,lf
  667. setnbhlp db    ' 1 - 14 letters or numbers (or nothing to quit): $'
  668. netmsg1    db    cr,lf,' Checking if our node name is unique ...$'
  669. netmsg2    db    cr,lf,' The network is active, our name is $'
  670. netmsg3 db    cr,lf,'  NetBios local name: $'
  671. netmsg4    db    '  Remote host: $'
  672. netmsg5 db    cr,lf,'  DECnet host: $'
  673. netmsg6 db    cr,lf,'  TELAPI Internet host: $'
  674. netmsg7    db    cr,lf,'  TES host name: $'
  675. netmsg8    db    cr,lf,'  EBIOS server port name: $'
  676. nonetmsg db    cr,lf,'?The network is not available$'
  677. noname    db    cr,lf,'?No name exists for the remote host.$'
  678. nethlp    db    cr,lf,'  node name of remote system,'
  679.     db    cr,lf,'  or press ENTER to use current name,'
  680.     db    cr,lf,'  or press ENTER for server mode (NetBios only).$'
  681. dnethlp    db    cr,lf,'  node name of remote system,'
  682.     db    cr,lf,'  or press ENTER to use current name,'
  683.     db    cr,lf,'  or  *  to see a list of LAT service names.$'
  684. nethlp2    db    cr,lf,' Optional LAT password, if using a LAT connection$'
  685. dnetsrv    db    cr,lf,' Available LAT service names:',cr,lf,'$'
  686. ngodset    db    cr,lf,' Connecting to network node: $'
  687. nbadset    db    bell,cr,lf,'?Cannot reach network node: $'
  688. recmsg    db    cr,lf,'?Network receive failed, status = $'
  689. sndmsg    db    cr,lf,'?Network send failed, status = $'
  690. naskpmt    db    cr,lf,' A network session is active.',cr,lf
  691.     db    ' Enter RESUME to resume it or NEW to start a new session:',0
  692. nettab    db    2
  693.     mkeyw    'New',0
  694.     mkeyw    'Resume',1
  695.  
  696. acnop    equ    80h            ; ACSI nop
  697.         ; second byte: null (ignored)
  698. acenable equ    81h            ; ACSI raise modem leads
  699.         ; second byte: DTR=01h, RTS=02h
  700. acdisable equ    82h            ; ACSI drop all modem leads
  701.         ; second byte: null (ignored)
  702. acbreak    equ    83h            ; ACSI send a BREAK
  703.         ; second byte: null (ignored)
  704. acsetmode equ    84h            ; ACSI set port Mode (speed etc)
  705. ; second byte: speed=3bits, parity=2bits, stopbits=1bit, databits=2bits
  706. acmodem    equ    85h            ; ACSI return modem leads state
  707.         ; second byte: DCD=80h, RI=40h, DSR=20h, CTS=10h
  708. acreqmodem equ    86h            ; ACSI request modem leads state
  709.         ; second byte: DCD=80h, RI=40h, DSR=20h, CTS=10h
  710. acdelay    equ    87h            ; ACSI pause transmission
  711.         ; second byte: delay in hundreths of second
  712. acpace    equ    88h            ; ACSI set flow control or pacing
  713.     ; second byte: direction send=10h, recv=20h; if pacing send=1, recv=2
  714. acsetxon equ    89h            ; ACSI set XON pacing character
  715.         ; second byte: char to represent resume transmission
  716. acsetxoff equ    8ah            ; ACSI set XOFF pacing character
  717.         ; second byte: char to represent cease transmission
  718. ; ACSI general read character status:    BREAK detected=10h, framing error=08h,
  719. ;                    parity error=04h, overrun=02h
  720.  
  721. ebbufset equ    0ffh            ; EBIOS set buf mode (1=send, 2=rcv)
  722. ebbufcnt equ    0fdh            ; EBIOS get buf count (1=send, 2=rcv)
  723. ebpace    equ    0feh            ; EBIOS set pacing mode (80h=send)
  724. ebrcv    equ    0fch            ; EBIOS receive, no wait
  725. ebsend    equ    1            ; EBIOS send a char
  726. ebmodem    equ    0fbh            ; EBIOS set modem leads
  727. ebbreak    equ    0fah            ; EBIOS send a BREAK
  728. ebcontrol equ    0f9h            ; EBIOS regain control
  729. ebredir equ    0f6h            ; EBIOS do port redirection
  730. ebquery    equ    0f5h            ; EBIOS get redirection info
  731. ebpresent equ    0f4h            ; EBIOS presence check
  732.  
  733. ebport    dw    0            ; EBIOS equivalent serial port 0..3
  734. ebcoms    db    0,0            ; adapter (port), path (80h=network)
  735.     db    16 dup (0)        ; Call name (host)
  736.     db    16 dup (0)        ; Listen name (null)
  737.     db    16 dup (0)        ; local name (null = use lan adapter)
  738.     db    0            ; unique name (1 = group name)
  739. ebhlp    db    'Name of server port$'    
  740. ebmsg2    db    cr,lf,'?No server port name is known,'
  741.     db    ' reenter the command with a name.$'
  742. ebmsg3    db    cr,lf,'?Unable to contact that port. Error code=$'
  743. ebiostab db    4            ; EBIOS table of local port names
  744.     mkeyw    '1',1
  745.     mkeyw    '2',2
  746.     mkeyw    '3',3
  747.     mkeyw    '4',4
  748.  
  749. tcpadrst db    cr,lf,'  tcp/ip address: $'    ; TCP/IP status msgs
  750. tcpsubst db    cr,lf,'  tcp/ip subnetmask: $'
  751. tcpdomst db    cr,lf,'  tcp/ip domain: $'
  752. tcpgatest db    cr,lf,'  tcp/ip gateway: $'
  753. tcppnsst db    cr,lf,'  tcp/ip primary-nameserver: $'
  754. tcpsnsst db    cr,lf,'  tcp/ip secondary-nameserver: $'
  755. tcpbcstst db    cr,lf,'  tcp/ip broadcast: $'
  756. tcphostst db    cr,lf,'  tcp/ip host: $'
  757. tcpportst db    cr,lf,'  tcp/ip port: $'
  758. tcpdebst db    cr,lf,'  tcp/ip debug-Options: $'
  759. tcppdintst db    ',  Packet-Driver-interrupt: \x$'
  760. tcppdnul db    ' (search for it)$'
  761. tcpodi    db    '   using ODI interface$'
  762. tcpttyst db    cr,lf,'  tcp/ip telnet-term-type: $'
  763. tcpttynul db    '(report real terminal type)',0    ; ASCIIZ
  764. tcpnlst    db    cr,lf,'  tcp/ip newline-mode: $' 
  765. tcpnlmsg0 db    'off (CR->CR NUL)$'
  766. tcpnlmsg1 db    'on (CR->CR LF)$'
  767. tcpdeboff db    'off$'
  768. tcpdebon db    'on$'
  769.  
  770. tcphlp    db    cr,lf,' Host Internet name  machine.domain  or'
  771.     db    ' Internet address  nnn.nnn.nnn.nnn'
  772.     db    cr,lf,'  or  *  to become a Telnet server.'
  773.     db    cr,lf,' Optional TCP port number may follow the host name.$'
  774. tcpporthlp db    cr,lf,' TCP port on host, 23 is Telnet.$'
  775. tcpbtpst db    '        from Bootp host: $'
  776. badport    db    cr,lf,'?Ports 25 is forbidden, sorry. Using 23 for Telnet.$'
  777. maxsessions    equ    6        ; max sessions, also in msntnd.c
  778. seslist    db    maxsessions dup (-1) ; list of Telnet session idents, -1=dead
  779. seshostlen equ    61            ; length of host name, asciiz
  780. sesname    db    maxsessions*seshostlen dup (0)    ; host names, asciiz.
  781. sescur    dw    -1            ; Current session (0..5)
  782. sesheader db    cr,lf,'         status    session    hostname$'
  783. sesinact  db    cr,lf,'         inactive     $'
  784. sesactive db    cr,lf,'         active       $'
  785. curmsg      db    cr,lf,'         current >    $'
  786. sesnone      db    cr,lf,' Error, all sessions are in use$'
  787. sesnohost db    cr,lf,' Oops, no host name is available$'
  788. seshelp    db    cr,lf,lf,' choices  R           return to active session'
  789.     db    cr,lf,'          1..6        pick a new or existing session'
  790.     db    cr,lf,'          N           start a new session (default)'
  791.     db    cr,lf
  792.     db    cr,lf,'Choice> $'
  793. data    ends
  794.  
  795. code1    segment
  796.     assume    cs:code1
  797.     extern    atsclr:near, setpos:near, setatch:near, termswapout:far
  798.     extern    termswapin:far, termswapdel:far
  799.  
  800. fatsclr    proc    far
  801.     call    atsclr
  802.     ret
  803. fatsclr    endp
  804. fsetatch proc    far
  805.     call    setatch
  806.     ret
  807. fsetatch endp
  808. fsetpos    proc    far
  809.     call    setpos
  810.     ret
  811. fsetpos    endp
  812. code1    ends
  813.  
  814. code    segment
  815.     extrn    comnd:near, prompt:near, dopar:near, lclyini:near
  816.     extrn    strcpy:near, strlen:near,decout:near, prtasz:near, prtscr:near
  817.     extrn    kbsusp:near, kbrest:near        ; in msuibm.asm
  818.     extrn    strcat:near, valout:near, crun:near, katoi:near, tolowr:near
  819.     extrn    trnmod:near
  820.  
  821.     assume    cs:code, ds:data, es:nothing
  822.  
  823. fprtasz    proc    far
  824.     call    prtasz
  825.     ret
  826. fprtasz    endp
  827. fpcwait    proc    far
  828.     call    pcwait
  829.     ret
  830. fpcwait    endp
  831. fstrlen    proc    far
  832.     call    strlen
  833.     ret
  834. fstrlen    endp
  835. fdecout    proc    far
  836.     call    decout
  837.     ret
  838. fdecout    endp
  839. fvalout    proc    far
  840.     call    valout
  841.     ret
  842. fvalout    endp
  843. foutchr    proc    far
  844.     call    outchr
  845.     ret
  846. foutchr    endp
  847. fdopar    proc    far
  848.     call    dopar
  849.     ret
  850. fdopar    endp
  851.  
  852. ; local initialization
  853.  
  854. lclini    proc    near
  855.     call    pcwtst        ; calibrate software timer
  856.     call    pcwtst
  857.     mov    flags.comflg,1    ; assume COM1 for communications port
  858.     call    model        ; get model of IBM machine
  859.     mov    lclsusp,offset suspend ; call this when suspending to DOS
  860.     mov    lclrest,offset restore ; call this when returning from DOS
  861.     mov    lclexit,offset finexit ; call this when exiting Kermit
  862.     call    getcodep        ; get Code Page ident
  863.     call    lclyini        ; let other modules initialize too...
  864.     ret
  865. lclini    endp
  866.  
  867. ; Call these routines when suspending Kermit to go to DOS
  868. suspend    proc    near
  869.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  870.     cmp    flags.comflg,'t'; doing TCP?
  871.     je    suspen1        ; e = yes, don't touch port
  872.     call    ihosts        ; suspend the host
  873.     mov    ax,20        ; wait 20 millisec for port to finish
  874.     call    pcwait
  875.     call    serrst
  876. suspen1:ret
  877. suspend    endp
  878.  
  879. ; Call these routines when returning to Kermit from DOS
  880. restore    proc    near
  881.     call    getcodep    ; reset Code Page ident
  882.     call    kbrest        ; DEC LK250 keyboard, set back to DEC mode
  883.     cmp    flags.comflg,'t'; doing TCP?
  884.     je    restor1        ; e = yes, don't touch port
  885.     call    serini        ; reinit serial port
  886.     call    ihostr        ; resume the host
  887. restor1:ret
  888. restore    endp
  889.  
  890. ; Call these routines when doing final exit of Kermit
  891. finexit    proc    near
  892.     call    serrst        ; reset serial port
  893.     cmp    nettype,0    ; any network connections open?
  894.     je    finex2        ; e = no, but go through the motions anyway
  895.     mov    dx,offset clomsg ; say connection going, ask for permission
  896.     call    prompt
  897.     mov    dx,offset clotab ; table of choices
  898.     xor    bx,bx        ; help
  899.     mov    ah,cmkey    ; get keyword
  900.     call    comnd
  901.     pushf
  902.     mov    ah,cmeol
  903.     call    comnd
  904.     popf
  905.     jnc    finex1        ; nc = got good response
  906.     ret            ; return carry set to say don't close
  907. finex1:    or    bx,bx        ; ok to close
  908.     jz    finex2        ; e = yes
  909.     stc            ; carry set to say don't close
  910.     ret
  911. finex2:    call    netclose    ; close network connections
  912.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  913.     clc            ; return with permission to exit
  914.     ret
  915. finexit    endp
  916.  
  917. ; The IBM PC's.
  918. model    proc    near
  919.     mov    isps2,0            ; PS/2 present indicator
  920.     push    es
  921.     push    ax            ; get IBM model code
  922.     mov    al,byte ptr es:[0fffeh]    ; get model id byte
  923.     mov    ah,0ch            ; AT and PS/2 configuration call
  924.     xor    al,al
  925.     int    15h            ; IBM Bios
  926.     jc    modelx            ; c = no information
  927.     cmp    word ptr es:[bx+2],040fch ; PS/2 model 50?
  928.     je    model3            ; e = yes
  929.     cmp    word ptr es:[bx+2],050fch ; PS/2 model 60?
  930.     je    model3            ; e = yes
  931.     cmp    byte ptr es:[bx+2],0f8h ; PS/2 model 80?
  932.     jne    modelx            ; ne = no
  933. model3:    mov    isps2,1            ; say real PS/2 for IRQ setting
  934. modelx:    pop    ax
  935.     pop    es
  936.     ret
  937. model    endp
  938.  
  939. ; Get the currently active Code Page ident into flags.chrset. User defined
  940. ; table overrides DOS report.
  941. getcodep proc    near
  942.     cmp    flags.chrset,1        ; user-defined table in use?
  943.     je    getcod1            ; e = yes
  944.     cmp    flags.chrset,866    ; forced CP866 in use?
  945.     je    getcod1            ; e = yes
  946.     mov    flags.chrset,437    ; find default global char set
  947.     cmp    dosnum,0300h+30        ; DOS version 3.30 or higher?
  948.     jb    getcod1            ; b = no, no Code Pages
  949.     mov    ax,6601h        ; get global Code Page
  950.     int    dos            ; bx=active Code Page, dx=boot CP
  951.     jc    getcod1
  952.     mov    flags.chrset,bx        ; setup default SET FILE CHAR SET
  953.     mov    vtcpage,bx        ; set terminal Code Page too
  954. getcod1:ret
  955. getcodep endp
  956.  
  957. ; show the definition of a key.  The terminal argument block (which contains
  958. ; the address and length of the definition tables) is passed in ax.
  959. ; Returns a string to print in AX, length of same in CX.
  960. ; Returns normally. Obsolete, name here for external reference only.
  961. showkey    proc    near
  962.     ret                ; return
  963. showkey    endp
  964. code    ends
  965.  
  966. code1    segment
  967.     assume    cs:code1
  968.  
  969. ftcpstats proc    far            ; TCP/IP status display
  970.     mov    ah,prstr
  971.     mov    dx,offset tcpadrst
  972.     int    dos
  973.     mov    dx,tcpdata[0]        ; offset of tcpaddress string
  974.     call    fprtasz
  975.     mov    bx,tcpdata[22]
  976.     cmp    byte ptr [bx],0        ; bootp host?
  977.     je    ftcpst4            ; e = no
  978.     mov    dx,offset tcpbtpst    ; show title
  979.     int    dos
  980.     mov    dx,tcpdata[22]        ; show host IP
  981.     call    fprtasz
  982. ftcpst4:mov    dx,offset tcpsubst
  983.     int    dos
  984.     mov    dx,tcpdata[2]        ; offset of tcp subnetmask string
  985.     call    fprtasz
  986.     mov    dx,offset tcpdomst
  987.     int    dos
  988.     mov    dx,tcpdata[4]        ; offset of tcp domain string
  989.     call    fprtasz
  990.     mov    dx,offset tcpgatest
  991.     int    dos
  992.     mov    dx,tcpdata[6]        ; offset of tcp gateway string
  993.     call    fprtasz
  994.     mov    dx,offset tcppnsst
  995.     int    dos
  996.     mov    dx,tcpdata[8]        ; offset of tcp primary nameserver 
  997.     call    fprtasz
  998.     mov    dx,offset tcpsnsst
  999.     int    dos
  1000.     mov    dx,tcpdata[10]        ; offset of tcp secondary nameserver
  1001.     call    fprtasz
  1002.     mov    dx,offset tcpbcstst
  1003.     int    dos
  1004.     mov    dx,tcpdata[14]        ; offset of tcp broadcast address
  1005.     call    fprtasz
  1006.     mov    dx,offset tcpportst
  1007.     int    dos
  1008.     push    ax
  1009.     push    bx
  1010.     push    cx
  1011.     mov    bx,tcpdata[16]        ; offset of tcp port
  1012.     mov    ax,[bx]
  1013.     call    fdecout
  1014.     mov    bx,tcpdata[18]        ; offset of Packet Driver interrupt
  1015.     mov    ax,[bx]
  1016.     cmp    ax,'DO'            ; using ODI?
  1017.     jne    ftcpst3            ; ne = no
  1018.     mov    ah,prstr
  1019.     mov    dx,offset tcpodi    ; say using ODI interface
  1020.     int    dos
  1021.     jmp    short ftcpst1
  1022. ftcpst3:push    ax            ; save value
  1023.     mov    ah,prstr
  1024.     mov    dx,offset tcppdintst
  1025.     int    dos
  1026.     pop    ax
  1027.     mov    cx,16
  1028.     push    ax
  1029.     call    fvalout            ; show value as hex
  1030.     pop    ax
  1031.     or    ax,ax            ; null?
  1032.     jnz    ftcpst1            ; nz = no, just show value
  1033.     mov    ah,prstr
  1034.     mov    dx,offset tcppdnul    ; show search msg
  1035.     int    dos
  1036. ftcpst1:pop    cx
  1037.     pop    bx
  1038.     pop    ax
  1039.     mov    dx,offset tcpttyst
  1040.     int    dos
  1041.     mov    dx,tcpdata[20]        ; offset of tcp term-type override
  1042.     push    bx
  1043.     mov    bx,dx
  1044.     cmp    byte ptr [bx],0
  1045.     jne    ftcpst2
  1046.     mov    dx,offset tcpttynul    ; alternate msg
  1047. ftcpst2:pop    bx
  1048.     call    fprtasz
  1049.     mov    dx,offset tcpnlst    ; newline mode msg
  1050.     int    dos
  1051.     push    bx
  1052.     mov    bx,tcpdata[24]        ; offset of tcpnewline
  1053.     mov    bl,[bx]            ; value of 0 (off) or 1
  1054.     mov    dx,offset tcpnlmsg0    ; assume off
  1055.     or    bl,bl            ; off?
  1056.     pop    bx
  1057.     jz    ftcpst5            ; z = yes
  1058.     mov    dx,offset tcpnlmsg1    ; say on
  1059. ftcpst5:mov    ah,prstr
  1060.     int    dos
  1061.     mov    dx,offset tcpdebst    ; debug-option
  1062.     int    dos
  1063.     push    bx
  1064.     mov    bx,tcpdata[26]        ; offset of tcpdebug
  1065.     mov    bl,[bx]            ; value of 0 (off) or 1
  1066.     mov    dx,offset tcpdeboff    ; assume off
  1067.     or    bl,bl            ; off?
  1068.     pop    bx
  1069.     jz    ftcpst6            ; z = yes
  1070.     mov    dx,offset tcpdebon    ; say on
  1071. ftcpst6:mov    ah,prstr
  1072.     int    dos
  1073.     mov    dx,offset tcphostst
  1074.     int    dos
  1075.     mov    dx,tcpdata[12]        ; offset of tcp host ident string
  1076.     call    fprtasz
  1077.     ret
  1078. ftcpstats endp
  1079. code1    ends
  1080.  
  1081. code    segment
  1082.     assume    cs:code
  1083.  
  1084. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  1085. ; Uses byte mdmhand, the modem line status register.
  1086. shomodem proc    near
  1087.     mov    ah,cmeol        ; get a confirm
  1088.     call    comnd
  1089.     jnc    shomd1a            ; nc = success
  1090.     ret
  1091. shomd1a:mov    dx,offset msmsg7    ; no modem status for network
  1092.     call    getmodem        ; get modem status
  1093.     mov    mdmhand,al
  1094.     mov    ah,prstr
  1095.     mov    dx,offset msmsg1    ; modem ready msg
  1096.     test    mdmhand,20h        ; is DSR asserted?
  1097.     jz    shomd1            ; z = no
  1098.     mov    dx,offset msmsg2    ; say not asserted
  1099. shomd1:    int    dos
  1100.     mov    dx,offset msmsg3    ; CD asserted msg
  1101.     test    mdmhand,80h        ; CD asserted?
  1102.     jz    shomd2            ; z = no
  1103.     mov    dx,offset msmsg4    ; say not asserted
  1104. shomd2:    int    dos
  1105.     mov    dx,offset msmsg5    ; CTS asserted msg
  1106.     test    mdmhand,10h        ; CTS asserted?
  1107.     jz    shomd3            ; z = no
  1108.     mov    dx,offset msmsg6    ; say not asserted
  1109. shomd3:    mov    ah,prstr
  1110.     int    dos
  1111.     
  1112.     mov    al,flags.comflg
  1113.     cmp    al,'1'            ; UART?
  1114.     jae    shomd3c            ; ae = no
  1115.     add    al,'0'            ; COMnumber
  1116.     mov    msmsg8+7,al        ; stuff in msg
  1117.     mov    ah,prstr
  1118.     mov    dx,offset msmsg8    ; show port base address
  1119.     int    dos
  1120.     mov    ax,modem.mddat        ; port address
  1121.     mov    cx,16            ; in hex
  1122.     call    valout
  1123.     mov    ah,prstr
  1124.     mov    dx,offset msmsg9    ; and IRQ
  1125.     int    dos
  1126.     mov    ax,modem.mdintv        ; interrupt vector
  1127.     mov    cl,al
  1128.     and    ax,7            ; lower three bits of IRQ
  1129.     cmp    cl,60h            ; using cascaded 8259?
  1130.     jb    shomd3a            ; b = no
  1131.     add    ax,8            ; say IRQ 8..15
  1132. shomd3a:call    decout            ; output as decimal
  1133.     cmp    fifo,0            ; UART FIFO active?
  1134.     je    shomd3c            ; e = no
  1135.     mov    dx,offset msmsg10    ; FIFO msg
  1136.     mov    ah,prstr
  1137.     int    dos
  1138.  
  1139. shomd3c:call    ftcpstats        ; call TCP/IP FAR worker
  1140.     mov    dx,offset netmsg3    ; local name
  1141.     int    dos
  1142.     mov    cx,16
  1143.     mov    di,offset deflname    ; default Netbios name
  1144.     call    prtscr
  1145.     cmp    rcv.scb_lname,' '    ; have NetBios name yet?
  1146.     jbe    shomd4            ; be = no, skip this part
  1147.     mov    ah,prstr
  1148.     mov    dx,offset netmsg4    ; remote name
  1149.     int    dos
  1150.     mov    cx,16
  1151.     mov    di,offset rcv.scb_rname
  1152.     call    prtscr
  1153. shomd4:    cmp    latservice,0        ; DECnet name available?
  1154.     je    shomd5            ; e = no
  1155.     mov    ah,prstr
  1156.     mov    dx,offset netmsg5
  1157.     cmp    teslat,0        ; TES-LAT instead?
  1158.     je    shomd4a            ; e = no
  1159.     mov    dx,offset netmsg7    ; TES heading
  1160. shomd4a:int    dos
  1161.     mov    dx,offset latservice    ; network host name, asciiz
  1162.     call    prtasz
  1163. shomd5:    cmp    word ptr internet,0    ; have TELAPI Internet address?
  1164.     je    shomd7            ; e = no
  1165.     mov    ah,prstr
  1166.     mov    dx,offset netmsg6
  1167.     int    dos
  1168.     xor    bx,bx            ; subscript
  1169.     mov    cx,4            ; four fields
  1170. shomd6:    mov    al,internet[bx]        ; binary internet address
  1171.     xor    ah,ah
  1172.     call    decout
  1173.     cmp    cx,1            ; doing last field?
  1174.     je    shmod6a            ; e = yes, no dot
  1175.     mov    dl,'.'
  1176.     mov    ah,conout
  1177.     int    dos
  1178. shmod6a:inc    bx
  1179.     loop    shomd6
  1180. shomd7:    cmp    tesname,0        ; have TES name?
  1181.     je    shomd8            ; e = no
  1182.     mov    ah,prstr
  1183.     mov    dx,offset netmsg7
  1184.     int    dos
  1185.     mov    dx,offset tesname    ; node name
  1186.     call    prtasz            ; show, asciiz
  1187.     clc
  1188.     ret
  1189. shomd8:    cmp    ebcoms+2,0        ; have an EBIOS name?
  1190.     je    shomd9            ; e = no
  1191.     mov    ah,prstr
  1192.     mov    dx,offset netmsg8
  1193.     int    dos
  1194.     mov    cx,16
  1195.     mov    di,offset ebcoms+2    ; host port, 16 chars space filled
  1196.     call    prtscr
  1197. shomd9:    clc
  1198.     ret
  1199. shomodem endp
  1200.  
  1201. ; Get modem status and set global byte mdmhand. Preserve all registers.
  1202. getmodem proc    near            ; gets modem status upon request
  1203.     cmp    portin,1        ; port active?
  1204.     je    getmod1            ; e = yes
  1205.     mov    bl,flags.comflg        ; pass current port ident
  1206.     cmp    bl,'4'            ; above UART and Bios?
  1207.     ja    getmod1            ; a = yes, do not start the port
  1208.     call    comstrt            ; do SET PORT command now
  1209.     jnc    getmod1            ; nc = success
  1210.     ret                ; failed to set port
  1211. getmod1:xor    al,al            ; assume nothing is on
  1212.     cmp    flags.comflg,'1'    ; UART?
  1213.     jae    getmod2            ; ae = no
  1214.     cmp    flags.comflg,0        ; null port?
  1215.     je    getmodx            ; e = yes, no status
  1216.     mov    dx,modem.mdstat        ; hardware, line status reg
  1217.     inc    dx            ; modem status reg
  1218.     in    al,dx
  1219.     jmp    short getmodx
  1220. getmod2:cmp    flags.comflg,'4'    ; above Bios? (networks)
  1221.     ja    getmod3            ; a = yes, no status
  1222.     mov    ah,3            ; ask Bios for modem status into al
  1223.     push    dx
  1224.     mov    dl,flags.comflg        ; get port id
  1225.     sub    dl,'1'            ; remove ascii bias (BIOS1 -> 0)
  1226.     int    rs232
  1227.     pop    dx
  1228. getmod3:cmp    flags.comflg,'E'    ; IBM EBIOS?
  1229.     jne    getmodx            ; ne = no
  1230.     mov    ah,3            ; get Bios style modem status
  1231.     push    dx
  1232.     mov    dx,ebport        ; current EBIOS port
  1233.     int    rs232
  1234.     pop    dx
  1235. getmodx:xor    ah,ah            ; return status in al
  1236.     clc
  1237.     ret
  1238. getmodem endp
  1239.  
  1240. ; Clear the input buffer. This throws away all the characters in the
  1241. ; serial interrupt buffer.  This is particularly important when
  1242. ; talking to servers, since NAKs can accumulate in the buffer.
  1243. ; Returns normally.
  1244.  
  1245. CLRBUF    PROC    NEAR
  1246.     cmp    repflg,0        ; REPLAY?
  1247.     je    clrbuf1            ; e = no
  1248.     ret
  1249. clrbuf1:call    prtchr            ; read from active comms port
  1250.     jnc    clrbuf1            ; nc = got a char, continue til none
  1251.     mov    ax,10            ; wait 10 ms
  1252.     call    pcwait
  1253.     call    prtchr            ; read from active comms port
  1254.     jnc    clrbuf1            ; nc = got a char, continue til none
  1255.     mov    lastread,0
  1256.     clc
  1257.     ret
  1258. CLRBUF    ENDP
  1259.  
  1260. ; Clear to the end of the current line.  Returns normally.
  1261. ; Upgraded for Topview compatibility.
  1262. CLEARL    PROC    NEAR
  1263.     push    ax
  1264.     push    bx
  1265.     push    dx
  1266.     mov    ah,3            ; Clear to end of line
  1267.     xor    bh,bh
  1268.     int    video            ; Get current cursor position into dx
  1269.     mov    ax,dx            ; Topview compatible clear line
  1270.     mov    bh,ah            ; same row
  1271.     mov    bl,byte ptr low_rgt    ; last column
  1272.     call    fatsclr            ; clear from ax to bx, screen coord
  1273.     pop    dx
  1274.     pop    bx
  1275.     pop    ax
  1276.     ret
  1277. CLEARL    ENDP
  1278.  
  1279. ; This routine blanks the screen.  Returns normally.
  1280. ; Upgraded to Topview compatiblity.
  1281. CMBLNK    PROC    NEAR
  1282.     push    ax
  1283.     push    bx
  1284.     xor    ax,ax            ; from screen loc 0,0
  1285.     mov    bx,low_rgt    ; to end of text screen (lower right corner)
  1286.     inc    bh            ; include status line
  1287.     call    fatsclr             ; do Topview compatible clear, in msyibm
  1288.     pop    bx
  1289.     pop    ax
  1290.     ret
  1291. CMBLNK  ENDP
  1292.  
  1293. ; Locate: homes the cursor.  Returns normally.
  1294.  
  1295. LOCATE  PROC    NEAR
  1296.     xor    dx,dx            ; Go to top left corner of screen
  1297.     jmp    poscur
  1298. LOCATE  ENDP
  1299.  
  1300. ; Position the cursor according to contents of DX:
  1301. ; DH contains row, DL contains column.  Returns normally.
  1302. POSCUR    PROC    NEAR
  1303.     push    ax
  1304.     push    bx
  1305.     mov    ah,2            ; Position cursor
  1306.     xor    bh,bh            ; page 0
  1307.     int    video
  1308.     pop    bx
  1309.     pop    ax
  1310.     ret
  1311. POSCUR    ENDP
  1312.  
  1313. ; Delete a character from the screen.  This works by printing
  1314. ; backspaces and spaces.
  1315.  
  1316. DODEL    PROC    NEAR
  1317.     mov    ah,prstr
  1318.     mov    dx,offset delstr    ; Erase character
  1319.     int    dos            
  1320.     ret
  1321. DODEL    ENDP
  1322.  
  1323. ; Move the cursor to the left margin, then clear to end of line.
  1324.  
  1325. CTLU    PROC    NEAR
  1326.     mov    ah,prstr
  1327.     mov    dx,offset clrlin
  1328.     int    dos
  1329.     jmp    clearl
  1330. CTLU    ENDP
  1331.  
  1332.  
  1333. BEEP    PROC    NEAR
  1334.     mov    timeract,1    ; say timer chip is being used here
  1335.     push    ax
  1336.     push    cx
  1337.     mov    al,10110110B    ; Gen a short beep (long one losses data.)
  1338.     out    timercmd,al    ; set Timer to to mode 3
  1339.     mov    ax,1512        ; divisor, for frequency
  1340.     out    timer2data,al    ; send low byte first
  1341.     mov    al,ah
  1342.     out    timer2data,al
  1343.     in    al,ppi_port    ; get 8255 Port B setting
  1344.     or    al,3        ; turn on speaker and timer
  1345.     out    ppi_port,al    ; start speaker and timer
  1346.     push    ax
  1347.     mov    ax,40        ; 40 millisecond beep, calibrated time
  1348.     call    pcwait
  1349.     pop    ax
  1350.     in    al,ppi_port
  1351.     and    al,0fch        ; turn off speaker and timer
  1352.     out    ppi_port,al
  1353.     pop    cx
  1354.     pop    ax
  1355.     mov    timeract,0    ; say timer chip is no longer in use here
  1356.     clc
  1357.     ret
  1358. BEEP    ENDP 
  1359.  
  1360.  
  1361. ; write a line in inverse video at the bottom of the screen...
  1362. ; the line is passed in dx, terminated by a $.  Returns normally.
  1363. putmod    proc    near
  1364.     push    ax        ; save regs
  1365.     push    bx
  1366.     push    cx
  1367.     push    dx
  1368.     push    si
  1369.     mov    si,dx        ; preserve message
  1370.     mov    bl,scbattr    ; screen attributes at Kermit init time
  1371.     push    bx        ; save scbattr
  1372.     and    bl,77h        ; get colors, omit bright and blink
  1373.     rol    bl,1        ; interchange fore and background
  1374.     rol    bl,1
  1375.     rol    bl,1
  1376.     rol    bl,1
  1377.     mov    scbattr,bl
  1378.     call    clrmod        ; clear mode line to inverse video
  1379.     mov    dx,low_rgt    ; lower right corner
  1380.     inc    dh        ;  of status line
  1381.     xor    dl,dl        ; start on left
  1382.     mov    ah,scbattr    ; inverse video attribute
  1383.     cld
  1384. putmo1:    lodsb            ; get a byte
  1385.     cmp    al,'$'        ; end of string?
  1386.     je    putmo2
  1387.     call    fsetatch    ; write char and attribute
  1388.     inc    dl        ; increment for next write
  1389.     cmp    dl,crt_cols    ; beyond physical right border?
  1390.     jb    putmo1        ; b = no
  1391. putmo2:    pop    bx
  1392.     mov    scbattr,bl
  1393.     pop    si
  1394.     pop    dx
  1395.     pop    cx
  1396.     pop    bx
  1397.     pop    ax
  1398.     ret
  1399. putmod    endp
  1400.  
  1401. ; clear the mode line written by putmod.
  1402. clrmod    proc    near
  1403.     push    ax        ; save regs
  1404.     push    bx
  1405.     mov    bx,low_rgt    ; ending location is lower right corner
  1406.     inc    bh        ;  of status line
  1407.     mov    ah,bh
  1408.     xor    al,al        ; column zero
  1409.     call    fatsclr        ; clear this region
  1410.     pop    bx
  1411.     pop    ax
  1412.     ret
  1413. clrmod    endp
  1414.  
  1415. ; put a help message on the screen.  This one uses reverse video...
  1416. ; pass the message in ax, terminated by a null.
  1417. puthlp    proc    near
  1418.     push    bx        ; save regs
  1419.     push    cx
  1420.     push    dx
  1421.     push    si
  1422.     push    ax        ; preserve this
  1423.     cld
  1424.     mov    bl,scbattr    ; screen attributes at Kermit init time
  1425.     and    bl,77h        ; get colors, omit bright and blink
  1426.     rol    bl,1        ; interchange fore and background
  1427.     rol    bl,1
  1428.     rol    bl,1
  1429.     rol    bl,1
  1430.     xor    bh,bh        ; preset page 0
  1431.     mov    temp,bx        ; temp = page 0, reverse video 
  1432.  
  1433.     mov    si,ax        ; point to it
  1434.     mov    dh,1        ; init counter
  1435. puthl1:    lodsb            ; get a byte
  1436.     cmp    al,lf        ; linefeed?
  1437.     jne    puthl2        ; no, keep going
  1438.     inc    dh        ; count it
  1439.     jmp    short puthl1    ; and keep looping
  1440. puthl2:    or    al,al        ; end of string?
  1441.     jnz    puthl1        ; nz = no, keep going
  1442.     mov    ax,600h        ; scroll to clear window
  1443.     xor    cx,cx        ; from top left
  1444.     mov    dl,4fh        ; to bottom right of needed piece
  1445.     mov    bh,70h        ; inverse video
  1446.     mov    bh,bl        ; inverse video
  1447.     int    video
  1448.     call    locate        ; home cursor
  1449.     mov    bx,0070h    ; bh = page 0, bl = inverse video
  1450.     mov    bx,temp
  1451.     mov    cx,1        ; one char at a time
  1452.     cld            ; scan direction is forward
  1453.     pop    si        ; point to string again
  1454. puthl3:    lodsb            ; get a byte
  1455.     or    al,al        ; end of string?
  1456.     jz    puthl4        ; z = yes, stop
  1457.     push    si        ; save around bios call
  1458.     cmp    al,' '        ; printable?
  1459.     jb    puth21        ; b = no
  1460.     mov    ah,9        ; write char at current cursor position
  1461.     int    video        ; do the Bios int 10h call
  1462.     inc    dl        ; point to next column
  1463.     jmp    short puth23    ; move cursor there
  1464. puth21:    cmp    al,cr        ; carriage return?
  1465.     jne    puth22        ; ne = no
  1466.     xor    dl,dl        ; set to column zero
  1467.     jmp    short puth23
  1468. puth22:    cmp    al,lf        ; line feed?
  1469.     jne    puth23
  1470.     inc    dh        ; go to next line
  1471. puth23:    mov    ah,2        ; set cursor position to dx
  1472.     int    video
  1473.     pop    si        ; restore pointer
  1474.     jmp    short puthl3    ; and keep going
  1475. puthl4:    mov    dh,byte ptr low_rgt+1    ; go to last line
  1476.     inc    dh
  1477.     xor    dl,dl
  1478.     call    poscur        ; position cursor
  1479.     pop    si
  1480.     pop    dx
  1481.     pop    cx
  1482.     pop    bx
  1483.     ret
  1484. puthlp    endp
  1485.  
  1486.  
  1487. ; set the current port.  
  1488. ; Note: serial port addresses are found by looking in memory at 40:00h and
  1489. ; following three words for COM1..4, resp. All UARTS are assumed to follow
  1490. ; std IBM addresses relative to 03f8h for COM1, and actual address are offset
  1491. ; from value found in segment 40h. Global byte flags.comflg is 1,2,3,4 for
  1492. ; COM1..4, and is 'N' for NetBios, etc.
  1493. ; 'O' is for Intel Opennet Network (FGR)
  1494. ; If address 02f8h is found in 40:00h then name COM1 is retained but COM2
  1495. ;  addressing is used to access the UART and a notice is displayed. IRQ 3
  1496. ; or IRQ 4 is sensed automatically for any COMx port.
  1497. COMS    PROC    NEAR
  1498.     mov    dx,offset comptab    ; table of legal comms ports
  1499.     xor    bx,bx            ; no extra help text
  1500.     mov    ah,cmkey        ; parse key word
  1501.     call    comnd
  1502.     jnc    coms0a            ; nc = success
  1503.     ret                ; failure
  1504. coms0a:    cmp    bl,'4'            ; networks?
  1505.     ja    comstrt            ; a = yes
  1506.     mov    ah,cmeol        ; non-network
  1507.     push    bx
  1508.     call    comnd            ; get a confirm
  1509.     pop    bx
  1510.     jnc    comstrt            ; nc = success
  1511.     ret                ; failure
  1512.  
  1513. COMSTRT:mov    temp,bx            ; port ident is in BL
  1514.     cmp    bl,'N'            ; NetBios network?
  1515.     jne    comst2a            ; ne = no
  1516.       jmp    comsn            ; yes, get another item for networks
  1517. comst2a:cmp    bl,'O'            ; Opennet network?
  1518.       jne    comst2            ; ne = no
  1519.     jmp    comso            ; yes, get another item for networks
  1520.  
  1521. comst2:    cmp    bl,'U'            ; Ungermann Bass net?
  1522.     jne    comst3            ; ne = no
  1523.     jmp    comsub
  1524. comst3:    cmp    bl,'D'            ; DECnet?
  1525.     jne    comst4            ; ne = no
  1526.     jmp    comsd            ; do DECnet startup
  1527. comst4:    cmp    bl,'E'            ; IBM EBIOS?
  1528.     jne    comst5            ; ne = no
  1529.     test    nettype,acsi        ; NetBios without EBIOS.COM?
  1530.     jz    comst4a            ; z = no, using EBIOS.COM
  1531.     mov    inettyp,bl        ; set type code
  1532.     jmp    comso2            ; do NetBios setup
  1533. comst4a:jmp    comse            ; do EBIOS checkup
  1534. comst5:    cmp    bl,'W'            ; Novell NASI?
  1535.     jne    comst6            ; ne = no
  1536.     jmp    comsub
  1537. comst6:    cmp    bl,'C'            ; 3Com BAPI?
  1538.     jne    comst7            ; ne = no
  1539.     jmp    comsbapi
  1540. comst7:    cmp    bl,'T'            ; Novell TELAPI
  1541.     jne    comst8            ; ne = no
  1542.     jmp    comstelapi
  1543. comst8:    cmp    bl,'I'            ; TES?
  1544.     jne    comst9            ; ne = no
  1545.     jmp    comsteslat
  1546. comst9:    cmp    bl,'t'            ; Telnet, internal?
  1547.     jne    comst10            ; ne = no
  1548.     jmp    comstn
  1549. comst10:cmp    bl,'b'            ; [JRS] Beame & Whiteside TCP?
  1550.     jne    coms1c            ; [JRS]
  1551.     jmp    comsbw            ; setup BW connection
  1552.                       ; stop sources of NetBios interrupts
  1553. coms1c:    call    nbclose            ; close NetBios session now
  1554.     
  1555. coms2:    call    serrst            ; close current comms port
  1556.     mov    al,byte ptr temp    ; get COMx (1-4)
  1557.     mov    flags.comflg,al        ; remember port ident
  1558.     cmp    al,'1'            ; Bios?
  1559.     jb    coms2a            ; b = no, hardware
  1560.     sub    al,'0'            ; remove ascii bias for portinfo
  1561. coms2a:    dec    al
  1562.     xor    ah,ah            ; count ports from 0
  1563.     push    bx            ; set port structure
  1564.     mov    bx,type prtinfo        ; size of each portinfo structure
  1565.     mul    bl            ; times port number
  1566.     pop    bx            ; restore register
  1567.     add    ax,offset port1        ; plus start of COM1
  1568.     mov    portval,ax        ; points to our current port struct
  1569.     cmp    flags.comflg,'1'    ; Bios path?
  1570.     jb    coms4            ; b = no, check hardware
  1571.     add    ax,offset portb1-offset port1 ; correct to use Bios ports
  1572.     mov    portval,ax
  1573.     clc
  1574.     ret
  1575.  
  1576. coms4:     cmp    portin,-1        ; serial port touched yet?
  1577.     jne    coms4a            ; ne = yes, else avoid init looping
  1578.     mov    portin,0        ; say serial port is being touched
  1579. coms4a:    push    es
  1580.     mov    ax,40h        ; look at RS232_base [bx] in Bios area 40:00h
  1581.     mov    es,ax
  1582.     mov    bx,temp            ; get desired port number 1..4
  1583.     xor    bh,bh
  1584.     dec    bl            ; count com1 as bl = 0, etc
  1585.     shl    bx,1            ; make bx a word index
  1586.     mov    ax,es:[bx]        ; get modem base address into ax
  1587.     pop    es
  1588.     push    bx            ; save this index
  1589.     or    ax,ax            ; is address zero?
  1590.     jnz    comsc            ; nz = no, have port address
  1591.     mov    ah,prstr
  1592.     mov    dx,offset badprt    ; tell them what we are doing
  1593.     int    dos
  1594.     mov    ax,defcom[bx]        ; get default COMn port address
  1595.     push    ax
  1596.     mov    cx,16            ; base 16
  1597.     call    valout            ; show port
  1598.     pop    ax
  1599. comsc:                    ; hardware tests
  1600.     mov    modem.mddat,ax    ; set base address (also data address) 03f8h
  1601.     add    ax,2
  1602.     mov    modem.mdiir,ax        ; interrupt identification reg 03fah
  1603.     inc    ax            ; increment to command port 03fbh
  1604.     mov    modem.mdcom,ax        ; set line control register address
  1605.     add    ax,2            ; increment to status port 03fdh
  1606.     mov    modem.mdstat,ax        ; set line-status port address
  1607.     call    chkport            ; get type of UART support
  1608.     pop    bx            ; recover port index
  1609.     jc    comsnu            ; c = not a real 8250 class UART
  1610.     mov    ax,40h
  1611.     push    es
  1612.     mov    es,ax
  1613.     mov    ax,modem.mddat        ; get COMn port address
  1614.     mov    es:[bx],ax        ; force into seg 40h
  1615.     pop    es
  1616.     call    chkint            ; find IRQ for the port
  1617.     jnc    comsc1            ; nc = found, else error condition
  1618.     ret
  1619. comsc1:    call    getbaud            ; update current baud info for port
  1620.     clc
  1621.     ret                ; success
  1622.  
  1623.                     ; no UART
  1624. comsnu:    mov     ah,prstr        ; tell user about Bios pathway
  1625.     mov    dx,offset biosmsg
  1626.     int    dos
  1627.     mov    dl,byte ptr temp    ; selected hardware port
  1628.     add    dl,'0'            ; map to Bios
  1629.     mov    flags.comflg,dl
  1630.     mov    ah,conout        ; say port number
  1631.     int    dos
  1632.     stc                ; say error
  1633.     ret
  1634.                                         ; Opennet Network support (FGR)
  1635. comso:    mov    inettyp,'O'        ; remember OpenNet type network
  1636.     jmp    short comso2        ; do generic network code
  1637.                       ; NetBios Network support
  1638. comsn:    mov    inettyp,'N'        ; remember Netbios type network
  1639. comso2:    mov    ah,cmword        ; get a word (remote node name)
  1640.     mov    dx,offset decbuf    ; work buffer
  1641.     mov    word ptr decbuf,0    ; insert terminator
  1642.     mov    bx,offset nethlp    ; help message
  1643.     call    comnd            ; get the name, ignore errors
  1644.     mov    newnambuf,al        ; save number of chars entered
  1645.     mov    ah,cmeol
  1646.     call    comnd            ; get a confirm
  1647.     jc    comsn2            ; c = failure
  1648.     ; Enter here from EBIOS when EBIOS.COM is not installed. Use 'E'
  1649.     ; and nettype subident of abios.
  1650. comsn3:    call    serrst            ; reset serial port
  1651.     cmp    newnambuf,0        ; any name given?
  1652.     je    comsn1            ; e = no, use current name
  1653.     mov    si,offset decbuf
  1654.     mov    di,offset nambuf    ; copy to here
  1655.     call    strcpy
  1656. comsn1:    call    chknet            ; start network usage
  1657.     jc    comsn2            ; c = failed
  1658.     cmp    pcnet,0            ; is network alive (non-zero)?
  1659.     jne    comsn4            ; ne = yes
  1660. comsn2:    stc
  1661.     ret                ; failure
  1662.  
  1663. comsn4:    mov    portval,offset port_nb     ; set Network port structure address
  1664.     mov    port_nb.portrdy,1    ; say the comms port is ready
  1665.     mov    al,inettyp        ; FGR - get saved network type
  1666.     mov    flags.comflg,al        ; set the Netbios port flag
  1667.     clc                ; return success
  1668.     ret                ; End NetBios
  1669.  
  1670.                     ; Ungermann-Bass terminal port [ohl +]
  1671. comsub:    push    bx            ; save net type U or W
  1672.     mov     ah,cmeol
  1673.         call    comnd                   ; get a confirm
  1674.     jc    comsub0            ; c = failure
  1675.     call    serrst            ; reset serial port
  1676.         call    chkub                   ; check UB network presence
  1677.     pop    bx            ; recover net type U or W
  1678.     jnc    comsub1            ; nc = present
  1679. comsub0:ret                ; return failure
  1680.  
  1681. comsub1:mov     portval,offset port_ub ; set Network port data structure address
  1682.     mov    port_ub.portrdy,1    ; say the comms port is ready
  1683.         mov     flags.comflg,bl        ; set the comm port flag
  1684.     mov     pcnet,2                 ; network is present and active
  1685.         clc                ; return success
  1686.         ret                ; End Ungermann Bass / Novell NASI
  1687.  
  1688.                     ; TESLAT
  1689. comsteslat:
  1690.     mov    teslat,1        ; say TES over LAT (vs DECnet)
  1691.     jmp    short comsd1        ; common code
  1692.                     ; DECnet
  1693. comsd:    mov    teslat,0        ; DECnet over LAT or CTERM
  1694.  
  1695. comsd1:    mov    ah,cmword        ; get a word (remote node name)
  1696.     mov    dx,offset decbuf    ; work buffer
  1697.     mov    word ptr decbuf,0    ; insert terminator
  1698.     mov    bx,offset dnethlp    ; help message
  1699.     call    comnd            ; get the name
  1700.     mov    temp,ax            ; save number of chars entered
  1701.     mov    ah,cmword        ; get optional LAT service name
  1702.     mov    dx,offset decbuf+80    ; work near end of this buffer
  1703.     mov    word ptr decbuf+80,0    ; insert terminator
  1704.     mov    bx,offset nethlp2    ; help message
  1705.     mov    comand.cmblen,16    ; length of buffer (password = 16 chr)
  1706.     call    comnd            ; get the name, ignore if absent
  1707.     mov    decbuf+79,al        ; store byte count in name here
  1708.     mov    comand.cmblen,0        ; length of buffer back to normal
  1709.     mov    ah,cmeol
  1710.     call    comnd            ; get a confirm
  1711.     jnc    comsd3
  1712.     ret                ; did not get a confirm
  1713. comsd3:    call    serrst            ; close serial port now
  1714.     cmp    temp,0            ; any node name?
  1715.     je    comsd8            ; e = no, assume preestablished
  1716.      cmp    decbuf,'*'        ; just show LAT names?
  1717.     jne    comsd4            ; ne = no
  1718.     call    far ptr chkdec        ; see if network is available
  1719.     jc    comsd3a            ; c = no, no net available
  1720.     and    nettype,not decnet    ; remove CTERM indicator
  1721.     test    nettype,declat        ; LAT type present?
  1722.     jz    comsd3a            ; z = no
  1723.     call    latlst            ; show LAT names
  1724.     and    nettype,not declat    ; remove this indicator
  1725.     clc                ; success but do not make connection
  1726.     ret
  1727.  
  1728. comsd3a:cmp    teslat,0        ; doing TES-LAT?
  1729.     je    comsd3b            ; e = no, DECnet
  1730.     mov    teslat,0        ; not this method of TES
  1731.     jmp    comstes1        ; try older TES method
  1732. comsd3b:mov    ah,prstr
  1733.     mov    dx,offset nonetmsg    ; say net is not available
  1734.     int    dos
  1735.     clc
  1736.     ret
  1737.                     ; put name in uppercase, strip '::'
  1738. comsd4:    mov    si,offset decbuf    ; the node name, make upper case
  1739.     mov    cx,temp            ; length of node name
  1740.     add    si,cx            ; and add '::' if absent
  1741.     push    ds
  1742.     pop    es
  1743.     cmp    byte ptr [si-1],':'    ; ended on colon?
  1744.     jne    comsd5            ; ne = no
  1745.     dec    cx            ; remove it
  1746.     cmp    byte ptr [si-2],':'    ; first colon present?
  1747.     jne    comsd5            ; e = yes
  1748.     dec    cx            ; remove it
  1749. comsd5:    mov    si,offset decbuf    ; uppercase and copy name
  1750.     mov    di,offset latservice    ; to this structure
  1751.     jcxz    comsd7a            ; z = empty name
  1752.     cld
  1753. comsd6:    lodsb                ; si = new node name
  1754.     cmp    al,'a'            ; in lower case?
  1755.     jb    comsd7            ; b = no
  1756.     cmp    al,'z'            ; in lower case?
  1757.     ja    comsd7            ; a = no
  1758.     and    al,not 20h        ; convert to upper case
  1759. comsd7:    stosb
  1760.     loop    comsd6
  1761. comsd7a:mov    byte ptr [di],0        ; terminate latservice name
  1762.     mov    si,offset decbuf+80    ; LAT password
  1763.     mov    di,offset latpwd    ; where it will reside
  1764.     mov    byte ptr [di],0        ; clear password now
  1765.     call    strcpy            ; copy it, asciiz
  1766.     mov    cl,decbuf+79        ; length of name
  1767.     xor    ch,ch
  1768.     add    di,cx            ; point to trailer
  1769.     sub    cx,16            ; max chars in password
  1770.     jle    comsd8            ; le = filled now, or no password
  1771.     mov    al,' '            ; make it space filled
  1772.     push    ds
  1773.     pop    es
  1774.     rep    stosb            ; fill in spaces
  1775. comsd8:    call    far ptr chkdec        ; see if network is available
  1776.     jc    comsd3a            ; c = no
  1777.  
  1778.     mov    ah,prstr
  1779.     test    nettype,decnet        ; starting CTERM?
  1780.     jz    comsd9a            ; z = no
  1781.     mov    dx,offset decmsg4    ; assume CTERM
  1782.     int    dos
  1783. comsd9a:test    nettype,declat        ; LAT too?
  1784.     jz    comsd9b            ; z = no
  1785.     cmp    teslat,0        ; TES-LAT?
  1786.     jne    comsd9b            ; ne = yes, don't say LAT on screen
  1787.     mov    dx,offset decmsg5    ; say LAT connection is ready
  1788.     int    dos
  1789. comsd9b:cmp    pcnet,2            ; session active?
  1790.     jb    comsd10            ; b = no, start a new one
  1791.     call    chknew            ; session exists, Resume or start new?
  1792.     jc    comsd11            ; c = resume
  1793.     call    decclose        ; close current session
  1794. comsd10:mov     portval,offset port_dec ; set Network port data structure addr
  1795.     cmp    teslat,0        ; TESLAT?
  1796.     jne    comsd12            ; ne = yes
  1797.     mov    flags.comflg,'D'    ; set the comm port flag
  1798. comsd11:clc
  1799.     ret                ; end of DECnet
  1800. comsd12:mov    flags.comflg,'I'    ; set the comm port flag
  1801.     clc
  1802.     ret                ; end of TESLAT
  1803.  
  1804.  
  1805. comsbapi:mov    ah,bapihere        ; 3Com BAPI presence check
  1806.     xor    al,al
  1807.     mov    bx,0aaaah        ; undocumented magic
  1808.     int    bapiint
  1809.     cmp    ax,0af01h        ; signature
  1810.     jne    comsbap1        ; ne = not present
  1811.     call    serrst            ; close current port
  1812.     mov    ah,bapieecm        ; disable Enter Command Mode char
  1813.     xor    al,al
  1814.     int    bapiint
  1815.     mov    portval,offset port_ub ; set Network port data structure address
  1816.     mov    port_ub.portrdy,1    ; say the comms port is ready
  1817.     or    nettype,bapi        ; indentify network type
  1818.         mov     flags.comflg,'C'    ; set the comm port flag
  1819.     mov     pcnet,2            ; network is present and active
  1820.     clc                ; success
  1821.     ret
  1822. comsbap1:mov    ah,prstr
  1823.     mov    dx,offset nonetmsg    ; say no network
  1824.     int    dos
  1825. comsbap3:stc                ; say failure
  1826.     ret                ; end 3Com BAPI
  1827.  
  1828. comse:    mov    dx,offset ebiostab    ; table of EBIOS ports
  1829.     xor    bx,bx
  1830.     mov    ah,cmkey
  1831.     call    comnd
  1832.     jnc    comse1            ; nc = success
  1833.             ; failure is ok, fails for GETBAUD etc calling comstrt
  1834.     mov    bx,ebport        ; use current port
  1835.     inc    bx            ; here count from 1
  1836. comse1:    push    bx
  1837.     mov    ah,cmword        ; get a word (remote node name)
  1838.     mov    dx,offset decbuf    ; work buffer
  1839.     mov    word ptr decbuf,0    ; insert terminator
  1840.     mov    bx,offset ebhlp        ; help message
  1841.     call    comnd            ; get the name
  1842.     mov    ah,cmeol
  1843.     call    comnd            ; get a confirm
  1844.     pop    bx
  1845.     jnc    comse7
  1846.     ret                ; c = failure
  1847.  
  1848. comse7:    dec    bx            ; count from 0
  1849.     mov    ebport,bx        ; port number 0..3
  1850.     call    chkebios        ; EBIOS presence check
  1851.     jnc    comse7a            ; nc = success
  1852.     mov    inettyp,'E'        ; try NetBios directly (ABIOS)
  1853.     mov    al,decbuf        ; indicator of new host name
  1854.     mov    newnambuf,al        ; set for NetBios routine
  1855.     or    nettype,acsi        ; say doing special subset of NetBios
  1856.     jmp    comsn3            ; setup NetBios connection
  1857.  
  1858. comse7a:push    es
  1859.     mov    bx,ds
  1860.     mov    es,bx
  1861.     mov    bx,offset ebcoms    ; es:bx to ebcoms address
  1862.     mov    dx,ebport        ; port number
  1863.     mov    cx,51            ; number of bytes in ebcoms
  1864.     mov    ah,ebquery        ; get redirection table info
  1865.     int    rs232
  1866.     mov    ebcoms,0        ; query puts ebport in LANA, clear it
  1867.     cmp    decbuf,0        ; any new name given?
  1868.     je    comse4            ; e = no, presume name exists in EBIOS
  1869.     mov    si,offset decbuf    ; user input
  1870.     mov    di,offset ebcoms+2    ; where to store it
  1871.     mov    cx,16            ; 16 char NetBios name
  1872.     cld
  1873. comse2:    lodsb                ; get a new char
  1874.     or    al,al            ; null terminator?
  1875.     jnz    comse3            ; nz = no, use it
  1876.     mov    al,' '            ; replace with space
  1877.     rep    stosb            ; do remaining spots
  1878.     jmp    short comse3b        ; carry on when done
  1879. comse3:    stosb                ; store it
  1880.     loop    comse2
  1881.  
  1882. comse3b:call    setnbname        ; setup local Netbios name
  1883.     jc    comse4            ; c = failed
  1884.     mov    si,ds
  1885.     mov    es,si
  1886.     cld
  1887.     mov    ebcoms+2+16,0        ; no Listen required, just a Call
  1888.     mov    cx,8
  1889.     mov    si,offset deflname    ; our Netbios name
  1890.     mov    di,offset ebcoms+2+16+16
  1891.     rep    movsw
  1892. comse4:    mov    bx,offset ebcoms    ; es:bx to ebcoms structure
  1893.     mov    ebcoms+1,80h        ; force a network connection
  1894.     mov    ah,ebredir        ; do redirection
  1895.     xor    al,al
  1896.     mov    dx,ebport
  1897.     int    rs232
  1898.     pop    es
  1899.     or    ax,ax            ; status
  1900.     jz    comse5            ; z is success
  1901.  
  1902.     push    ax
  1903.     mov    ah,prstr
  1904.     mov    dx,offset ebmsg3    ; cannot open network
  1905.     int    dos
  1906.     pop    ax
  1907.     xchg    ah,al
  1908.     xor    ah,ah
  1909.     call    decout            ; show error value
  1910.     stc
  1911.     ret
  1912. comse5:    cmp    ebcoms+2,' '        ; do we have a name?
  1913.     ja    comse6            ; a = yes
  1914.     mov    ah,prstr
  1915.     mov    dx,offset ebmsg2    ; say bad command
  1916.     int    dos
  1917.     stc                ; fail
  1918.     ret
  1919. comse6:    call    serrst            ; reset previous port
  1920.     mov    bx,offset portb1    ; use Bios data structure
  1921.     mov    ax,type prtinfo        ; portinfo item size
  1922.     mov    cx,ebport        ; actual port (0..3)
  1923.     mul    cl            ; times port
  1924.     add    bx,ax            ; new portb<n> offset
  1925.     mov    portval,bx
  1926.     mov    [bx].portrdy,1        ; say the comms port is ready
  1927.     mov    [bx].sndproc,offset ebisnd ; send processor
  1928.     mov    [bx].rcvproc,offset ebircv ; receive processor
  1929.     mov    [bx].cloproc,offset ebiclose ; close processor
  1930.     or    nettype,ebios        ; indentify network type
  1931.     mov    flags.comflg,'E'    ; say EBIOS
  1932.     mov    pcnet,1
  1933.     clc                ; success
  1934.     ret
  1935. comsex:    mov    dx,offset nonetmsg    ; say network is not available
  1936.     mov    ah,prstr
  1937.     int    dos
  1938. comsex1:stc                ; failure
  1939.     ret
  1940.  
  1941. comstelapi:                ; Novell TELAPI
  1942.     mov    ah,cmword        ; get a word (remote node name)
  1943.     mov    dx,offset decbuf    ; work buffer
  1944.     mov    word ptr decbuf,0    ; insert terminator
  1945.     mov    bx,offset telhlp    ; help message
  1946.     call    comnd            ; get the name
  1947.     mov    ah,cmeol
  1948.     call    comnd            ; get a confirm
  1949.     jnc    comstel1        ; nc = ok so far
  1950.     ret                ; did not get a confirm
  1951. comstel1:cmp    decbuf,0        ; got new address?
  1952.     jne    comstel2        ; ne = yes
  1953.     cmp    word ptr internet,0    ; have we a previous address?
  1954.     jne    comstel6        ; ne = yes, use it instead
  1955.     jmp    short comstel5        ; no address, say illegal
  1956. comstel2:cmp    portin,0        ; inited port yet?
  1957.     jl    comstel8        ; l = no
  1958.     test    nettype,telapi        ; already doing TELAPI?
  1959.     jz    comstel7        ; z = no
  1960.     call    chknew            ; ask Resume or New
  1961.     jc    comstel6        ; c = Resume
  1962. comstel7:call    telapiclose        ; close that connection
  1963. comstel8:xor    bx,bx            ; convert Internet address to binary
  1964.     xor    dx,dx            ; Internet field in dl, as a temp
  1965.     mov    word ptr internet,dx    ; clear Internet address
  1966.     mov    word ptr internet+2,dx
  1967.     mov    si,offset decbuf    ; fresh text
  1968.     cld
  1969.  
  1970. comstel3:lodsb                ; get ascii digit
  1971.     cmp    al,'.'            ; separator?
  1972.     jne    comstel4        ; ne = no
  1973.     inc    bx            ; next field
  1974.     cmp    bx,3            ; beyond last field
  1975.     ja    comstel5        ; a = yes, error
  1976.     jmp    short comstel3
  1977. comstel4:or    al,al            ; end of information?
  1978.     jz    comstel6        ; z = yes
  1979.     sub    al,'0'            ; strip ascii bias
  1980.     cmp    al,9            ; in digits?
  1981.     ja    comstel5        ; a = no
  1982.     mov    dl,internet[bx]        ; current field
  1983.     xor    dh,dh
  1984.     shl    dx,1            ; times two
  1985.     push    dx            ; save
  1986.     shl    dx,1            ; times four
  1987.     shl    dx,1            ; times eight
  1988.     pop    cx            ; recover times two
  1989.     add    dx,cx            ; plus two = times ten
  1990.     add    al,dl            ; plus current digit
  1991.     mov    internet[bx],al        ; save value
  1992.     jmp    short comstel3        ; next character
  1993.  
  1994. comstel5:mov    ah,prstr        ; say bad address construction
  1995.     mov    dx,offset telmsg1
  1996.     int    dos
  1997.     mov    dx,offset decbuf    ; show address
  1998.     call    prtasz
  1999.     stc
  2000.     ret
  2001. comstel6:call    serrst            ; end previous async session
  2002.     mov    portval,offset port_ub    ; set Network port data structure addr
  2003.     or    nettype,telapi        ; indentify network type
  2004.         mov     flags.comflg,'T'    ; set the comm port flag
  2005.     clc
  2006.     ret
  2007.  
  2008. comstes1:mov    cx,0ffffh        ; old TES presence check
  2009.     mov    ah,tesinstal        ; installation/status check
  2010.     call    tes_service
  2011.     jc    comstes2        ; c = error of some kind
  2012.     cmp    ax,'TE'            ; signature
  2013.     jne    comstes2        ; ne = not present
  2014.     cmp    cx,0ffffh        ; should change too
  2015.     jne    comstes3        ; ne = present
  2016. comstes2:mov    ah,prstr
  2017.     mov    dx,offset nonetmsg    ; say no network
  2018.     int    dos
  2019.     stc                ; say failure
  2020.     ret
  2021. comstes3:mov    tesport,dx        ; remember TES intercepted port
  2022.     call    serrst            ; close current port
  2023.     mov    portval,offset port_tes ; set Network port data structure addr
  2024.     or    nettype,tes        ; indentify network type
  2025.         mov     flags.comflg,'I'    ; set the comm port flag
  2026.     mov    teslat,0        ; not LAT kind
  2027.     cmp    decbuf,'*'        ; was show-all entered?
  2028.     jne    comstes4        ; ne = no
  2029.     jmp    teshosts        ; show known TES hosts
  2030. comstes4:mov    ax,temp            ; length of entered name
  2031.     or    al,tesname        ; plus preexisting name, if any
  2032.     or    ax,ax            ; anything present?
  2033.     jz    comstes9        ; z = no name, find existing session
  2034.     cmp    decbuf,0        ; anything to copy?
  2035.     je    comstes5        ; e = no, use existing name
  2036.     call    tesclose        ; close existing connection
  2037.     or    nettype,tes        ; indentify network type
  2038.     mov    si,offset decbuf
  2039.     mov    di,offset tesname
  2040.     call    strcpy            ; copy node name
  2041. comstes5:clc
  2042.     ret
  2043.  
  2044. comstes9:mov    tesses,1        ; search for an active/held session
  2045. comstes10:call    tesstate        ; get state of that session to AH
  2046.     test    ah,2            ; active?
  2047.     jnz    comstes12        ; nz = yes, use it
  2048.     inc    tesses            ; next session
  2049.     cmp    tesses,9        ; done all?
  2050.     jbe    comstes10        ; be = no
  2051.     mov    tesses,1        ; try for a held session
  2052. comstes11:call    tesstate        ; get state of that session to AH
  2053.     test    ah,1            ; on hold?
  2054.     jnz    comstes12        ; nz = yes, use it
  2055.     inc    tesses            ; next session
  2056.     cmp    tesses,9        ; done all?
  2057.     jbe    comstes11        ; be = no
  2058.     mov    tesses,0        ; say no session
  2059.     mov    ah,prstr
  2060.     mov    dx,offset tesnhost    ; give directions
  2061.     int    dos
  2062.     call    teshosts        ; show known hosts
  2063. comstes12:ret
  2064.  
  2065.                     ; TCP/IP Telnet
  2066. comstn:    mov    ah,cmword        ; get a word (remote node name)
  2067.     mov    comand.cmblen,60    ; set 60 byte limit plus null
  2068.     mov    dx,offset decbuf+1    ; work buffer, 1st byte = count
  2069.     mov    word ptr decbuf,0    ; insert terminator
  2070.     mov    decbuf+80,0        ; byte count of args
  2071.     mov    bx,offset tcphlp    ; help message
  2072.     call    comnd            ; get the name
  2073.     jc    comstnx
  2074.     or    al,al            ; anything?
  2075.     jz    comstn1            ; z = no
  2076.     mov    decbuf,al        ; store byte count
  2077.  
  2078.     mov    ah,cmword        ; get optional Port number
  2079.     mov    comand.cmblen,7        ; set 7 byte limit plus null
  2080.     mov    dx,offset decbuf+82    ; far from real node names
  2081.     mov    decbuf+80,0        ; byte count of args
  2082.     mov    decbuf+81,'\'        ; \number prefix, just in case
  2083.     mov    word ptr decbuf+82,0    ; clear entry
  2084.     mov    bx,offset tcpporthlp
  2085.     call    comnd
  2086.     jc    comstnx
  2087.     mov    decbuf+80,al        ; store arg byte count
  2088. comstn1:mov    ah,cmeol
  2089.     call    comnd            ; get a confirm
  2090.     jnc    comstn2            ; nc = ok so far
  2091. comstnx:ret                ; did not get a confirm
  2092.  
  2093. comstn2:call    serrst            ; close current comms port
  2094.     mov    portin,0
  2095.     mov    flags.comflg,'t'    ; what we want, may not have yet
  2096.     call    sesmgr            ; SESSION MANAGER
  2097.     jnc    comstn3            ; nc = start a new session
  2098.     ret                ; resume existing session
  2099. comstn3:mov    si,offset decbuf+82    ; optional port number
  2100.     cmp    byte ptr [si-2],0    ; byte count, any port specified?
  2101.     je    comstn5            ; e = no, use default
  2102.     cmp    byte ptr [si],'\'    ; user specified leading backslash?
  2103.     je    comstn4            ; e = yes
  2104.     dec    si            ; then use ours
  2105. comstn4:call    katoi            ; convert si to number in ax
  2106.     or    ax,ax            ; any port specified
  2107.     jz    comstn5            ; z = no, use 23
  2108.     cmp    ax,25            ; this one?
  2109.     jne    comstn6            ; ne = no
  2110.     mov    ah,prstr
  2111.     mov    dx,offset badport    ; say bad port number
  2112.     int    dos
  2113. comstn5:mov    ax,23            ; use official Telnet port
  2114. comstn6:mov    bx,tcpdata+16        ; holds offset of tcpport
  2115.     mov    [bx],ax            ; copy new port
  2116.     mov    portval,offset port_tn    ; set Network port data structure addr
  2117.         mov     nsbrk,1                 ; network BREAK supported
  2118.     clc
  2119.     ret
  2120.                     ; Beame & Whiteside TCP/IP
  2121. comsbw:    mov    ah,cmword        ; get a word (remote node name)
  2122.     mov    dx,offset decbuf    ; work buffer
  2123.     mov    word ptr decbuf,0    ; insert terminator
  2124.     mov    bx,offset telhlp    ; help message
  2125.     call    comnd            ; get the name
  2126.     mov    ah,cmeol
  2127.     call    comnd            ; get a confirm
  2128.     jnc    comsbw1            ; nc = ok so far
  2129.     ret                ; did not get a confirm
  2130. comsbw1:cmp    decbuf,0        ; got new address?
  2131.     jne    comsbw2            ; ne = yes
  2132.     cmp    word ptr internet,0    ; have we a previous address?
  2133.     je    comsbw5            ; e = no address, say illegal
  2134.     jmp    comsbw6
  2135. comsbw2:cmp    portin,0        ; inited port yet?
  2136.     jl    comsbw8            ; l = no
  2137.     test    nettype,bwtcp        ; [JRS] already doing BWTCP?
  2138.     jz    comsbw7            ; [JRS] z = no
  2139.     call    chknew            ; ask Resume or New
  2140.     jnc    comsbw7            ; nc = New
  2141.     jmp    comsbw6
  2142. comsbw7:call    bwclose            ; close current connection
  2143. comsbw8:xor    bx,bx            ; convert Internet address to binary
  2144.     xor    dx,dx            ; Internet field in dx, as a temp
  2145.     mov    word ptr internet,dx    ; clear Internet address
  2146.     mov    word ptr internet+2,dx
  2147.     mov    si,offset decbuf    ; fresh text
  2148.     cld
  2149.     cmp    byte ptr [si],'*'    ; [JRS] telnet server mode?
  2150.     jnz    comsbw3            ; [JRS] nz = no, process IP address
  2151.     mov    word ptr internet,-1    ; [JRS] bogus IP for server mode
  2152.     mov    word ptr internet+2,-1    ; [JRS] bogus IP for server mode
  2153.  
  2154. comsbw6:call    serrst            ; end previous async session
  2155.     push    bx
  2156.     mov    bx,offset port_tn
  2157.     mov    portval,bx
  2158.     mov    [bx].sndproc,offset bwsend ; [JRS] BW send routine
  2159.     mov    [bx].rcvproc,offset bwrecv ; [JRS] BW Receive routine
  2160.     mov    [bx].cloproc,offset bwclose ; [JRS] BW Close routine
  2161.     pop    bx
  2162.     or    nettype,bwtcp        ; [JRS] set it to BW-TCP
  2163.         mov     flags.comflg,'b'    ; [JRS] set the comm port flag
  2164.     clc
  2165.     ret
  2166.  
  2167. comsbw3:lodsb                ; get ascii digit
  2168.     cmp    al,'.'            ; separator?
  2169.     jne    comsbw4            ; ne = no
  2170.     inc    bx            ; next field
  2171.     cmp    bx,3            ; beyond last field
  2172.     ja    comsbw5            ; a = yes, error
  2173.     jmp    short comsbw3
  2174. comsbw4:or    al,al            ; end of information?
  2175.     jz    comsbw6            ; z = yes
  2176.     sub    al,'0'            ; strip ascii bias
  2177.     cmp    al,9            ; in digits?
  2178.     ja    comsbw5            ; a = no
  2179.     mov    dl,internet[bx]        ; current field
  2180.     xor    dh,dh
  2181.     shl    dx,1            ; times two
  2182.     push    dx            ; save
  2183.     shl    dx,1            ; times four
  2184.     shl    dx,1            ; times eight
  2185.     pop    cx            ; recover times two
  2186.     add    dx,cx            ; plus two = times ten
  2187.     add    al,dl            ; plus current digit
  2188.     mov    internet[bx],al        ; save value
  2189.     jmp    short comsbw3        ; next character
  2190.  
  2191. comsbw5:mov    ah,prstr        ; say bad address construction
  2192.     mov    dx,offset telmsg1
  2193.     int    dos
  2194.     mov    dx,offset decbuf    ; show address
  2195.     call    prtasz
  2196.     stc
  2197.     ret
  2198. COMS    ENDP
  2199.  
  2200. teshosts proc    near            ; TES, show list of hosts
  2201.     mov    ah,prstr
  2202.     mov    dx,offset tesnlist    ; show list of hosts
  2203.     int    dos
  2204.     push    es
  2205.     push    si
  2206.     mov    ah,tesgets        ; get TES known servers
  2207.     call    tes_service        ; cx gets qty
  2208.     mov    dx,offset decbuf    ; work buffer
  2209.     mov    word ptr decbuf,'  '    ; item spacing
  2210.     xor    di,di            ; line length counter
  2211.     or    cx,cx            ; any servers?
  2212.     jnz    teshost1        ; nz = some servers
  2213.     inc    cx            ; say one for loop
  2214.     push    cx
  2215.     mov    word ptr decbuf+2,'ON'    ; prefill with NONE
  2216.     mov    word ptr decbuf+4,'EN'
  2217.     mov    decbuf+6,0        ; asciiz
  2218.     mov    cx,6            ; length of "  NONE"
  2219.     jmp    short teshost3        ; show NONE
  2220. teshost1:push    cx            ; count of servers
  2221.     push    si            ; save master list pointer
  2222.     push    di
  2223.     mov    si,es:[si]        ; get offset of first name
  2224.     mov    di,dx            ; decbuf
  2225.     add    di,2            ; move into decbuf+2
  2226. teshost2:mov    al,es:[si]        ; get name char
  2227.     inc    si
  2228.     mov    [di],al            ; store name char
  2229.     inc    di
  2230.     or    al,al            ; at end?
  2231.     jnz    teshost2        ; nz = no
  2232.     pop    di
  2233.     pop    si            ; master list of offsets
  2234.     add    si,2            ; next item in list
  2235.     call    strlen            ; get length of name w/spaces
  2236.     add    di,cx            ; length of display line with name
  2237.     cmp    di,60            ; time to break line?
  2238.     jbe    teshost3        ; be = no
  2239.     push    dx
  2240.     mov    ah,prstr        ; break the screen line
  2241.     mov    dx,offset crlf
  2242.     int    dos
  2243.     pop    dx
  2244.     xor    di,di            ; say line is empty
  2245. teshost3:add    di,cx            ; current line length
  2246.     call    prtasz            ; show asciiz text at ds:dx
  2247.     pop    cx
  2248.     loop    teshost1        ; do all entries
  2249.     pop    si
  2250.     pop    es
  2251.     ret
  2252. teshosts endp
  2253.  
  2254. ; Perform TES function given in AH, but tell cmd interpreter to not prompt.
  2255. tes_service     proc    near
  2256.         push    ax
  2257.         push    si
  2258.         push    es
  2259.         mov     ax,ds
  2260.         mov     es,ax
  2261.     mov    si,offset tesquiet    ; cmd to say no prompting
  2262.     xor    al,al            ; no visible response please
  2263.     mov    ah,tesexec
  2264.         int     rs232
  2265.         pop     es
  2266.         pop     si
  2267.         pop     ax
  2268.     push    ds            ; prevent corruption by TES
  2269.         int     rs232            ; do the main request
  2270.     pop    ds
  2271.         ret
  2272. tes_service     endp
  2273.  
  2274. ; TES - start or resume a TES connection
  2275. tesstrt    proc    near
  2276.     cmp    tesses,0        ; session yet?
  2277.     jne    tesstr2            ; ne = yes
  2278.     cmp    tesname,0        ; have a node name?
  2279.     jne    tesstr1            ; ne = yes
  2280.     jmp    tesstr4            ; find an existing connection, if any
  2281.  
  2282. tesstr1:push    si
  2283.     mov    si,offset tesname    ; node name
  2284.     mov    ah,tesnews        ; make a new session
  2285.     call    tes_service
  2286.     pop    si
  2287.      jmp    short tesstr4        ; double check on transistions
  2288.  
  2289.                     ; have a session, live or held
  2290. tesstr2:call    tesstate        ; get session status
  2291.     test    ah,2            ; active or being made so?
  2292.     jnz    tesstr3            ; nz = yes, connect to it
  2293.     test    ah,1            ; session on hold or being made so?
  2294.     jz    tesstr1            ; z = no, make a new one
  2295.     mov    ah,tesresume        ; resume a session
  2296.     mov    al,tesses        ; the session number
  2297.     call    tes_service
  2298.     shl    ah,1            ; get status into carry bit
  2299.     jc    tesstr4            ; c = problem, try to recover
  2300.  
  2301. tesstr3:cmp    tesname,0        ; have name yet?
  2302.     je    tesstr4            ; e = no, get it now
  2303.     mov    pcnet,2            ; have an active session
  2304.     mov    port_tes.portrdy,1    ; say port is ready
  2305.     clc
  2306.     ret
  2307.  
  2308. tesstr4:push    si            ; find an active session number
  2309.     push    es
  2310.     mov    temp,0            ; retry counter
  2311.     mov    tesses,1        ; session number
  2312. tesstr5:mov    ah,teslist        ; get TES session pointers
  2313.     call    tes_service        ; CX gets quantity of ACTIVE sessions
  2314. tesstr6:mov    al,es:[si]        ; get session status
  2315.     cmp    al,82h            ; making a session now?
  2316.     je    tesstr7            ; e = yes, good enough
  2317.     test    al,80h            ; in transitional status?
  2318.     jz    tesstr6b        ; z = no
  2319.     mov    ah,100
  2320.     call    pcwait            ; wait 100 ms
  2321.     inc    temp
  2322.     cmp    temp,10
  2323.     ja    tesstr6a        ; a = too many retries, quit
  2324.     jmp    short tesstr5        ; nz = yes, go around again
  2325. tesstr6b:mov    temp,0            ; clear retry counter
  2326.     test    al,2            ; 0=inactive, 1=on hold, 2=active?
  2327.     jnz    tesstr7            ; nz = active
  2328.     add    si,3            ; skip status byte, name offset
  2329.     inc    tesses            ; bump session number
  2330.     cmp    tesses,9        ; done all?
  2331.     jbe    tesstr6            ; be = no
  2332. tesstr6a:mov    tesses,0        ; no active session
  2333.     mov    port_tes.portrdy,0    ; say the comms port is not ready
  2334.     mov     pcnet,1            ; network is present and inactive
  2335.     stc                ; signal failure
  2336.     jmp    short tesstr8
  2337.                     ; set port ready, get host name
  2338. tesstr7:mov    port_tes.portrdy,1    ; say the comms port is ready
  2339.     mov     pcnet,2            ; network is present and active
  2340.     mov    di,offset tesname    ; readback asciiz name
  2341.     mov    byte ptr [di],0        ; clear the name field
  2342.     mov    si,es:[si+1]        ; get name ptr offset
  2343.     or    si,si            ; check for null pointer
  2344.     jz    tesstr6a        ; z = no name, dead session
  2345.     mov    cx,49            ; limit to 48 chars plus null
  2346. tesstr7a:mov    al,es:[si]        ; get a char
  2347.     inc    si
  2348.     mov    [di],al            ; store
  2349.     inc    di
  2350.     or    al,al            ; null?
  2351.     jz    tesstr7b        ; z = yes, stop here
  2352.     loop    tesstr7a        ; keep going
  2353. tesstr7b:clc                ; signal success
  2354. tesstr8:pop    es
  2355.     pop    si
  2356.     ret
  2357. tesstrt    endp
  2358.  
  2359. ; TES. Return session status in AH for session in tesses. Destroys AX
  2360. tesstate proc    near
  2361.     push    cx
  2362.     push    si
  2363.     push    es
  2364.     mov    ah,teslist        ; get session list
  2365.     call    tes_service
  2366.     mov    ah,0ffh            ; set up no session status
  2367.     mov    al,tesses        ; our session number, 1..9
  2368.     dec    al            ; base on zero here
  2369.     mov    ah,al
  2370.     shl    ah,1
  2371.     add    al,ah
  2372.     xor    ah,ah            ; times three
  2373.     add    si,ax            ; point to session structure es:[si]
  2374.     mov    ah,es:[si]        ; get session status byte
  2375. testat1:pop    es
  2376.     pop    si
  2377.     pop    cx
  2378.     ret
  2379. tesstate endp
  2380.  
  2381. ; Start Novell TELAPI session. Internet address is already binary
  2382. telstrt    proc    near
  2383.     mov    dx,word ptr internet    ; internet address, high part
  2384.     mov    cx,word ptr internet+2
  2385.     mov    bx,telport        ; Telnet port (23 decimal)
  2386.     push    es
  2387.     push    si
  2388.     xor    si,si            ; use TELAPI data structures, not ours
  2389.     mov    es,si            ; es:si = Telnet state record, theirs
  2390.     mov    di,offset telhostid    ; two byte host identifier in ds:di
  2391.     mov    ah,telopen        ; open the connection
  2392.     int    rs232
  2393.     mov    telses,ax        ; save TELAPI session number
  2394.     pop    si
  2395.     pop    es
  2396.     or    ax,ax            ; get status returned in AX
  2397.     jns    telstr1            ; ns = success
  2398.     cmp    ax,telinuse        ; socket is already connected? (-56)
  2399.      jne    telstr2            ; ne = no, else attach to it
  2400. telstr1:mov    port_ub.portrdy,1    ; say the comms port is ready
  2401.     mov     pcnet,2            ; network is present and active
  2402.     or    nettype,telapi
  2403.     clc
  2404.     ret
  2405.                     ; failure message display section
  2406. telstr2:mov    dx,offset telmsg51    ; network unreachable
  2407.     cmp    ax,telunreac        ; correct?
  2408.     je    telstr3            ; e = yes
  2409.     mov    dx,offset telmsg56    ; socket in use
  2410.     cmp    ax,telinuse
  2411.     je    telstr3
  2412.     mov    dx,offset telmsg60    ; timeout on connection attempt
  2413.     cmp    ax,teltmo
  2414.     je    telstr3
  2415.     mov    dx,offset telmsg61    ; connection refused
  2416.     cmp    ax,telrefuse
  2417.     je    telstr3
  2418.     mov    dx,offset telmsg64    ; host is down
  2419.     cmp    ax,teldwnhost
  2420.     je    telstr3
  2421.     mov    dx,offset telmsg67    ; unknown host
  2422.     cmp    ax,telunkhost
  2423.     je    telstr3
  2424.     mov    dx,offset telmsg301    ; no more space
  2425.     cmp    ax,telfull
  2426.     je    telstr3
  2427.     push    ax            ; unknown error, show error value
  2428.     mov    dx,offset telmsg2
  2429.     mov    ah,prstr
  2430.     int    dos
  2431.     pop    ax
  2432.     neg    ax            ; make positive number again
  2433.     call    decout            ; show error value, for now
  2434.     jmp    short telstr4
  2435. telstr3:mov    ah,prstr
  2436.     int    dos            ; show reason msg
  2437. telstr4:mov    ax,3000            ; show for three seconds
  2438.     call    pcwait
  2439.     mov    port_ub.portrdy,0    ; say port is not ready
  2440.     stc                ; fail
  2441.     ret
  2442. telstrt    endp
  2443.  
  2444. ; Start Beame & Whiteside TCP connecton.  IP address is already binary [JRS]
  2445. bwstart    proc    near            ; [JRS]
  2446.     push    bx            ; [JRS]
  2447.     push    cx            ; [JRS]
  2448.     push    dx            ; [JRS]
  2449.     mov    bx,bwhandle        ; [JRS] check the file handle
  2450.     or    bx,bx            ; [JRS] non-zero is open
  2451.     jnz    bwstrt1            ; [JRS] nz = yes, just continue
  2452.  
  2453.     mov    ax,3d42h        ; [JRS] open file shared read/write
  2454.     mov    dx,offset bwtcpnam    ; [JRS] "TCP-IP10"
  2455.     int    dos
  2456.     jc    bwstrt2            ; c = failed
  2457.     mov    bwhandle,ax        ; [JRS] save file handle
  2458.     mov    bx,ax            ; [JRS] copy handle
  2459.     mov    ax,4401h        ; [JRS] io/ctl - set dev info
  2460.     xor    cx,cx            ; [JRS]
  2461.     mov    dx,60h            ; [JRS] data is raw
  2462.     int    dos            ; [JRS]
  2463.     jc    bwstrt2            ; c = failed
  2464.     mov    xmtbuf,0        ; [JRS] set up port bind address
  2465.     push    es
  2466.     mov    ax,40h            ; Bios work area
  2467.     mov    es,ax
  2468.     mov    ax,es:[6ch]        ; low word of Bios tod tics
  2469.     pop    es
  2470.     mov    word ptr xmtbuf+1,ax    ; local port
  2471.     mov    ax,4403h        ; [JRS] write to device
  2472.     mov    bx,bwhandle        ; [JRS] device handle
  2473.     mov    cx,3            ; [JRS] length of data
  2474.     mov    dx,offset xmtbuf    ; [JRS] data buffer
  2475.     int    dos            ; [JRS]
  2476.     jc    bwstrt2            ; c = failed
  2477.  
  2478.     mov    xmtbuf,1        ; [JRS] set up IP bind address
  2479.     mov    dx,word ptr internet    ; [JRS] internet address, high part
  2480.     mov    cx,word ptr internet+2    ; [JRS]
  2481.     cmp    dx,-1            ; [JRS] check for server addr -1
  2482.     jz    bwaccept        ; [JRS] z = -1, do accept processing
  2483.  
  2484.     mov    word ptr xmtbuf+1,dx    ; [JRS] store address in buffer
  2485.     mov    word ptr xmtbuf+3,cx    ; [JRS]
  2486.     mov    xmtbuf+5,23        ; [JRS] telnet port (23)
  2487.     mov    xmtbuf+6,0        ; [JRS] high byte
  2488.     mov    ax,4403h        ; [JRS] write to device
  2489.     mov    bx,bwhandle        ; [JRS]
  2490.     mov    cx,7            ; [JRS]
  2491.     mov    dx,offset xmtbuf    ; [JRS]
  2492.     int    dos            ; [JRS]
  2493.     jc    bwstrt2            ; c = failed
  2494.  
  2495. bwstrt0:mov    xmtbuf,6        ; [JRS] set up for no read blocking
  2496.     mov    xmtbuf+1,1        ; [JRS]    control string is \6\1
  2497.     mov    ax,4403h        ; [JRS] write to device
  2498.     mov    bx,bwhandle        ; [JRS]
  2499.     mov    cx,2            ; [JRS]
  2500.     mov    dx,offset xmtbuf    ; [JRS]
  2501.     int    dos            ; [JRS]
  2502.     jc    bwstrt2            ; c = failed
  2503.  
  2504. bwstrt1:pop    dx            ; [JRS] restore registers
  2505.     pop    cx            ; [JRS]
  2506.     pop    bx            ; [JRS]
  2507.     mov    port_tn.portrdy,1    ; [JRS] say the comms port is ready
  2508.     mov     pcnet,2            ; [JRS] network is present and active
  2509.     or    nettype,bwtcp        ; [JRS]
  2510.     mov    optstate,0        ; init Options
  2511.     mov    sgaflg,0        ; assume supresss go aheads in effect
  2512.     mov    option2,TELOPT_SGA
  2513.     mov    ah,DO
  2514.     call    bwsendiac        ; say do supress go aheads
  2515.     clc
  2516.     ret
  2517. bwstrt2:call    bwclose            ; [JRS] failure, close "file"
  2518.     pop    dx            ; [JRS]
  2519.     pop    cx            ; [JRS]
  2520.     pop    bx            ; [JRS]
  2521.     stc                ; c = failed
  2522.     ret
  2523.  
  2524. bwaccept:mov    xmtbuf,2        ; [JRS] set port to accept calls
  2525.     mov    ax,4403h        ; [JRS] write to device
  2526.     mov    bx,bwhandle        ; [JRS]
  2527.     mov    cx,1            ; [JRS]
  2528.     mov    dx,offset xmtbuf    ; [JRS]
  2529.     int    dos            ; [JRS]
  2530.     mov    ax,4402h        ; [JRS] read from device
  2531.     mov    bx,bwhandle        ; [JRS] device handle
  2532.     mov    cx,11            ; [JRS] buffer length
  2533.     mov    dx,offset xmtbuf    ; [JRS] buffer
  2534.     int    dos            ; [JRS]
  2535. bwacpt1:cmp    xmtbuf,4        ; [JRS] check response 0 < xmtbuf < 4
  2536.     jge    bwacpt2            ; [JRS]    complete
  2537.     cmp    xmtbuf,0        ; [JRS]
  2538.     je    bwacpt2            ; [JRS]
  2539.                     ; [JRS] waiting for a connection
  2540.     mov    ax,4402h        ; [JRS] read from device
  2541.     mov    bx,bwhandle        ; [JRS]
  2542.     mov    cx,11            ; [JRS]
  2543.     mov    dx,offset xmtbuf    ; [JRS]
  2544.     int    dos            ; [JRS]
  2545.     jmp    short bwacpt1        ; [JRS] got look at response
  2546. bwacpt2:cmp    xmtbuf,0        ; [JRS] check for response of zero
  2547.     je    bwstrt2            ; [JRS] e=yes, fail
  2548.     jmp    bwstrt0            ; [JRS] success, we have a call
  2549. bwstart    endp                ; [JRS]
  2550. code    ends
  2551.  
  2552. code1    segment
  2553.     assume    cs:code1
  2554.  
  2555. ; Check for presence of DECNET. Host name is in latservice.
  2556. ; Try LAT then try CTERM. Sets nettype for kind found.
  2557. ; Return carry clear if success, or carry set if failure.
  2558. chkdec    proc    FAR
  2559.     cmp    pcnet,2            ; net active now?
  2560.     jb    chkde2            ; b = no
  2561.     cmp    lathand,0        ; valid LAT handle?
  2562.     jne    chkde1            ; ne = yes
  2563.     cmp    decneth,0        ; valid LAT handle?
  2564.     je    chkde2            ; e = invalid handle
  2565. chkde1:    clc
  2566.     ret                ; return to active session
  2567.  
  2568. chkde2:    push    es
  2569.     and    nettype,not (declat+decnet) ; clear network type bits
  2570.     cmp    teslat,0        ; TESLAT?
  2571.     jne    chkde2a            ; ne = yes
  2572.     mov    latversion,2        ; assume version 2
  2573.     mov    ah,35h            ; get interrupt vector
  2574.     mov    al,6eh            ; DNP sockets interrupt 6Eh
  2575.     int    dos
  2576.     cmp    word ptr es:[bx-3],'ND'    ; look for "DNP" signature
  2577.     jne    chkde4            ; ne = uh oh, something is wrong
  2578.     mov    al,es:[bx-5]        ; major version number
  2579.     mov    latversion,al        ; save as LAT version too
  2580. chkde2a:call    chklat            ; check for LAT
  2581.     jc    chkde3            ; c = not present
  2582.     mov    latversion,2        ; Force this since v4 is broken
  2583.     cmp    teslat,0        ; TESLAT?
  2584.     je    chkde3            ; e = no
  2585.     mov    latversion,3        ; version 3 for TESLAT
  2586.     jmp    short chkde4
  2587.                     ; now do CTERM too
  2588. chkde3:    mov    al,decint        ; CTERM interrupt 69h
  2589.     mov    ah,35h            ; get vector to es:bx
  2590.     int    dos
  2591.     mov    ax,es
  2592.     or    ax,ax            ; undefined interrupt?
  2593.     jz    chkde4            ; z = yes
  2594.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  2595.     je    chkde4            ; e = yes
  2596.     mov    ax,dpresent        ; CTERM installation call
  2597.     int    decint
  2598.     cmp    al,0ffh            ; CTERM installed?
  2599.     jne    chkde4            ; ne = no
  2600.     or    nettype,decnet        ; kind of network is CTERM
  2601. chkde4:    pop    es
  2602.     test    nettype,declat+decnet    ; any DEC network found?
  2603.     jz    chkde5            ; z = no
  2604.     clc                ; clear means yes
  2605.     ret
  2606. chkde5:    stc                ; status is no net
  2607.     ret
  2608. chkdec    endp
  2609.  
  2610. ; Check for LAT interrupt vector, return carry clear if found else carry set.
  2611. chklat    proc    near
  2612.     push    es
  2613.     mov    al,latint        ; LAT interrupt 6Ah
  2614.     mov    ah,35h            ; get vector to es:bx
  2615.     int    dos
  2616.     mov    ax,es
  2617.     or    ax,ax            ; undefined interrupt?
  2618.     jz    chklat1            ; z = yes
  2619.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  2620.     je    chklat1            ; e = yes, not installed
  2621.     cmp    word ptr es:[bx-3],'AL'    ; preceeding 3 bytes spell 'LAT'?
  2622.     jne    chklat1            ; ne = no, so no LAT, try CTERM
  2623.     cmp    byte ptr es:[bx-1],'T'
  2624.     jne    chklat1            ; ne = no, fail
  2625.     or    nettype,declat        ; kind of network is LAT
  2626.     pop    es
  2627.     clc                ; success
  2628.     ret
  2629. chklat1:pop    es
  2630.     stc                ; say failure
  2631.     ret
  2632. chklat    endp
  2633.  
  2634. ; Start DECNET link. Host name is in latservice, nettype has LAT or CTERM
  2635. ; kind bits. Return carry clear if success, or carry set if failure.
  2636. decstrt    proc    FAR
  2637.     cmp    pcnet,2            ; net active now?
  2638.     jb    decst2            ; b = no
  2639.     cmp    lathand,0        ; invalid LAT handle?
  2640.     jne    decst1            ; ne = no, have a connection
  2641.     cmp    decneth,0        ; invalid CTERM handle?
  2642.     je    decst2            ; e = yes, start the net
  2643. decst1:    mov    port_dec.portrdy,1    ; say the comms port is ready
  2644.     cmp    teslat,0        ; TES-LAT?
  2645.     je    decst1a            ; e = no
  2646.     mov    flags.comflg,'I'    ; TES-LAT
  2647.     clc
  2648.     ret
  2649. decst1a:mov     flags.comflg,'D'    ; set the comm port flag
  2650.     clc
  2651.     ret                ; return to active session
  2652.  
  2653. decst2:    push    es            ; used a lot here
  2654.     call    chkdec            ; get net type
  2655.     jnc    decst3            ; nc = have a CTERM or LAT kind
  2656.     jmp    decst16            ; c = net not found
  2657.  
  2658. decst3:    cmp    latservice,0        ; node name present?
  2659.     jne    decst4            ; ne = yes
  2660.     mov    ah,prstr
  2661.     mov    dx,offset noname    ; say host name is required
  2662.     int    dos
  2663.     pop    es
  2664.     stc                ; fail
  2665.     ret
  2666.  
  2667. decst4:    test    nettype,declat        ; LAT is available?
  2668.     jnz    decst6            ; nz = yes
  2669.     jmp    decst13            ; z = no, try CTERM
  2670.  
  2671. decst6:    cmp    word ptr latscbptr+2,0    ; any segment allocated now?
  2672.     jne    decst8            ; ne = yes, do not malloc one here
  2673. ;    cmp    tv_mode,0        ; running under Windows or DV?
  2674. ;    je    decst6a            ; e = no, ok to try local SCB
  2675. ;    jmp    decst12b        ; can't use local so no LAT today
  2676. decst6a:mov    bx,870+15        ; size of LAT SCB, bytes, rounded up
  2677.     mov    cl,4
  2678.     shr    bx,cl            ; bytes to paragraphs
  2679.     mov    temp,bx            ; save requested paragraphs
  2680.     mov    ah,alloc        ; allocate memory, ax gets segment
  2681.     int    dos            ; bx gets # paragraphs allocated
  2682.     jnc    decst7            ; nc = success
  2683.     jmp    decst13            ; fail, go try CTERM
  2684. decst7:    mov    latseg,ax
  2685.     mov    word ptr latscbptr+2,ax    ; remember seg of SCB
  2686.     mov    word ptr latscbptr+10,ax ; and on the "To:" side as well
  2687.     mov    es,ax
  2688.     xor    di,di            ; es:di is destination
  2689.     xor    ax,ax            ; get word of zeros
  2690.     mov    word ptr latscbptr+0,ax    ; remember offset (0) of SCB
  2691.     mov    word ptr latscbptr+8,ax    ;  as above
  2692.     mov    cx,bx            ; paragraphs obtained
  2693.     shl    cx,1
  2694.     shl    cx,1
  2695.     shl    cx,1            ; words
  2696.     cld
  2697.     rep    stosw            ; clear the SCB
  2698.     cmp    temp,bx            ; wanted vs allocated (bx) paragraphs
  2699.     jbe    decst5            ; be = enough, setup structure
  2700.     jmp    decst12            ; deallocate memory and try CTERM
  2701.  
  2702. decst5:    and    nettype,not declat    ; presume failure
  2703.     cmp    latversion,4        ; version 4?
  2704.     jb    decst8            ; b = no, earlier, do our own SCB
  2705.     mov    ax,latscbget        ; get LAT interior SCB addr to es:bx
  2706.     mov    dh,0ffh
  2707.     int    latint
  2708.     or    ah,ah            ; success?
  2709.     jnz    decst8            ; nz = no
  2710.     mov    ax,es
  2711.     mov    word ptr latscbptr+6,ax    ; address of SCB within LAT
  2712.     mov    word ptr latscbptr+4,bx ;  seg part
  2713.     call    decfems            ; copy EMS SCB to local SCB
  2714.     jmp    short decst9        ; fill in local info
  2715.  
  2716. decst8:    les    bx,latscbptr        ; allocate data buffers locally
  2717.     mov    es:[bx].slottbl,slotbf1    ; offset of first buffer
  2718.     mov    es:[bx].slottbl+2,slotbf2 ; offset of second buffer
  2719.     mov    es:[bx].slotqty,2    ; say two buffers
  2720.  
  2721. decst9:    les    di,latscbptr        ; set es:di to local scb
  2722.     mov    si,offset latservice    ; get host name
  2723.     mov    cx,17            ; 17 bytes
  2724.     cld
  2725.     rep    movsb            ; insert host name
  2726.     mov    ax,latopen        ; open a LAT session
  2727.     mov    di,offset latpwd    ; es:di optional asciiz LAT password
  2728.     cmp    byte ptr [di],0        ; any name entered?
  2729.     je    decst10            ; e = no
  2730.     and    al,0fh            ; open as AX = 0d0fh if with password
  2731. decst10:mov    bx,word ptr latscbptr    ; open needs es:bx == SCB
  2732.     cmp    latversion,4        ; LAT version 4?
  2733.     jb    decst11            ; b = no, use version 2
  2734.     mov    al,1            ; v4 form
  2735.     push    ax
  2736.     mov    cx,ds
  2737.     mov    word ptr es:[bx].lat_pwd+2,cx ; set the pointer segment
  2738.     mov    word ptr es:[bx].lat_pwd,di  ; address of the password buffer
  2739.     mov    dx,di
  2740.     call    fstrlen            ; password string length to cx
  2741.     mov    es:[bx].pwd_len,cl    ; length of the password
  2742.     or    cx,cx            ; is there a password?
  2743.     jnz    decst10a        ; nz = yes
  2744.     mov    word ptr es:[bx].lat_pwd,cx ; no, clear fields
  2745.     mov    word ptr es:[bx].lat_pwd+2,cx
  2746.     mov    byte ptr es:[bx].pwd_len,cl
  2747. decst10a:call    dec2ems            ; copy local SCB to one in EMS
  2748.     pop    ax
  2749.  
  2750. decst11:mov    dh,0ffh
  2751.     int    latint
  2752.     or    ah,ah            ; status byte
  2753.     jnz    decst12            ; nz = failure, clean up, try CTERM
  2754.     mov    dh,0ffh
  2755.     mov    lathand,dx        ; handle returned in dl, 0ffh in dh
  2756.     or    nettype,declat        ; say LAT session is active
  2757.     jmp    decst17            ; finish startup info
  2758.                     ; LAT startup failure
  2759. decst12:mov    ax,latseg        ; stored segment of memory block
  2760.     or    ax,ax            ; did we use it?
  2761.     jz    decst12a        ; z = no
  2762.     mov    es,ax            ; allocated segment, unneed now
  2763.     mov    ah,freemem        ; free it again
  2764.     int    dos
  2765.     jmp    short decst12b        ; clear pointers
  2766. decst12a:cmp    word ptr latscbptr+2,0    ; in use as LAT internal perhaps?
  2767.     je    decst12b        ; e = no
  2768.     les    bx,latscbptr
  2769.     mov    ax,latscbfree        ; free SCB internal to LAT
  2770.     int    latint
  2771. decst12b:xor    ax,ax
  2772.     mov    latseg,ax        ; say not used
  2773.     mov    lathand,ax        ; invalidate the handle
  2774.     mov    word ptr latscbptr+0,ax    ; clear SCB pointer
  2775.     mov    word ptr latscbptr+2,ax
  2776.     and    nettype,not declat    ; fall through to try CTERM
  2777.  
  2778. decst13:test    nettype,decnet        ; is CTERM available?
  2779.     jz    decst16            ; z = no
  2780.     and    nettype,not decnet    ; presume failure
  2781.     mov    ax,decseg        ; scb memory segment, if non-zero
  2782.     or    ax,ax            ; allocated already?
  2783.     jnz    decst14            ; nz = yes, segment is in ax
  2784.     mov    ax,dgetscb        ; get CTERM SCB size
  2785.     int    decint
  2786.     add    ax,15            ; round up byte count
  2787.     mov    cl,4
  2788.     shr    ax,cl            ; bytes to paragraphs
  2789.     mov    bx,ax
  2790.     mov    temp,ax            ; save requested paragraphs
  2791.     mov    ah,alloc        ; allocate memory
  2792.     int    dos            ; bx gets # paragraphs allocated
  2793.     jc    decst16            ; c = failure
  2794.     mov    decseg,ax        ; store address of memory block
  2795.     cmp    temp,bx            ; wanted vs allocated paragraphs
  2796.     jb    decst15            ; b = not enough, fail
  2797.  
  2798. decst14:mov    bx,offset latservice    ; ds:bx = node name
  2799.     mov    es,ax            ; ax holds scb segment
  2800.     xor    dx,dx            ; es:dx = SCB address
  2801.     mov    ax,dopen        ; open session
  2802.     int    decint
  2803.     cmp    ax,0            ; > 0 means session handle, else error
  2804.     jle    decst15            ; le = error
  2805.     mov    decneth,ax        ; store handle
  2806.     or    nettype,decnet        ; network type is DECnet
  2807.     jmp    short decst17        ; success
  2808.                     ; CTERM startup failure
  2809. decst15:push    ax            ; save error number in ax
  2810.     mov    ax,decseg        ; allocated memory segment
  2811.     mov    es,ax
  2812.     mov    ah,freemem        ; free allocated memory segment @ES
  2813.     int    dos            ; free the block
  2814.     mov    decseg,0        ; clear remembered segment address
  2815.     mov    ah,prstr
  2816.     mov    dx,offset decmsg1    ; cannot create session
  2817.     int    dos
  2818.     mov    dx,offset decmsg3    ; DEC Error #
  2819.     int    dos
  2820.     pop    ax            ; recover error number (negative)
  2821.     neg    ax
  2822.     call    fdecout            ; error number
  2823.     mov    decneth,0        ; invalidate the handle
  2824.     and    nettype,not decnet
  2825.  
  2826. decst16:mov    pcnet,0            ; no net
  2827.     mov    port_dec.portrdy,0    ; port is not ready
  2828.     pop    es
  2829.     stc                ; status is error
  2830.     ret
  2831.                     ; LAT or CTERM success
  2832. decst17:mov    pcnet,2            ; say net is present and active
  2833.     cmp    teslat,0        ; TES-LAT?
  2834.     je    decst18            ; e = no
  2835.     mov    flags.comflg,'I'    ; TES-LAT
  2836.     jmp    short decst19
  2837. decst18:mov     flags.comflg,'D'    ; set the comm port flag
  2838. decst19:mov    port_dec.portrdy,1    ; say the comms port is ready
  2839.     mov    ax,100            ; wait 100 ms for DECnet to get ready
  2840.     call    fpcwait            ; FAR call
  2841.     pop    es
  2842.     clc
  2843.     ret
  2844. decstrt    endp
  2845.  
  2846. ; Copy LAT scb from local SCB to one in EMS
  2847. dec2ems    proc    near
  2848.     cmp    latversion,4        ; version 4?
  2849.     jb    dec2emsx        ; b = no, earlier, do our own SCB
  2850.     push    ax
  2851.     push    bx
  2852.     push    cx
  2853.     push    dx
  2854.     push    es
  2855.     mov    ax,ds            ; seg where latscbptr is located
  2856.     mov    es,ax            ; to es:bx
  2857.     mov    bx,offset latscbptr
  2858.     mov    ax,latcpyems        ; copy from local to EMS
  2859.     mov    dh,0ffh            ; signature
  2860.     mov    cx,870            ; size of LAT structure
  2861.     int    latint            ; copy local LAT info to EMS version
  2862.     pop    es
  2863.     pop    dx
  2864.     pop    cx
  2865.     pop    bx
  2866.     pop    ax
  2867. dec2emsx:ret
  2868. dec2ems    endp
  2869.  
  2870. ; Copy LAT SCB from EMS to local SCB
  2871. decfems    proc    near
  2872.     cmp    latversion,4        ; version 4?
  2873.     jb    decfemsx        ; b = no, earlier, do our own SCB
  2874.     push    ax
  2875.     push    bx
  2876.     push    cx
  2877.     push    dx
  2878.     push    es
  2879.     mov    ax,ds            ; seg where latscbptr is located
  2880.     mov    es,ax            ; to es:bx
  2881.     mov    bx,offset latscbptr+4    ;local(0),LAT(4),local(8) in latscbptr
  2882.     mov    ax,latcpyems        ; copy from EMS to local
  2883.     mov    dh,0ffh            ; signature
  2884.     mov    cx,870            ; size of LAT structure
  2885.     int    latint
  2886.     pop    es
  2887.     pop    dx
  2888.     pop    cx
  2889.     pop    bx
  2890.     pop    ax
  2891. decfemsx:ret
  2892. decfems    endp
  2893. code1    ends
  2894.  
  2895. code    segment
  2896.     assume    cs:code
  2897.  
  2898. ; Display list of LAT service names. Presumes LAT presence checks have passed
  2899. latlst    proc    near
  2900.     push    es
  2901.     push    bx
  2902.     mov    ah,prstr
  2903.     mov    dx,offset dnetsrv    ; header
  2904.     int    dos
  2905.     push    ds
  2906.     pop    es
  2907.     mov    si,2            ; chars in line counter
  2908. latlst1:mov    bx,offset decbuf+2     ; es:bx = temp buffer for a name
  2909.     mov    word ptr [bx-2],'  '    ; indent
  2910.     mov    byte ptr [bx],0        ; and a null terminator
  2911.     mov    ax,latsrv        ; get next LAT service name
  2912.     mov    dh,0ffh
  2913.     int    latint
  2914.     or    ah,ah            ; check status
  2915.     jnz    latlst2            ; nz = done (no more names)
  2916.     mov    dx,offset decbuf    ; name ptr is in es:bx (our buffer)
  2917.     call    prtasz            ; show asciiz name
  2918.     call    strlen            ; get current length
  2919.     add    si,cx            ; count chars on this line
  2920.     cmp    si,60            ; enough on line already?
  2921.     jbe    latlst1            ; be = no
  2922.     mov    ah,prstr        ; break the screen line
  2923.     mov    dx,offset crlf
  2924.     int    dos
  2925.     mov    si,2            ; reset line count
  2926.     jmp    short latlst1        ; do it again
  2927. latlst2:pop    bx
  2928.     pop    es
  2929.     ret
  2930. latlst    endp
  2931.  
  2932. ; Check which Interrupt ReQuest line the port uses. Technique: allow interrupt
  2933. ; on transmitter holding register empty, test for that condition first with
  2934. ; IRQ 4 and then IRQ 3. Returns with IRQ values set and carry clear if success
  2935. ; or carry set if failure. [jrd]
  2936. chkint    proc    near
  2937.     call    serrst
  2938.     mov    bl,flags.comflg        ; port 1..4
  2939.     dec    bl
  2940.     xor    bh,bh
  2941.     mov    al,portirq[bx]        ; pre-specified IRQ, if any
  2942.     or    al,al            ; IRQ specified already?
  2943.     jnz    chkint20        ; nz = yes
  2944. chkint10:test    flags.comflg,1        ; COM1/3?
  2945.     jz    chkint13        ; z = no, COM2/4
  2946.     cmp    flags.comflg,1        ; COM1?
  2947.     je    chkint10a        ; e = yes, try IRQ 4
  2948.     cmp    isps2,0            ; IBM PS/2 Model 50 or above?
  2949.     jne    chkint11        ; ne = yes, other COM2..4 try IRQ 3
  2950. chkint10a:call    chkint5            ; test for IRQ 4
  2951.     jc    chkint11        ; c = failed
  2952.     ret
  2953. chkint11:call    chkint6            ; else try IRQ 3
  2954.     jnc    chkint12        ; nc = success
  2955.     jmp    chkint7            ; fall back on defaults
  2956. chkint12:ret                ; carry clear for success
  2957.  
  2958. chkint13:call    chkint6            ; test for IRQ 3
  2959.     jc    chkint14        ; c = failed
  2960.     ret
  2961. chkint14:call    chkint5            ; else try IRQ 4
  2962.     jnc    chkint15        ; nc = success
  2963.     jmp    chkint7            ; fall back on defaults
  2964. chkint15:ret                ; carry clear for success
  2965.  
  2966.                     ; IRQ specified, in AL
  2967. chkint20:mov    di,sp            ; do push sp test for XT vs 286 class
  2968.     push    sp            ; XT pushes sp-2, 286's push old sp
  2969.     pop    cx            ; recover pushed value, clean stack
  2970.     sub    di,cx            ; non-zero if < 80286, no slave 8259
  2971.     cmp    al,2            ; using IRQ 2?
  2972.     jne    chkint1            ; ne = no
  2973.     or    di,di            ; cascaded 8259?
  2974.     jnz    chkint1            ; nz = no
  2975.     add    al,7            ; map IRQ 2 to IRQ 9
  2976. chkint1:cmp    al,15            ; larger than legal IRQ?
  2977.     ja    chkint2            ; a = yes, fail
  2978.     or    di,di            ; 286 or above (cascaded 8259)?
  2979.     jz    chkint3            ; z = yes
  2980.     cmp    al,7            ; larger than legal for single 8259?
  2981.     jbe    chkint3            ; be = no
  2982. chkint2:stc                ; fail
  2983.     ret
  2984. chkint3:mov    cl,al            ; IRQ 0..15
  2985.     mov    bx,1
  2986.     shl    bx,cl            ; bit position of IRQ 0..15
  2987.     or    bl,bh            ; copy bit to bl
  2988.     mov    modem.mddis,bl        ; mask to disable IRQ
  2989.     not    bl            ; 0 means enable
  2990.     mov    modem.mden,bl        ; mask to enable IRQ
  2991.     and    al,7            ; IRQ, lower three bits
  2992.     mov    ah,al            ; make a copy
  2993.     add    ah,60h            ; specific EOI control code
  2994.     mov    modem.mdmeoi,ah        ; specific EOI control command
  2995.     add    al,8            ; IRQ 0 starts at Int 8
  2996.     xor    ah,ah
  2997.     mov    modem.mdintv,ax        ; Interrupt number
  2998.     mov    modem.mdmintc,20h    ; master 8259 control address
  2999.     or    bh,bh            ; on cascaded 8259?
  3000.     jz    chkint4            ; z = no
  3001.     or    modem.mdmintc,80h    ; slave 8259 control address (0a0h)
  3002.     add    modem.mdintv,70h-8    ; Interrupt number for IRQ 8..15
  3003. chkint4:clc
  3004.     ret
  3005.  
  3006.                     ; find IRQ 4 by usage test
  3007. chkint5:mov    modem.mddis,(1 shl 4)    ; IRQ 4 test. mask to disable IRQ 4
  3008.     mov    modem.mden,not (1 shl 4); mask to enable IRQ 4
  3009.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  3010.     mov    modem.mdintv,8+4    ; IRQ 4 interrupt vector (0ch)
  3011.     mov    modem.mdmintc,20h    ; use master 8259 here
  3012.     call    inttest
  3013.     jc    chkint5a        ; c = failed
  3014.     mov    modem.mdmeoi,60h+4    ; use specific EOI for IRQ4 level
  3015.     mov    bl,flags.comflg        ; port 1..4
  3016.     dec    bl
  3017.     xor    bh,bh
  3018.     mov    portirq[bx],4
  3019.     clc                ; this setup worked
  3020. chkint5a:ret
  3021.                     ; IRQ 3 test
  3022. chkint6:mov    modem.mddis,(1 shl 3)    ; mask to disable IRQ 3
  3023.     mov    modem.mden,not (1 shl 3); mask to enable IRQ 3
  3024.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  3025.     mov    modem.mdintv,8+3    ; IRQ 3 interrupt vector
  3026.     call    inttest
  3027.     jc    chkint6a        ; c = failed
  3028.     mov    modem.mdmeoi,60h+3    ; use specific EOI for IRQ3 level
  3029.     mov    bl,flags.comflg        ; port 1..4
  3030.     dec    bl
  3031.     xor    bh,bh
  3032.     mov    portirq[bx],3
  3033.     clc                ; this setup worked
  3034. chkint6a:ret
  3035.  
  3036.                     ; auto test did not work
  3037. chkint7:mov    modem.mdmintc,20h    ; use master 8259 Int controller
  3038.     cmp    flags.comflg,1        ; COM1?
  3039.     je    chkint8            ; e = yes, use IRQ 4
  3040.     cmp    isps2,0            ; IBM PS/2 Model 50 or above?
  3041.     jne    chkint9            ; ne = yes, other COMs use IRQ 3
  3042.     cmp    flags.comflg,3        ; COM2, COM3, or COM4?
  3043.     jne    short chkint9        ; ne = COM2 or COM4, use IRQ 3
  3044. chkint8:mov    modem.mdmeoi,60h+4    ; use specific EOI for IRQ4 level
  3045.     mov    modem.mddis,(1 shl 4)    ; IRQ 4 test. mask to disable IRQ 4
  3046.     mov    modem.mden,not (1 shl 4); mask to enable IRQ 4
  3047.     mov    modem.mdintv,8+4    ; IRQ 4 interrupt vector (0ch)
  3048.     mov    bl,flags.comflg        ; port 1..4
  3049.     dec    bl
  3050.     xor    bh,bh
  3051.     mov    ax,4            ; IRQ
  3052.     mov    portirq[bx],al
  3053.     jmp    short chkint9a        ; show message
  3054.  
  3055. chkint9:mov    modem.mdmeoi,60h+3    ; use specific EOI for IRQ 3 level
  3056.     mov    modem.mddis,(1 shl 3)    ; mask to disable IRQ 3
  3057.     mov    modem.mden,not (1 shl 3); mask to enable IRQ 3
  3058.     mov    modem.mdintv,8+3    ; IRQ 3 interrupt vector
  3059.     mov    bl,flags.comflg        ; port 1..4
  3060.     dec    bl
  3061.     xor    bh,bh
  3062.     mov    ax,3            ; IRQ
  3063.     mov    portirq[bx],al
  3064. chkint9a:push    ax
  3065.     mov    ah,prstr
  3066.     mov    dx,offset badirq    ; say assuming an IRQ
  3067.     int    dos
  3068.     pop    ax
  3069.     mov    cx,10            ; decimal
  3070.     call    valout            ; show IRQ
  3071.     clc
  3072.     ret
  3073.  
  3074. inttest:call    serini            ; setup port for given IRQ
  3075.     jc    inttes2            ; c = failure
  3076.     mov    dx,modem.mddat
  3077.     inc    dx            ; interrupt enable reg (3f9h)
  3078.     cli
  3079.     mov    intkind,0        ; clear interrupt cause
  3080.     mov    al,2            ; set xmtr holding reg empty interrupt
  3081.     out    dx,al
  3082.     call    delay
  3083.     mov    al,2            ; set xmtr holding reg empty interrupt
  3084.     out    dx,al            ; again, because first may be missed
  3085.     sti
  3086.     call    delay            ; wait one millisec for interrupt
  3087.     mov    al,intkind        ; interrupt kind
  3088.     push    ax
  3089.     call    serrst            ; reset port
  3090.     pop    ax
  3091.     test    al,2            ; check cause of interrupt, ours?
  3092.     jz    inttes2            ; z = no, test failed
  3093.     clc                ; this setup worked
  3094.     ret
  3095. inttes2:stc                ; failure
  3096.     ret
  3097. chkint    endp
  3098.  
  3099. ; Test presently selected serial port for having a real 8250 UART.
  3100. ; Return carry clear if 8250 present,
  3101. ;  else carry set and flags.comflg in ascii digits for system Bios or
  3102. ;  carry set for network.
  3103. ; Method is to check UART's Interrupt Identification Register for high
  3104. ; five bits being zero; IBM does it this way. Assumes port structure
  3105. ; has been initialized with addresses of UART.    21 Feb 1987 [jrd]
  3106. ; 29 May 1987 Add double check by reading Line Status Register. [jrd]
  3107.  
  3108. chkport    proc    near
  3109.     cmp    flags.comflg,4        ; non-UART port?
  3110.     ja    chkporx            ; a = yes
  3111.     cmp    flags.comflg,0        ; undefined port?
  3112.     je    chkporx            ; e = yes
  3113.     push    ax
  3114.     push    dx
  3115.     mov    dx,modem.mdiir        ; UART Interrupt Ident reg (3FAh/2FAh)
  3116.     in    al,dx            ; read UART's IIR
  3117.     test    al,30h            ; are these bits set?
  3118.     jnz    chkpor1            ; nz = yes, not an 8250/16450/16550A
  3119.     mov    dx,modem.mdstat        ; line status register
  3120.     in    al,dx             ; read to clear UART BI, FE, PE, OE bits
  3121.     call    delay
  3122.     in    al,dx            ; these bits should be cleared
  3123.     test    al,8eh            ; are they cleared?
  3124.     jnz    chkpor1            ; nz = no, not an 8250/16450/16550A
  3125.     pop    dx
  3126.     pop    ax
  3127.     clc                ; clear carry (say 8250/etc)
  3128.     ret
  3129. chkpor1:pop    dx
  3130.     pop    ax
  3131.     add    flags.comflg,'0'    ; set Bios usage flag (ascii digit)
  3132. chkporx:stc                ; set carry (say no 8250/etc)
  3133.     ret
  3134. chkport    endp
  3135.  
  3136. ; Check for presence of IBM EBIOS
  3137. ; Returns carry clear if EBIOS present, else carry set
  3138. chkebios proc    near
  3139.     mov    dx,ebport        ; port 0..3
  3140.     mov    ax,ebpresent*256+0ffh    ; IBM EBIOS presence check
  3141.     int    rs232
  3142.     jc    chkebios1        ; c = failure
  3143.     or    ax,ax            ; returns ax = 0 if present
  3144.     jnz    chkebios1        ; nz = not present
  3145.     clc
  3146.     ret
  3147. chkebios1:stc                ; IBM EBIOS not present
  3148.     ret
  3149. chkebios endp
  3150.  
  3151. ; Set the baud rate for the current port, based on the value
  3152. ; in the portinfo structure.  Returns carry clear.
  3153.  
  3154. BAUDST    PROC    NEAR
  3155.     mov    dx,offset bdtab        ; baud rate table, ascii
  3156.     xor    bx,bx            ; help is the table itself
  3157.     mov    ah,cmkey        ; get keyword
  3158.     call    comnd
  3159.     jc    baudst1            ; c = failure
  3160.     push    bx            ; save result
  3161.     mov    ah,cmeol        ; get confirmation
  3162.     call    comnd
  3163.     pop    bx
  3164.     jc    baudst1            ; c = failure
  3165.     call    dobaud            ; use common code
  3166.     clc
  3167. baudst1:ret
  3168. BAUDST    ENDP
  3169.  
  3170. DOBAUD    PROC    NEAR
  3171.     cmp    portin,-1        ; port used yet?
  3172.     jne    dobd3            ; ne = yes, go get rate
  3173.     push    bx            ; save rate index
  3174.     mov    bl,flags.comflg        ; pass current port ident
  3175.     call    comstrt            ; do SET PORT command now
  3176.     pop    bx
  3177.     jnc    dobd3            ; nc = success
  3178. dobd4:    stc
  3179.     ret                ; failure
  3180. dobd3:    push    bx            ; save baud rate index
  3181.     mov    al,flags.comflg        ; comms port
  3182.     cmp    al,'E'            ; EBIOS?
  3183.     je    dobd5            ; e = yes
  3184.     cmp    al,'4'            ; UART or Bios?
  3185.     ja    dobd1            ; a = no, networks
  3186.     call    chkport            ; check port for real 8250 UART
  3187. dobd5:    pop    bx            ; baud rate index
  3188.     push    bx            ; check if new rate is valid
  3189.     mov    ax,bx
  3190.     shl    ax,1            ; make a word index
  3191.     mov    bx,offset bddat        ; start of table
  3192.     cmp    flags.comflg,'0'    ; Bios?
  3193.     jb    dobd0a            ; b = no, UART
  3194.     mov    bx,offset clbddat    ; use Bios speed parameters
  3195. dobd0a:    add    bx,ax
  3196.     mov    ax,[bx]            ; data to output to port
  3197.     cmp    al,0FFh            ; unimplemented baud rate?
  3198.     jne    dobd0            ; ne = no
  3199.     mov    ah,prstr
  3200.     mov    dx,offset badbd        ; give an error message
  3201.     int    dos
  3202.     jmp    dobd1
  3203.  
  3204. dobd0:    pop    bx            ; get baud rate index
  3205.     push    bx
  3206.     mov    si,portval
  3207.     mov    [si].baud,bx        ; set the baud rate index
  3208.     mov    dl,flags.comflg        ; get coms port (1..4, letters)
  3209.     cmp    dl,4            ; running on a real uart?
  3210.     jbe    dobd2            ; be = yes, the real thing
  3211.     cmp    dl,'E'            ; EBIOS?
  3212.     je    dobd6            ; e = yes
  3213.     cmp    dl,'4'            ; Bios?
  3214.     ja    dobd1            ; a = no, network
  3215.     or    dl,dl            ; zero (undefined port)?
  3216.     jz    dobd1            ; z = yes, just exit
  3217.     and    dl,7            ; use lower three bits
  3218.     dec    dl            ; count ports as 0..3 for Bios
  3219.     jmp    short dobd7
  3220. dobd6:    test    nettype,acsi        ; using EBIOS.COM?
  3221.     jnz    dobd8            ; nz = not using it
  3222.     mov    dx,ebport        ; get EBIOS port (0..3)
  3223. dobd7:    xor    dh,dh
  3224.     xor    ah,ah            ; set serial port
  3225.     int    rs232            ; Bios: set the parameters
  3226.          jmp    short dobd1        ; and exit
  3227.  
  3228. dobd8:    push    bx            ; ACSI
  3229.     call    send            ; send current buffer first
  3230.     pop    bx
  3231.     shl    bx,1            ; index words
  3232.     mov    ax,clbddat[bx]        ; Bios speed settings
  3233.     mov    word ptr xmtbufx,4    ; four bytes in packet
  3234.     mov    ah,acsetmode        ; ACSI set mode
  3235.     mov    word ptr xmtbufx+2,ax    ; Mode setting
  3236.     call    send            ; send speed update to host
  3237.     jmp    short dobd1        ; exit
  3238.  
  3239. dobd2:    pushf
  3240.     cli                ; interrupts off
  3241.     push    ax            ; UART, remember value to output
  3242.     mov    dx,modem.mdcom        ; LCR -- Initialize baud rate
  3243.     in    al,dx            ; get it
  3244.     mov    bl,al            ; make a copy
  3245.     or    ax,80H        ; turn on DLAB bit to access divisor part
  3246.     out    dx,al
  3247.     mov    dx,modem.mddat
  3248.     pop    ax            ; set the baud rate divisor
  3249.     out    dx,al
  3250.     inc    dx            ; next address for high part
  3251.     mov    al,ah            ; set high part of divisor
  3252.     out    dx,al
  3253.     mov    dx,modem.mdcom        ; LCR again
  3254.     mov    al,bl            ; get original setting from bl
  3255.     out    dx,al            ; restore it
  3256.     popf                ; restore interrupt state
  3257. dobd1:    pop    bx            ; restore regs
  3258.     clc
  3259.     ret
  3260. DOBAUD    ENDP
  3261.  
  3262. ; Get the current baud rate from the serial card and set it
  3263. ; in the portinfo structure for the current port.  Returns normally.
  3264. ; This is used during initialization.
  3265.  
  3266. GETBAUD    PROC    NEAR
  3267.     push    ax
  3268.     push    bx
  3269.     mov    bx,portval
  3270.     mov    al,flags.comflg
  3271.     cmp    al,4            ; UART?
  3272.     ja    getb3            ; a = no, Bios or Networks
  3273.     cmp    portin,-1        ; port unused?
  3274.     jne    getbud            ; ne = no, used, go get rate
  3275.     mov    bl,al            ; pass current port ident
  3276.     call    comstrt            ; do SET PORT command now
  3277.     jnc    getbud            ; nc = success
  3278. getb3:    pop    bx
  3279.     pop    ax
  3280.     ret                ; failure
  3281. getbud:    push    cx            ; save some regs
  3282.     push    dx
  3283.     pushf
  3284.     cli                ; interrupts off
  3285.     mov    dx,modem.mdcom         ; get current Line Control Register value
  3286.     in    al,dx
  3287.     mov    bl,al            ; save it
  3288.     or    ax,80H              ; turn on to access baud rate generator
  3289.     out    dx,al
  3290.     mov    dx,modem.mddat        ; Divisor latch
  3291.     inc    dx
  3292.     in    al,dx            ; get high order byte
  3293.     mov    ah,al            ; save here
  3294.     dec    dx
  3295.     in    al,dx            ; get low order byte
  3296.     push    ax    
  3297.     mov    dx,modem.mdcom        ; Line Control Register
  3298.     mov    al,bl            ; restore old value
  3299.     out    dx,al
  3300.     pop    ax
  3301.     popf                ; ints back to normal
  3302.     cmp    ax,0FFFFH        ; if no port
  3303.     je    getb2            ; e = no port, bus noise
  3304.     mov    bx,offset bddat        ; find rate's offset into table
  3305.     xor    cl,cl            ; keep track of index
  3306. getb0:    cmp    ax,[bx]            ; observed vs table divisor
  3307.     je    getb1            ; e = found a match
  3308.     inc    cl            ; next table index
  3309.     cmp    cl,baudlen        ; at the end of the list?
  3310.     jge    getb2            ; ge = yes, quit
  3311.     add    bx,2            ; next table entry
  3312.     jmp    short getb0
  3313. getb1:    xor    ch,ch
  3314.     mov    bx,portval
  3315.     mov    [bx].baud,cx        ; set baud rate
  3316. getb2:    pop    dx            ; restore regs
  3317.     pop    cx
  3318.     pop    bx
  3319.     pop    ax
  3320.     clc
  3321.     ret
  3322. GETBAUD    ENDP
  3323.  
  3324. ; Examine incoming communications stream for a packet SOP character.
  3325. ; Return CX= count of bytes starting at the SOP character (includes SOP)
  3326. ; and carry clear. Return CX = 0 and carry set if SOP is not present.
  3327. ; Destroys AL.
  3328. peekcom proc far
  3329.     mov    cx,count        ; qty in circular buffer
  3330.     cmp    cx,6            ; basic NAK
  3331.     jb    peekc4            ; b = two few chars, get more
  3332.     push    bx
  3333.     cli        ; interrupts off, to keep srcpnt & count consistent
  3334.     mov    bx,srcpnt        ; address of next available slot in buffer
  3335.     sub    bx,cx            ; minus number of unread chars in buffer
  3336.     cmp    bx,offset source    ; located before start of buf?
  3337.     jae    peekc1            ; ae = no
  3338.     add    bx,bufsiz        ; else do arithmetic modulo bufsiz
  3339. peekc1:    mov    al,[bx]
  3340.     cmp    al,trans.rsoh        ; packet receive SOP?
  3341.     je    peekc3            ; e = yes
  3342.     inc    bx
  3343.     cmp    bx,offset source+bufsiz ; beyond end of buffer?
  3344.     jb    peekc2            ; b = no
  3345.     mov    bx,offset source    ; wrap around
  3346. peekc2:    loop    peekc1            ; keep looking
  3347.     sti
  3348.     pop    bx
  3349.     stc                ; set carry for no SOP
  3350.     ret
  3351. peekc3:    sti                ; interrupts back on now
  3352.     pop    bx
  3353.     inc    cx            ; include SOP in count
  3354.     clc                ; say SOP found
  3355.     ret                ; CX has count remaining
  3356.     
  3357. peekc4:    push    bx            ; read from port, add to buffer
  3358.     mov    bx,portval
  3359.     push    si            ; used by packet routines
  3360.     call    [bx].rcvproc        ; read routine
  3361.     pop    si
  3362.     jc    peekc7            ; c = nothing available
  3363.     cmp    count,0            ; something put in buffer?
  3364.     jne    peekc7            ; ne = yes, go read from buffer
  3365.     mov    bx,srcpnt        ; were next read would be
  3366.     inc    bx            ; add to buffer
  3367.     cmp    bx,offset source+bufsiz    ; pointing beyond end of buffer?
  3368.     jb    peekc5            ; b = no
  3369.     mov    bx,offset source    ; wrap pointer, modulo bufsiz
  3370. peekc5:    cli
  3371.     mov    [bx],al            ; store byte
  3372.     mov    srcpnt,bx        ; update pointer to next free slot
  3373.     inc    count
  3374.     cmp    count,bufsiz        ; count more that buffer size?
  3375.     jbe    peekc6            ; be = no
  3376.     mov    count,bufsiz        ; limit to bufsiz (tells the truth)
  3377. peekc6:    sti
  3378. peekc7:    pop    bx
  3379.     cmp    count,6            ; anything now?
  3380.     jae    peekcom            ; ne = yes, repeat examination
  3381.     xor    cx,cx            ; return count of zero
  3382.     stc                ; say no data
  3383.     ret
  3384. peekcom endp
  3385.  
  3386. ; Get Char from    serial port buffer.
  3387. ; returns carry set if no character available at port, otherwise
  3388. ; returns carry clear with char in al, # of chars in buffer in dx.
  3389. prtchr  proc    near
  3390.     cmp    holdscr,0        ; Holdscreen in effect?
  3391.     jne    prtch3            ; ne = yes, do not read
  3392.     call    chkxon            ; see if we need to send XON
  3393.     cmp    repflg,0        ; REPLAY?
  3394.     je    prtch1            ; e = no
  3395.     jmp    prtchrpl        ; yes, do replay file reading
  3396. prtch1:    cmp    count,0            ; is buffer empty?
  3397.     jne    prtch4            ; ne = no, read from it
  3398.     push    bx
  3399.     mov    bx,portval
  3400.     call    [bx].rcvproc        ; read routine
  3401.     pop    bx            ; fall through to grab new char
  3402.     jc    prtch3            ; c = nothing available
  3403.     cmp    count,0            ; something put in buffer?
  3404.     jne    prtch4            ; ne = yes, go read from buffer
  3405. prtch2:    inc    dx
  3406.     clc                ; return single char already in AL
  3407.     ret
  3408. prtch3:    xor    dx,dx            ; return count of zero
  3409.     stc                ; say no data
  3410.     ret
  3411.  
  3412. prtch4:    push    si            ; save si
  3413.     cli        ; interrupts off, to keep srcpnt & count consistent
  3414.     mov    si,srcpnt        ; address of next available slot in buffer
  3415.     sub    si,count        ; minus number of unread chars in buffer
  3416.     cmp    si,offset source    ; located before start of buf?
  3417.     jae    prtch5            ; ae = no
  3418.     add    si,bufsiz        ; else do arithmetic modulo bufsiz
  3419. prtch5:    lodsb                ; get a character into al
  3420.     dec    count            ; one less unread char now
  3421.     sti                ; interrupts back on now
  3422.     pop    si
  3423.     mov    dx,count        ; return # of chars in buffer
  3424.     or    al,al            ; is this a null byte?
  3425.     jnz    prtch6            ; nz = no
  3426.     cmp    flags.comflg,'t'    ; using TCP/IP Telnet?
  3427.     jne    prtch6            ; ne = no
  3428.     cmp    lastread,CR        ; CR NULL?
  3429.     jne    prtch6            ; ne = no
  3430.     mov    lastread,al        ; remember what we last read
  3431.     stc                ; discard the NVT NULL
  3432.     ret
  3433. prtch6:    mov    lastread,al        ; remember what we last read
  3434.     clc
  3435.     ret
  3436. prtchr  endp
  3437.  
  3438. uartrcv    proc    near            ; UART receive
  3439.     stc                ; say not returning char in al here
  3440.     ret                ; interrupt driven so no work here
  3441. uartrcv    endp
  3442.  
  3443. ebircv    proc    near            ; EBIOS calls
  3444.     mov    dx,ebport        ; port 0..3
  3445.     mov    ah,ebrcv        ; IBM EBIOS receive /no wait
  3446.     int    rs232            ; does line check then char ready chk
  3447.     test    ah,8ch            ; timeout, framing error, parity error?
  3448.     jnz    ebircv2            ; nz = error, no char
  3449.     jmp    schrcv            ; z = success, process char in AL
  3450. ebircv2:stc                ; say not returning char in al here
  3451.     ret
  3452. ebircv    endp
  3453.  
  3454. biosrcv    proc    near            ; Bios calls
  3455.     xor    dh,dh            ; assume port 1, find current port
  3456.     mov    dl,flags.comflg        ; get port number (1..4)
  3457.     or    dl,dl            ; zero (no such port)?
  3458.     jz    biosrc1            ; z = yes, don't access it
  3459.     and    dl,7            ; use low three bits
  3460.     dec    dl            ; address ports as 0..3 for Bios
  3461.     mov    ah,3            ; check port status, std Bios calls
  3462.     int    rs232            ; Bios call
  3463.     test    ah,mdminp        ; data ready?
  3464.     jnz    biosrc2            ; nz = yes, get one
  3465. biosrc1:stc                ; say not returning char in al here
  3466.     ret
  3467. biosrc2:mov    ah,2            ; receive a char into al
  3468.     int    rs232            ; Bios call
  3469.     test    ah,8ch            ; timeout, framing error, parity error?
  3470.     jnz    biosrc1            ; nz = error, no char
  3471.     jmp    short schrcv        ; single char read post processor
  3472. biosrcv    endp
  3473.  
  3474. schrcv    proc    near            ; single char read final filter    
  3475.     test    flowcnt,2        ; using input XON/XOFF flow control?
  3476.     jz    schrcv3            ; z = no
  3477.     mov    ah,al            ; get copy of character
  3478.     and    ah,parmsk        ; strip parity, if any, before testing
  3479.     cmp    ah,flowoff        ; acting on XOFF?
  3480.     jne    schrcv2            ; ne = no, go on
  3481.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  3482.     jne    schrcv1            ; ne = yes, ignore (possible echo)
  3483.     mov    xofrcv,bufon        ; set the flag saying XOFF received
  3484. schrcv1:stc                ; say not returning char in al here
  3485.     ret
  3486. schrcv2:cmp    ah,flowon        ; acting on XON?
  3487.     jne    schrcv3            ; ne = no, go on
  3488.     mov    xofrcv,off        ; clear the XOFF received flag
  3489.     xor    dx,dx
  3490.     stc
  3491.     ret                ; no data to return
  3492. schrcv3:xor    ah,ah
  3493.     clc                ; return char in al
  3494.     ret                ; expect count=0
  3495. schrcv    endp
  3496.  
  3497.                     ; REPLAY, read char from a file
  3498. prtchrpl proc    near
  3499.     cmp    repflg,2        ; at EOF already?
  3500.     jne    prtchrp1        ; ne = no
  3501.     stc                ; yes, return with no char
  3502.     ret
  3503. prtchrp1:push    bx
  3504.     push    cx
  3505.     xor    dx,dx
  3506.     test    xofsnt,usron        ; user level xoff sent?
  3507.     jz    prtchrp2        ; z = no
  3508.     pop    cx            ; suppress reading here
  3509.     pop    bx
  3510.     stc                ; say not returning char in al here
  3511.     ret
  3512. prtchrp2:test    tekflg,tek_active    ; doing graphics mode?
  3513.     jnz    prtchrp3        ; nz = yes, do not insert pauses
  3514.     in    al,ppi_port        ; delay
  3515.     in    al,ppi_port
  3516.     in    al,ppi_port        ; burn some bus cycles
  3517.     in    al,ppi_port        ; because a 1 ms wait is too long
  3518.     in    al,ppi_port
  3519. prtchrp3:mov    ah,readf2
  3520.     mov    bx,diskio.handle    ; file handle
  3521.     mov    cx,1            ; read one char
  3522.     mov    dx,offset decbuf    ; to this buffer
  3523.     int    dos
  3524.     jc    prtchrp4        ; c = read failure
  3525.     cmp    ax,cx            ; read the byte?
  3526.     jne    prtchrp4        ; ne = no
  3527.     pop    cx
  3528.     pop    bx
  3529.     mov    al,decbuf        ; get the char into al
  3530.     clc
  3531.     ret                ; return it
  3532. prtchrp4:call    beep
  3533.     mov    ax,40            ; wait 40 millisec
  3534.     call    pcwait
  3535.     call    beep
  3536.     mov    repflg,2        ; say at EOF
  3537.     pop    cx
  3538.     pop    bx
  3539.     stc                ; say not returning char in al here
  3540.     ret
  3541. prtchrpl endp
  3542.  
  3543. ; DECnet receive routine
  3544. DECRCV    PROC    NEAR
  3545.     test    nettype,declat        ; LAT interface?
  3546.     jz    decrcv1            ; z = not LAT
  3547.     mov    dx,lathand
  3548.     or    dx,dx            ; invalid handle?
  3549.     jz    decrcv1            ; z = yes, try CTERM
  3550. or lathand,0ff00h
  3551.     mov    ah,latread        ; read char via LAT into AL
  3552.     int    latint
  3553.     test    ah,80h            ; char available?
  3554.     jz    decrcv2            ; z = yes
  3555. ; non-SCB status check, slower and much safer
  3556.     mov    ah,latstat        ; get status
  3557.     mov    dx,lathand
  3558.     int    latint
  3559.     test    ah,4            ; session not active?
  3560.     jnz    decrcv3            ; nz = yes, no valid session
  3561.     stc                ; say not returning char in al here
  3562.     ret
  3563. ; end alterntive code
  3564.  
  3565. ;    push    es
  3566. ;    push     bx
  3567. ;    les    bx,latscbptr
  3568. ;    test    es:[bx].sstatus,18h    ; status: stop slot or circuit failure
  3569. ;    pop    bx
  3570. ;    pop    es
  3571. ;    jnz    decrcv4            ; nz = yes, no valid session
  3572. ;    stc                ; return no char
  3573. ;    ret
  3574.  
  3575. decrcv1:test    nettype,decnet        ; is CTERM active?
  3576.     jz    decrcv3            ; z = no
  3577.     mov    dx,decneth        ; handle
  3578.     or    dx,dx            ; legal?
  3579.     jz    decrcv3            ; z = no
  3580.     mov    ax,dcstat        ; CTERM status
  3581.     int    decint
  3582.     test    ah,0c0h            ; no session, DECnet error?
  3583.     jnz    decrcv3            ; nz = yes, stop here
  3584. ;    test    ah,1            ; data available?
  3585. ;    jz    decrcv4            ; z = no
  3586. ; data available test fails under flow control, maybe a Cterm bug.
  3587.     mov    ax,dread        ; read char via CTERM
  3588.     int    decint
  3589.     test    ah,80h            ; char received?
  3590.     jnz    decrcv4            ; nz = no
  3591. decrcv2:jmp    schrcv            ; use common completion code
  3592.  
  3593. decrcv3:call    decclose        ; close connection
  3594.     test    flags.remflg,dserver    ; server mode?
  3595.     jz    decrcv4            ; z = no
  3596.     call    serini            ; reinitialize it for new session
  3597. decrcv4:stc                ; say not returning char in al here
  3598.     ret
  3599. DECRCV    ENDP
  3600.  
  3601. ; NetBios Receive packet routine. If a new packet has been received unpack
  3602. ; the data and request a new one with no-wait option. If a receive request is
  3603. ; still outstanding just return with no new data.
  3604. ; Return carry clear if success. If failure, reset serial port (Server mode
  3605. ; reinits serial port). Return carry set. No entry setup needed.
  3606. RECEIVE PROC    NEAR            ; receive network session pkt
  3607.     cmp    pcnet,1            ; net ready yet?
  3608.     jbe    receiv3            ; be = no, declare a broken session
  3609.     cmp    rposted,1        ; is a request outstanding now?
  3610.     je    receiv4            ; e = yes (1), don't do another
  3611.     jb    receiv1            ; b = no (0), do one now
  3612.     call    receiv2            ; have new pkt, unpack, do new recv
  3613.     jnc    receiv1            ; nc = success
  3614.     ret                ; else return carry set
  3615.  
  3616. receiv1:mov    rposted,1        ; say posting a receive now
  3617.     mov    rcv.scb_length,nbuflen    ; length of input buffer  
  3618.     mov    rcv.scb_cmd,nreceive+nowait   ; receive, no wait
  3619.     push    bx
  3620.     mov    bx,offset rcv        ; setup pointer to scb
  3621.     call    nbsession
  3622.     pop    bx
  3623.     stc                ; set carry to say no char yet
  3624.     ret                
  3625.  
  3626. receiv2:mov    al,rcv.scb_err        ; returned status
  3627.     or    al,al            ; success?
  3628.     jz    receiv5            ; z = yes, get the data
  3629.     cmp    al,npending        ; pending receive?
  3630.     je    receiv4            ; e = yes
  3631.     cmp    al,6            ; message incomplete?
  3632.     je    receiv5            ; e = yes, get what we have anyway
  3633.     cmp    al,0bh            ; receive cancelled?
  3634.     je    receiv4            ; e = yes
  3635.     cmp    al,18h            ; session ended abnormally?
  3636.     jbe    receiv3            ; e = yes, b = other normal errors
  3637.     mov    ah,prstr
  3638.     mov    dx,offset recmsg    ; give error message
  3639.     int    dos
  3640.     mov    al,rcv.scb_err        ; get error code
  3641.     call    decout            ; show error code
  3642.  
  3643.                     ; Error return
  3644. receiv3:call    nbclose            ; close the connection
  3645.     test    flags.remflg,dserver    ; server mode?
  3646.     jz    receiv4            ; z = no
  3647.     call    serini            ; reinitialize it for new session
  3648. receiv4:stc                ; say not returning char in al here
  3649.     ret
  3650. receiv5:mov    rposted,0        ; clear interlock flag
  3651.     test    nettype,acsi        ; ACSI?
  3652.     jnz    receiv6            ; nz = yes
  3653.     jmp    blkrcv            ; process block of data
  3654. receiv6:jmp    acsircv            ; process special format block data
  3655. RECEIVE    ENDP
  3656.  
  3657. ; Block receive transfer and flow control scan routine
  3658. ; Enter with DS:rcv.scb_baddr pointing at source buffer (rcvbuf),
  3659. ; and rcv.scb_length holding incoming byte count.
  3660. ; Destroys reg BX
  3661. ; Shared by NetBios, Novell, Opennet, Ungerman Bass, 3ComBAPI, TCP/IP, etc
  3662. blkrcv    proc    near
  3663.     push    cx            ; new packet has been received
  3664.     push    dx            ; copy contents to circ buf source
  3665.     push    si
  3666.     mov    dh,flowon
  3667.     mov    dl,flowoff
  3668.     mov    si,rcv.scb_baddr    ; source of text
  3669.     mov    bx,srcpnt        ; address of destination buffer slot
  3670. blkrcv6:mov    cx,rcv.scb_length    ; get remaining returned byte count
  3671.     jcxz    blkrcv13        ; z = nothing there
  3672.     mov    ax,offset source+bufsiz ; end of destination buffer+1
  3673.     sub    ax,bx            ; space remaining at end of buffer
  3674.     jns    blkrcv7            ; should never be negative
  3675.     neg    ax            ; but if so invert
  3676. blkrcv7:cmp    ax,cx            ; buffer ending vs incoming byte count
  3677.     jge    blkrcv8            ; ge = enough for this pass
  3678.     mov    cx,ax            ; limit this pass to end of the buffer
  3679. blkrcv8:sub    rcv.scb_length,cx    ; deduct chars done in this pass
  3680.     add    count,cx        ; add them to the count
  3681.     cld                ; inner loop "block" transfer
  3682.     test    flowcnt,2        ; doing input XON/XOFF flow control?
  3683.     jz    blkrcv20        ; z = no
  3684. blkrcv9:lodsb                ; get byte from rcvbuf to al
  3685.     mov    ah,al            ; get copy of character
  3686.     and    ah,parmsk        ; strip parity, if any, before testing
  3687.     cmp    ah,dl            ; acting on Xoff?
  3688.     jne    blkrcv10        ; ne = no
  3689.     cmp    xofsnt,0        ; have we sent an XOFF?
  3690.     jne    blkrcv12        ; ne = yes, ignore this XOFF char
  3691.     mov    xofrcv,bufon        ; set flag saying buffer XOFF received
  3692.     dec    count            ; uncount flow control
  3693.     jmp    short blkrcv12        ;  and skip this character
  3694. blkrcv10:cmp    ah,dh            ; acting on XON?
  3695.     jne    blkrcv11        ; ne = no, go on
  3696.     mov    xofrcv,off        ; clear the XOFF received flag
  3697.     dec    count            ; uncount flow control
  3698.     jmp    short blkrcv12        ;  and skip this character
  3699. blkrcv11:mov    [bx],al            ; store new char in buffer "source"
  3700.     inc    bx
  3701. blkrcv12:loop    blkrcv9            ; bottom of inner loop
  3702.     jmp    short blkrcv22
  3703.  
  3704. blkrcv20:push    es            ; no flow control, just do copy
  3705.     push    di
  3706.     mov    ax,ds
  3707.     mov    es,ax
  3708.     mov    di,bx            ; destination
  3709.     shr    cx,1            ; prep for word moves
  3710.     jnc    blkrcv21        ; nc = even number of bytes
  3711.     movsb
  3712. blkrcv21:rep    movsw            ; do quick copy
  3713.     mov    bx,di            ; update destination pointer
  3714.     pop    di
  3715.     pop    es
  3716.                     ; update buffer pointer for wrapping
  3717. blkrcv22:cmp    bx,offset source+bufsiz    ; pointing beyond end of buffer?
  3718.     jb    blkrcv6            ; b = no, do next pass
  3719.     mov    bx,offset source    ; wrap pointer, modulo bufsiz
  3720.     jmp    short blkrcv6        ; do next pass
  3721.  
  3722. blkrcv13:mov    srcpnt,bx        ; update pointer to next free slot
  3723.     cmp    count,bufsiz        ; count more that buffer size?
  3724.     jbe    blkrcv14        ; be = no
  3725.     mov    count,bufsiz        ; limit to bufsiz (tells the truth)
  3726. blkrcv14:pop    si
  3727.     pop    dx
  3728.     pop    cx
  3729.     stc                ; say no char in al from us
  3730.     ret
  3731. blkrcv    endp
  3732.  
  3733. ; ACSI block receive transfer and flow control scan routine
  3734. ; Enter with DS:rcv.scb_baddr pointing at source buffer (rcvbuf),
  3735. ; and rcv.scb_length holding incoming byte count.
  3736. ; Destroys regs AX and BX.
  3737. ; Format of packet: int count of entire block, then [char, status] byte pairs
  3738. acsircv    proc    near
  3739.     push    cx            ; new packet has been received
  3740.     push    dx            ; copy contents to circ buf source
  3741.     push    si
  3742.     mov    dh,flowon
  3743.     mov    dl,flowoff
  3744.     mov    bx,srcpnt        ; address of destination buffer slot
  3745.     mov    si,rcv.scb_baddr    ; source of text
  3746.     cld
  3747.     lodsw                ; get internal length word
  3748.     mov    cx,rcv.scb_length    ; get block length
  3749.     mov    rcv.scb_length,0    ; clear counter
  3750.     sub    cx,2            ; data bytes remaining in block
  3751.     cmp    ax,cx            ; internal vs external count
  3752.     jae    acsrcv1            ; ae=internal is gt or equal to ext
  3753.     mov    cx,ax            ; use shorter internal count
  3754. acsrcv1:shr    cx,1            ; count words in block
  3755.     jcxz    acsrcv14        ; z = nothing there
  3756.  
  3757. acsrcv9:lodsw                ; get char+status bytes from rcvbuf
  3758.     test    ah,80h            ; status, is it a command?
  3759.     jnz    acsrcv12        ; nz = yes, ignore the pair
  3760.     test    flowcnt,2        ; using input XON/XOFF flow control?
  3761.     jz    acsrcv11        ; z = no
  3762.     mov    ah,al            ; get copy of character
  3763.     and    ah,parmsk        ; strip parity, if any, before testing
  3764.     cmp    ah,dl            ; acting on Xoff?
  3765.     jne    acsrcv10        ; ne = no
  3766.     cmp    xofsnt,0        ; have we sent an XOFF?
  3767.     jne    acsrcv12        ; ne = yes, ignore this XOFF char
  3768.     mov    xofrcv,bufon        ; set flag saying buffer XOFF received
  3769.     jmp    short acsrcv12        ;  and skip this character
  3770. acsrcv10:cmp    ah,dh            ; acting on XON?
  3771.     jne    acsrcv11        ; ne = no, go on
  3772.     mov    xofrcv,off        ; clear the XOFF received flag
  3773.     jmp    short acsrcv12        ;  and skip this character
  3774. acsrcv11:mov    [bx],al            ; store new char in buffer "source"
  3775.     inc    bx
  3776.     inc    count            ; add it to the count
  3777.     cmp    bx,offset source+bufsiz    ; pointing beyond end of buffer?
  3778.     jb    acsrcv12        ; b = no
  3779.     mov    bx,offset source    ; wrap pointer, modulo bufsiz
  3780. acsrcv12:loop    acsrcv9
  3781.  
  3782. acsrcv13:mov    srcpnt,bx        ; update pointer to next free slot
  3783.     cmp    count,bufsiz        ; count more that buffer size?
  3784.     jbe    acsrcv14        ; be = no
  3785.     mov    count,bufsiz        ; limit to bufsiz (tells the truth)
  3786. acsrcv14:pop    si
  3787.     pop    dx
  3788.     pop    cx
  3789.     stc                ; say no char in al from us
  3790.     ret
  3791. acsircv    endp
  3792.  
  3793. ; NetBios Receive post processing interrupt routine.
  3794. ; Sets rposted interlock flag
  3795. RPOST    PROC    NEAR        ; NetBios receive post interrupt routine
  3796.     push    ds
  3797.     push    ax
  3798.     mov    ax,data            ; reestablish data segment
  3799.     mov    ds,ax
  3800.     mov    rposted,2        ; set interlock flag to completed
  3801.     pop    ax
  3802.     pop    ds
  3803.     iret                ; return from interrupt
  3804. RPOST    endp
  3805.  
  3806. ; TES block mode receive, uses blkrcv to process results
  3807. TESRCV    proc    near
  3808.     push    di
  3809.     push    cx
  3810.     push    dx
  3811.     push    es
  3812.     mov    ax,data
  3813.     mov    es,ax            ; es:di will point to rcvbuf
  3814.     mov    di,offset rcvbuf
  3815.     mov    cx,nbuflen        ; buffer length
  3816.     mov    dx,tesport        ; operational port
  3817.     mov    ah,tesbread        ; block read
  3818.     int    rs232
  3819.     jcxz    tesrcv1            ; z = no characters read
  3820.     mov    rcv.scb_length,cx    ; prepare for receive call
  3821.     call    blkrcv            ; process rcvbuf
  3822.     jmp    short tesrcv2
  3823. tesrcv1:call    tesstate        ; get session status to AH
  3824.     and    ah,7fh            ; trim high bit (transition states)
  3825.     or    ah,ah            ; session active?
  3826.     jnz    tesrcv2            ; nz = yes, carry on
  3827.     call    tesclose        ; close our end
  3828. tesrcv2:pop    es
  3829.     pop    dx
  3830.     pop    cx
  3831.     pop    di
  3832.     stc                ; say not returning char in al here
  3833.     ret
  3834. TESRCV    endp
  3835.  
  3836. ; Ungermann-Bass NETCI port receive characters routine.  Receive one or more
  3837. ; characters.  Calls the blkrcv routine to transfer character to main source
  3838. ; circular buffer.  Return carry clear if success. 
  3839. UBRECV    PROC    near
  3840.     push    cx
  3841.     push    es
  3842.     mov    ax,data
  3843.     mov    es,ax            ; es:bx will point to rcvbuf
  3844.     mov    bx,offset rcvbuf
  3845.     mov    cx,nbuflen        ; buffer length
  3846. ubrecv2:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet interface?
  3847.     jz    ubrecv2a        ; z = no
  3848.     mov    ah,bapiread
  3849.     xor    dh,dh            ; session 0
  3850.     test    nettype,tcpnet        ; TCP/IP Telnet?
  3851.     jz    ubrecv2d        ; z = no
  3852.     call    ktcpcom            ; Far call Telnet code
  3853.     jmp    short ubrecv2e
  3854. ubrecv2d:int    bapiint
  3855.  
  3856. ubrecv2e:cmp    ah,3            ; status, no session and above
  3857.     jb    ubrecv3            ; b = no, successful?
  3858.     jmp    short ubrecv2b        ; broken connection, terminate it
  3859.  
  3860. ubrecv2a:test    nettype,telapi        ; Novell TELAPI?
  3861.     jz    ubrecv2c        ; z = no, use Int 6Bh kind
  3862. ;    cmp    pcnet,2            ; port going?
  3863. ;    jb    ubrec1            ; b = no
  3864.     push    si
  3865.     push    bx
  3866.     mov    si,bx            ; use es:si for buffer address
  3867.     mov    bx,telses        ; session number
  3868.     mov    ah,telread
  3869.     int    rs232
  3870.     pop    bx
  3871.     pop    si
  3872.     xchg    ax,cx            ; byte count returned in AX
  3873.     jcxz    ubrecv2b        ; z = connection broken
  3874.     or    cx,cx
  3875.     jns    ubrecv3            ; ns = no error
  3876.     cmp    cx,-35            ; status of no data?
  3877.     jne    ubrecv2b        ; ne = no
  3878.     xor    cx,cx            ; mimic no data
  3879.     jmp    short ubrec1
  3880. ubrecv2b:
  3881.     call    ubclose
  3882.     jmp    short ubrec1
  3883.  
  3884. ubrecv2c:test    nettype,netone        ; UB?
  3885.     jz    ubrec1            ; z = no, do nothing
  3886.     mov    ax, nciread        ; function 1 (receive) port 0     [ohl]
  3887.     int    netci            ; get characters         [ohl]
  3888. ubrecv3:jcxz    ubrec1            ; cx = z = nothing to do
  3889.     mov    rcv.scb_length,cx    ; prepare for rpost call
  3890.     call    blkrcv            ; process buffer
  3891. ubrec1:    pop    es
  3892.     pop    cx
  3893.     stc                ; say not returning char in al here
  3894.     ret
  3895. UBRECV    ENDP
  3896.  
  3897. ; Beame & Whiteside TCP receive routine [JRS]
  3898. bwrecv    proc    near            ; [JRS]
  3899.     test    nettype,bwtcp        ; active?
  3900.     jnz    bwrecv1            ; nz = yes
  3901.     stc
  3902.     ret
  3903.  
  3904. bwrecv1:push    di            ; [JRS] save the environment
  3905.     push    si            ; [JRS]
  3906.     push    dx            ; [JRS]
  3907.     push    cx            ; [JRS]
  3908.     push    bx            ; [JRS]
  3909.     mov    ah,readf2        ; [JRS] read from "file"
  3910.     mov    bx,bwhandle        ; [JRS] device handle
  3911.     or    bx,bx
  3912.     jz    bwrecv4            ; z = invalid handle
  3913.     mov    cx,nbuflen-4        ; number of bytes to read - safety
  3914.     mov    dx,offset rcvbuf    ; [JRS] data buffer is DS:DX
  3915.     int    dos            ; [JRS] ask dos to get it
  3916.     jc    bwrecv5            ; [JRS] c = no data available
  3917.     mov    cx,ax            ; [JRS] get the number of bytes read
  3918.     jcxz    bwrecv4            ; [JRS] no chars read is a hangup
  3919.     cmp    ax,nbuflen-4        ; check on sanity
  3920.     ja    bwrecv5            ; a = error of some kind, ignore
  3921.     mov    si,offset rcvbuf
  3922.     call    bwtnopt            ; do options scanning
  3923.     jmp    short bwrecv5
  3924. bwrecv4:call    bwclose            ; read failed, quit
  3925. bwrecv5:pop    bx            ; [JRS] restore environment
  3926.     pop    cx            ; [JRS]
  3927.     pop    dx            ; [JRS]
  3928.     pop    si            ; [JRS]
  3929.     pop    di            ; [JRS]
  3930.     stc                ; [JRS] flag no characters read
  3931.     ret                ; [JRS]
  3932. bwrecv    endp                ; [JRS]
  3933.  
  3934. ; Beame & Whiteside telnet options scanner and processor
  3935. ; Enter with newly read material in ds:si, of length CX bytes
  3936. bwtnopt    proc    near
  3937.     or    cx,cx
  3938.     jle    bwtnopt1        ; le = nothing to do
  3939.     cmp    optstate,0        ; outside IAC string?
  3940.     je    bwtnopt2        ; e = yes
  3941.     jmp    bwtnopt20        ; do options
  3942. bwtnopt1:ret
  3943.  
  3944. bwtnopt2:push    cx
  3945.     push    es
  3946.     mov    ax,seg rcvbuf        ; make es:di the receiver buffer
  3947.     mov    es,ax
  3948.     mov    di,si
  3949.     mov    al,IAC            ; IAC
  3950.     cld
  3951.     repne    scasb            ; look for IAC
  3952.     pop    es
  3953.     pop    cx
  3954.     mov    ax,di            ; points one byte after break
  3955.     jne    bwtnopt3        ; ne = no IAC
  3956.     dec    ax            ; backup to IAC
  3957. bwtnopt3:sub    ax,si            ; minus starting offset
  3958.     sub    cx,ax            ; original count - <before IAC>
  3959.     mov    rcv.scb_length,ax    ; data length before IAC
  3960.     mov    rcv.scb_baddr,si     ; source of text
  3961.     add    si,ax            ; starting point for IAC
  3962.     or    ax,ax            ; any leading text?
  3963.     jz    bwtnopt4        ; z = nothing to block receive upon
  3964.     call    blkrcv            ; dispose of it, saves si and cx
  3965. bwtnopt4:or    cx,cx            ; bytes remaining in buffer
  3966.     jg    bwtnopt5        ; if positive then si == IAC byte
  3967.     xor    cx,cx            ; force zero
  3968.     ret
  3969. bwtnopt5:inc    si
  3970.     dec    cx            ; skip IAC
  3971.     mov    optstate,2        ; read two more chars
  3972.     jmp    bwtnopt            ; repeat
  3973.  
  3974. bwtnopt20:cmp    optstate,2        ; reading 1st char after IAC?
  3975.     jb    bwtnopt23        ; b = no
  3976.     dec    cx            ; read the char
  3977.     lodsb
  3978.     cmp    al,SB            ; before legal options?
  3979.     jae    bwtnopt22        ; ae = no
  3980.     inc    si            ; recover char
  3981.     inc    cx
  3982.     mov    optstate,0        ; clear Options machine
  3983.     jmp    bwtnopt            ; continue
  3984.  
  3985. bwtnopt22:mov    option1,al        ; save first Option byte
  3986.     mov    optstate,1        ; get one more byte
  3987.     jmp    bwtnopt            ; get the second Options byte
  3988.  
  3989. bwtnopt23:mov    optstate,0        ; read second char after IAC
  3990.     dec    cx            ; read the char
  3991.     lodsb
  3992.     mov    option2,al        ; second options byte
  3993.     mov    ah,option1
  3994.     mov    bx,portval
  3995.     mov    bl,[bx].ecoflg        ; echo status
  3996.                     ; decode options and respond
  3997.     cmp    al,TELOPT_ECHO        ; Echo?
  3998.     jne    bwtnopt30        ; ne = no
  3999.     cmp    ah,WILL            ; remote host will echo?
  4000.     jne    bwtnopt26        ; ne = no
  4001.     cmp    bl,0            ; are we doing local echo?
  4002.     je    bwtnopt29        ; e = no
  4003.     mov    ah,DO            ; say please echo
  4004.     call    bwsendiac
  4005.     xor    bl,bl            ; say we should not echo
  4006.     call    setecho            ; set our echo state
  4007.     jmp    bwtnopt
  4008. bwtnopt26:cmp    ah,WONT            ; remote host won't supply echo?
  4009.     jne    bwtnopt28        ; ne = no
  4010.     cmp    bl,0            ; are we doing local echo?
  4011.     jne    bwtnopt29        ; ne = yes
  4012.     mov    ah,DONT
  4013.     call    bwsendiac
  4014.     mov    bl,lclecho        ; do local echoing
  4015.     call    setecho            ; set local echoing state
  4016.     jmp    bwtnopt
  4017.  
  4018. bwtnopt28:cmp    ah,DO            ; remote host wants us to echo?
  4019.     jne    bwtnopt29        ; ne = no
  4020.     mov    ah,WONT            ; decline
  4021.     call    bwsendiac
  4022. bwtnopt29:jmp    bwtnopt
  4023.  
  4024. bwtnopt30:cmp    al,TELOPT_SGA        ; SGA?
  4025.     jne    bwtnopt40        ; ne = no
  4026.     cmp    ah,WONT            ; host won't do SGAs?
  4027.     jne    bwtnopt33        ; ne = no
  4028.     cmp    sgaflg,0        ; our state is don't too?
  4029.     jne    bwtnopt35        ; ne = yes
  4030.     inc    sgaflg            ; change state
  4031.     mov    ah,DONT            ; say please don't
  4032.     call    bwsendiac
  4033.     cmp    bl,0            ; doing local echo?
  4034.     jne    bwtnopt35        ; ne = yes
  4035.     mov    bl,lclecho        ; change to local echoing
  4036.     call    setecho
  4037.     jmp    bwtnopt            ; continue
  4038. bwtnopt33:cmp    ah,WILL            ; host will use Go Aheads?
  4039.     jne    bwtnopt35        ; ne = no
  4040.     cmp    sgaflg,0        ; doing SGAs?
  4041.     jne    bwtnopt35        ; ne = no
  4042.     mov    sgaflg,0        ; change to doing them
  4043.     mov    ah,DO
  4044.     call    bwsendiac
  4045. bwtnopt35:jmp    bwtnopt
  4046.  
  4047. bwtnopt40:cmp    ah,WILL            ; all other Options
  4048.     jne    bwtnopt41        ; ne = no
  4049.     mov    ah,DONT            ; say do not
  4050.     call    bwsendiac        ; respond
  4051.     jmp    bwtnopt43        ; continue
  4052. bwtnopt41:cmp    ah,DO
  4053.     jne    bwtnopt42
  4054.     mov    ah,WONT            ; say we won't
  4055.     call    bwsendiac
  4056.     mov    ah,DONT            ; and host should not either
  4057.     call    bwsendiac
  4058.     jmp    bwtnopt43        ; continue
  4059. bwtnopt42:cmp    ah,DONT
  4060.     jne    bwtnopt43
  4061.     mov    ah,WONT            ; say we won't
  4062.     call    bwsendiac
  4063. bwtnopt43:jmp    bwtnopt            ; continue
  4064. bwtnopt endp
  4065.  
  4066. ; Beame & Whiteside, send IAC byte1 byte2, where byte 1 is in AH
  4067. ; and byte 2 is in option2
  4068. bwsendiac proc    near
  4069.     push    cx
  4070.     push    si
  4071.     push    ax
  4072.     mov    ah,IAC            ; send IAC
  4073.     call    outchr
  4074.     pop    ax            ; send command byte
  4075.     call    outchr
  4076.     mov    ah,option2        ; send response byte
  4077.     call    outchr
  4078.     pop    si
  4079.     pop    cx
  4080.     ret
  4081. bwsendiac endp
  4082.  
  4083. ; Update local-echo status from B&W Telnet Options negotiations
  4084. ; Enter with BL = 0 or lclecho, to clear or set local-echo
  4085. setecho    proc    near
  4086.     and    yflags,not lclecho    ; assume no local echo in emulator
  4087.     or    yflags,bl        ; set terminal emulator
  4088.     push    si
  4089.     mov    si,portval
  4090.     mov    [si].ecoflg,bl        ; set mainline SET echo flag
  4091.     pop    si
  4092.     cmp    ttyact,0        ; acting as a Terminal?
  4093.     je    setecho1        ; e = no
  4094.     push    cx
  4095.     push    si
  4096.     call    dword ptr ftogmod    ; toggle mode line
  4097.     call    dword ptr ftogmod    ; and again
  4098.     pop    si
  4099.     pop    cx
  4100. setecho1:ret
  4101. setecho    endp
  4102.  
  4103. ; Put the char in AH to the serial port, assumimg the port is active.
  4104. ; Returns carry clear if success, else carry set.
  4105. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  4106. ; prevent confusion of flow control logic at top of outchr; used by receiver
  4107. ; buffer high/low water mark flow control code. [jrd]
  4108. outchr    proc    near
  4109.     cmp    quechar,0        ; char queued for transmission?
  4110.     je    outch0            ; e = no, no XOFF queued
  4111.     xchg    ah,quechar        ; save current char
  4112.     cmp    ah,flowoff        ; really XOFF?
  4113.     jne    outch0a            ; ne = no
  4114.     mov    xofsnt,bufon           ; we are senting XOFF at buffer level
  4115. outch0a:call    outch2            ; send queued char (XOFF usually)
  4116.     xor    ah,ah            ; replacement for queued char, none
  4117.     xchg    ah,quechar        ; recover current char, send it
  4118. outch0:    test    flowcnt,1        ; doing output XON/XOFF flow control?
  4119.     jz    outch1b            ; z = no, just continue
  4120.     cmp    ah,flowoff        ; sending xoff?
  4121.     jne    outch1            ; ne = no
  4122.     mov    xofsnt,usron        ; indicate user level xoff being sent
  4123.     jmp    short outch1b
  4124. outch1:    and    xofsnt,not usron    ; cancel user level xoff
  4125.     cmp    ah,flowon        ; user sending xon?
  4126.     jne    outch1b            ; ne = no
  4127.     mov    xofsnt,off         ; say an xon has been sent (cancels xoff)
  4128. outch1b:test    flowcnt,2        ; using incoming xon/xoff?
  4129.     jz    outch2            ; z = no
  4130.     cmp    xofrcv,off        ; are we being held (xoff received)?
  4131.     je    outch2            ; e = no - it's OK to go on
  4132.     push    cx            ; save reg
  4133.     mov    ch,15            ; 15 sec timeout interval
  4134.     xor    cl,cl            ;  convert to 4 millsec increments
  4135.  
  4136. outch1a:cmp    xofrcv,off        ; are we being held (xoff received)?
  4137.     je    outch1c            ; e = no - it's OK to go on
  4138.     push    ax
  4139.     mov    ax,4            ; 4 millisec wait loop
  4140.     call    pcwait
  4141.     pop    ax
  4142.     loop    outch1a            ; and try it again
  4143.     mov    xofrcv,off        ; timed out, force it off
  4144.     cmp    ttyact,0        ; in Connect mode?
  4145.     je    outch1c            ; e = no
  4146.     push    ax            ; save char around the call
  4147.     call    beep            ; let user know we are xoff-ed
  4148.     pop    ax            ;  but are sending anyway
  4149. outch1c:pop    cx            ; end of flow control section
  4150.              ; OUTCH2 is entry point for sending without flow control
  4151. OUTCH2:    mov    al,ah            ; Parity routine works on AL
  4152.     call    dopar            ; Set parity appropriately
  4153.     mov    ah,al            ; Don't overwrite character with status
  4154.     cmp    repflg,0        ; doing REPLAY from a file?
  4155.     je    outch3            ; e = no
  4156.     and    al,7fh            ; strip parity
  4157.     cmp    al,'C'-40h        ; Control-C? (to exit playback mode)
  4158.     je    outch2a            ; e = yes, return failure
  4159.     clc                ; return success, send nothing
  4160.     ret
  4161. outch2a:stc                ; failure, to exit playback mode
  4162.     ret
  4163. outch3:    push    bx
  4164.     mov    bx,portval        ; output char is in register AH
  4165.     call    [bx].sndproc        ; output processing routine
  4166.     pop    bx
  4167.     ret
  4168. outchr    endp
  4169.  
  4170. uartsnd    proc    near            ; UART send
  4171.     push    cx
  4172.     push    dx
  4173.     mov    dx,modem.mddat
  4174.     add    dx,4            ; modem control reg 3fch
  4175.     cmp    dupflg,0        ; full duplex?
  4176.     jne    uartsn1            ; ne = no, half
  4177.     test    flowcnt,4        ; using RTS to control incoming chars?
  4178.     jz    uartsn3            ; z = no
  4179.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  4180.     add    dx,2            ; modem status reg 3feh
  4181.     jmp    short uartsn2        ; do CTS test/waiting
  4182.                     ; Half Duplex here
  4183. uartsn1:in    al,dx            ; modem control reg 3fch
  4184.     or    al,2            ; assert RTS for hardware transmit
  4185.     push    ax
  4186.     in    al,ppi_port        ; delay
  4187.     pop    ax
  4188.     out    dx,al
  4189.     add    dx,2            ; modem status register 3feh
  4190.     in    al,ppi_port        ; delay
  4191.     in    al,ppi_port        ; delay
  4192.     in    al,dx            ; get DSR status
  4193.     test    al,20h            ; ignore CTS if DSR is not asserted
  4194.     jz    uartsn3            ; z = DSR not asserted
  4195.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  4196.                     ; Half Duplex and RTS/CTS flow cont.
  4197. uartsn2:in    al,dx            ; wait on CTS (ah has output char)
  4198.     test    al,10h            ; is CTS asserted? (dx = 3feh)
  4199.     jnz    uartsn3            ; nz = yes
  4200.     push    ax            ; preserve char in ah
  4201.     mov    ax,1            ; wait one millisec
  4202.     call    pcwait
  4203.     pop    ax
  4204.     loop    uartsn2            ; test again
  4205.     push    ax
  4206.     call    beep            ; timeout, make non-fatal
  4207.     pop    ax            ; continue to send the char
  4208.  
  4209. uartsn3:mov    bx,portval
  4210.     cmp    [bx].baud,Bsplit    ; split-speed mode?
  4211.     jne    uartsn4            ; ne = no
  4212.     mov     al,ah                   ; [pslms]
  4213.         call    out75b            ; do split speed sending at 75 baud
  4214.         pop     dx
  4215.         pop     cx
  4216.     ret                ; out75b sets/clears carry bit
  4217.  
  4218. uartsn4:xor    cx,cx
  4219. uartsn4a:mov    dx,modem.mdstat        ; get port status
  4220.     in    al,dx
  4221.     test    al,20H            ; Transmitter (THRE) ready?
  4222.     jnz    uartsn5            ; nz = yes
  4223.     in    al,ppi_port        ; delay
  4224.     in    al,ppi_port        ; delay
  4225.     loop    uartsn4a
  4226.     jmp    short uartsn8        ; Timeout
  4227. uartsn5:mov    al,ah            ; Now send it out
  4228.     mov    dx,modem.mddat        ; use a little time
  4229.     push    ax
  4230.     in    al,ppi_port        ; delay
  4231.     pop    ax
  4232.     out    dx,al
  4233.     cmp    dupflg,0        ; full duplex?
  4234.     je    uartsn7            ; e = yes
  4235.     cmp    al,trans.seol        ; End of Line char?
  4236.     jne    uartsn7            ; ne = no
  4237.     xor    cx,cx            ; loop counter
  4238. uartsn6:mov    dx,modem.mdstat        ; modem line status reg
  4239.     in    al,dx            ; read transmitter shift reg empty bit
  4240.     push    ax
  4241.     in    al,ppi_port        ; delay, wait for char to be sent
  4242.     in    al,ppi_port
  4243.     in    al,ppi_port
  4244.     in    al,ppi_port
  4245.     pop    ax
  4246.     test    al,40h            ; is it empty?
  4247.     loopz    uartsn6            ; z = no, not yet
  4248.     mov    dx,modem.mddat
  4249.     add    dx,4            ; modem control reg 3fch
  4250.     in    al,dx
  4251.     and    al,not 2        ; unassert RTS
  4252.     push    ax
  4253.     in    al,ppi_port        ; delay
  4254.     pop    ax
  4255.     out    dx,al
  4256. uartsn7:pop    dx            ; exit success
  4257.     pop    cx
  4258.     clc
  4259.     ret
  4260. uartsn8:call    beep
  4261.     pop    dx            ; exit failure
  4262.     pop    cx
  4263.     stc
  4264.     ret
  4265. uartsnd    endp
  4266.  
  4267. biossnd    proc    near            ; Bios send
  4268.     push    cx            ; find current port
  4269.     mov    cx,5            ; retry counter
  4270.     push    dx
  4271.     xor    dx,dx            ; assume port 1
  4272.     mov    dl,flags.comflg        ; get port number (1..4)
  4273.     or    dl,dl            ; zero (no such port)?
  4274.     jz    biossn3            ; z = yes, don't access it
  4275.     and    dl,7            ; use lower three bits
  4276.     dec    dl            ; address ports as 0..3 for Bios
  4277.     mov    al,ah            ; now send it out
  4278. biossn2:push    ax            ; save char
  4279.     mov    ah,1            ; send char
  4280.     int    rs232            ; bios send
  4281.     shl    ah,1            ; set carry if failure
  4282.     pop    ax            ; recover char
  4283.     jnc    biossn4            ; nc = success
  4284.     push    ax
  4285.     mov    ax,60            ; wait 60 ms
  4286.     call    pcwait            ; this must preserve cx and dx
  4287.     pop    ax            ; recover char
  4288.     loop    biossn2            ; try again
  4289. biossn3:stc                ; fail through here
  4290. biossn4:pop    dx
  4291.     pop    cx
  4292.     ret                ; c set = failure, else success
  4293. biossnd    endp
  4294.  
  4295. ebisnd    proc    near            ; EBIOS block send
  4296.     mov    bx,xmtcnt        ; count of chars in buffer
  4297.     mov    xmtbufx[bx],ah        ; put char in buffer
  4298.     inc    xmtcnt            ; count of items in this buffer
  4299.     and    ah,7fh            ; strip parity
  4300.     cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  4301.     jae    ebisnd2            ; ae = buffer is full, send it now
  4302.     cmp    ah,trans.seol        ; end of packet?
  4303.     je    ebisnd2            ; e = yes, send buffer
  4304.     test    flowcnt,1        ; using output XON/XOFF flow control?
  4305.     jz    ebisnd1            ; z = no
  4306.     cmp    ah,flowon        ; flow control?
  4307.     je    ebisnd2            ; e = yes, always expedite
  4308.     cmp    ah,flowoff        ; ditto for flow off
  4309.     je    ebisnd2
  4310. ebisnd1:cmp    ttyact,0        ; are we in Connect mode?
  4311.     jne    ebisnd2            ; ne = yes, send now
  4312.     clc                ; e = no, wait for more before sending
  4313.     ret
  4314. ebisnd2:push    si
  4315.     mov    si,offset xmtbufx
  4316. ebisnd3:cmp    xmtcnt,0        ; buffer count
  4317.     jle    ebisnd4            ; le = nothing to send
  4318.     cld
  4319.     lodsb                ; read next byte from buffer
  4320.     push    si
  4321.     mov    ah,ebsend        ; EBIOS send char in AL
  4322.     mov    dx,ebport        ; port 0..3, do here to waste time
  4323.     int    rs232            ; bios send
  4324.     pop    si
  4325.     shl    ah,1            ; put status high bit into carry
  4326.     jc    ebisnd4            ; c = failure
  4327.     dec    xmtcnt
  4328.     jmp    short ebisnd3
  4329. ebisnd4:pop    si
  4330.     ret                ; c set = failure, else success
  4331. ebisnd    endp
  4332.  
  4333. decsnd    proc    near            ; DECnet/LAT send processor
  4334.     test    nettype,declat        ; LAT?
  4335.     jz    decsnd3            ; z = no, use CTERM
  4336.     mov    cx,100            ; retry counter
  4337.     mov    byte ptr temp,ah    ; outgoing char
  4338. decsnd1:mov    dx,lathand        ; LAT handle
  4339.     or    dx,dx            ; legal handle?
  4340.     jz    decsnd4            ; z = invalid handle
  4341.     push    cx
  4342.     mov    al,byte ptr temp
  4343.     mov    ah,latsend        ; LAT send byte
  4344.     int    latint
  4345.     pop    cx
  4346.     or    ah,ah            ; status
  4347.     jnz    decsnd2            ; nz = failed, check
  4348.     clc
  4349.     ret
  4350. decsnd2:mov    ah,latstat        ; status call
  4351.     mov    dx,lathand        ; handle
  4352.     push    cx
  4353.     int    latint
  4354.     pop    cx
  4355.     test    ah,4            ; session active?
  4356.     jnz    decsnd4            ; nz = no, fail
  4357.     mov    ax,10            ; wait 10 millisecs
  4358.     call    pcwait
  4359.     loop    decsnd1            ; retry
  4360.     jmp    short decsnd4        ; fail outright
  4361.  
  4362. decsnd3:mov    dx,decneth        ; DECnet, handle
  4363.     or    dx,dx            ; legal handle?
  4364.     jz    decsnd4            ; z = invalid handle
  4365.     mov    bl,ah            ; CTERM char to be sent
  4366.     mov    ax,dsend        ; send byte in bl
  4367.     int    decint
  4368.     rcl    ah,1            ; status 80h bit, did char get sent?
  4369.     jc    decsnd4            ; c = failure
  4370.     ret
  4371. decsnd4:call    decclose        ; failure, close connection
  4372.     stc
  4373.     ret
  4374. decsnd    endp
  4375.  
  4376. ; Software uart that generates output rate of 75 baud independently of
  4377. ; 8250 baudrate; use with V.23 split speed modems.
  4378. ; This routine outputs a character in 8,<parity>,1 format only.
  4379. ; To generate good bit timing, latency is to be kept low; now set for max
  4380. ; 12% bit distortion and 1.2% speed deviation (about the same as the input
  4381. ; stage of a HW-uart), which requires latency < 3ms (i e the same as 8250
  4382. ;  requires for receive in 9600 baud)
  4383. ; Creator Dan Norstedt 1987. Implemented 18 Feb 1988 by [pslms].
  4384. out75b    proc    near
  4385.     mov    timeract,1    ; say we are allocating the timer chip
  4386.     push    cx
  4387.     push    dx
  4388.     xchg    ax,bx        ; save char to output
  4389.     mov    bh,1        ; prepare output char
  4390.     mov    cx,cnt75b    ; maximum end count
  4391. out75b1:call    read_timer2    ; save previous end count in CX, read timer
  4392.                 ;  test for timer still decrementing ?
  4393.         jb    out75b1        ; b = yes, wait (for a maximum of 1 bit)
  4394.         mov    al,0b4h        ; set up counter 2 to mode 2, load LSB+MSB
  4395.         out    timercmd,al    ; set mode 2 = rate generator
  4396.         jmp    $+2
  4397.         mov    ax,cnt75b*4+cnt75b*4+cnt75b*2-precomp  ; set start point
  4398.         out    timer2data,al    ; output LSB
  4399.         jmp    $+2
  4400.         xchg    cx,ax        ; save value in CX for compare in READ_TIMER2
  4401.         mov    al,ch        ; output MSB
  4402.         cli            ; timer starts counting on next instr, make
  4403.         out    timer2data,al    ;  sure it's not to far of from start bit
  4404.         in     al,ppi_port    ; get Port B contents
  4405.         jmp    $+2
  4406.         and    al,0fch        ; mask speaker and gate 2 bits
  4407.         inc    ax
  4408.         out    ppi_port,al    ; set speaker off and gate 2 on
  4409.         mov    al,-1
  4410.         out    timer2data,al    ; set counter wraparound to 0FFFFH
  4411.         jmp    $+2
  4412.         out    timer2data,al
  4413.         mov    bp,cnt75b*4+cnt75b*4+cnt75b ; set timer value for next bit
  4414.         mov    dx,modem.mddat    ; get com port address
  4415.         add    dx,3        ; address of it's line control register
  4416.         in     al,dx        ; get port status
  4417.         jmp    $+2
  4418. out75b2:or    al,brkbit    ; set line to space (by using break bit)
  4419. out75b3:out    dx,al        ; once start bit is out, we may reenable
  4420.         sti            ;  without getting extra jitter
  4421. out75b4:call    read_timer2
  4422.     jns    out75b5        ; ns = timer doesn't seem to run
  4423.     cmp    ax,bp        ; time for next bit?
  4424.     jns    out75b4        ; ns = no, wait
  4425.     sub    bp,cnt75b    ; yes, step time to next event
  4426.     in     al,dx        ; get line control register
  4427.     and    al,0bfh        ; remove break bit
  4428.     shr    bx,1        ; carry for mark bit, none for space
  4429.     jnc    out75b2        ; nc = it was a space (we know BX is non-zero)
  4430.     jnz    out75b3        ; mark, and not the last one
  4431.     jmp    $+2
  4432.     out    dx,al        ; last, start to send stop bit
  4433.     pop    dx
  4434.     pop    cx
  4435.     mov    timeract,0    ; say we are finished with the timer chip
  4436.     cmp    quechar,0    ; any char queued to be sent?
  4437.     je    out75b6        ; e = no
  4438.     call    outchr        ; yes, send it now
  4439. out75b6:clc
  4440.     ret
  4441. out75b5:in    al,dx        ; timer doesn't function properly,
  4442.     and    al,0bfh        ;  restore com port and return error
  4443.     out    dx,al
  4444.     mov    timeract,0    ; say we are finished with the timer chip
  4445.     pop    dx
  4446.     pop    cx
  4447.     stc
  4448.         ret
  4449. out75b    endp
  4450.      
  4451. read_timer2    proc    near
  4452.     mov     al,80h          ; Freeze timer 2
  4453.     out     timercmd,al
  4454.     jmp     $+2
  4455.     in      al,timer2data   ; Get LSB
  4456.     jmp     $+2
  4457.     mov     ah,al
  4458.     in      al,timer2data   ; Get MSB
  4459.     xchg    al,ah           ; Get LSB and MSB right
  4460.     cmp     ax,cx           ; Compare to previous sample
  4461.     mov     cx,ax           ; Replace previous sample with current
  4462.     ret
  4463. read_timer2 endp
  4464.  
  4465. ; NetBios Send packet routine. Send xmt scb with no-wait option. Waits
  4466. ; up to 6 seconds for current Send to complete before emitting new Send.
  4467. ; Failure to Send resets serial port (Server mode allows reiniting of serial
  4468. ; port). Returns carry clear for success, carry set for failure.
  4469. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  4470. SEND    PROC    NEAR            ; Network. Send session packet
  4471.     mov    bx,xmtcnt        ; count of chars in buffer
  4472.     test    nettype,acsi        ; ACSI?
  4473.     jz    send32            ; z = no
  4474.     or    bx,bx            ; at start of buffer?
  4475.     jnz    send31            ; nz = no
  4476.     mov    bx,2            ; include internal count word
  4477.     mov    word ptr xmtbufx,bx
  4478.     mov    xmtcnt,bx
  4479. send31:    mov    xmtbufx[bx+1],0        ; status
  4480.     inc    xmtcnt
  4481.     add    word ptr xmtbufx,2    ; internal count word
  4482. send32:
  4483.     mov    xmtbufx[bx],ah        ; put char in buffer
  4484.     inc    xmtcnt            ; count of items in this buffer
  4485.     and    ah,7fh            ; strip parity
  4486.     cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  4487.     jae    send22            ; ae = buffer is full, send it now
  4488.     test    nettype,acsi        ; ACSI?
  4489.     jz    send33            ; z = no
  4490.     cmp    xmtcnt,512        ; ACSI has hard 512 byte limit
  4491.     jb    send33            ; b = not full yet
  4492.     mov    xmtcnt,512        ; limit buffer
  4493.     jmp    short send22        ; send only this buffer
  4494. send33:    cmp    ah,trans.seol        ; end of packet?
  4495.     je    send22            ; e = yes, send buffer
  4496.     test    flowcnt,1        ; using output XON/XOFF flow control?
  4497.     jz    send21            ; z = no
  4498.     cmp    ah,flowon        ; flow control?
  4499.     je    send22            ; e = yes, always expedite
  4500.     cmp    ah,flowoff        ; ditto for flow off
  4501.     je    send22
  4502. send21:cmp    ttyact,0        ; are we in Connect mode?
  4503.     jne    send22            ; ne = yes, send now
  4504.     clc                ; e = no, wait for more before sending
  4505.     ret
  4506. send22:    cmp    pcnet,1            ; network ready yet?
  4507.     ja    send0b            ; a = net is operational
  4508.     je    send0c            ; e = net but no session, fail
  4509.     jmp    send3a            ; no net, fail
  4510. send0c:    jmp    send3            ; net but no session
  4511. send0b:    cmp    sposted,0        ; is a send outstanding now?
  4512.     je    send1            ; e = no, go ahead
  4513.     push    cx            ; Timed test for old send being done
  4514.     mov    ch,trans.rtime        ; receive timeout other side wants
  4515.     mov    cl,80h            ; plus half a second
  4516.     shl    cx,1            ; sending timeout * 512
  4517. send0:    cmp    sposted,0        ; is a send outstanding now?
  4518.     je    send0a            ; e = no, clean up and do send
  4519.     push    cx            ; save cx
  4520.     push    ax            ; and ax
  4521.     mov    ax,2            ; wait 2 milliseconds
  4522.     call    pcwait            ;  between retests
  4523.     pop    ax
  4524.     pop    cx            ; loop counter
  4525.     loop    send0            ; repeat test
  4526.     pop    cx            ; recover cx
  4527.     jmp    send3a            ; get here on timeout, can't send
  4528. send0a:    pop    cx            ; recover cx and proceed to send
  4529.  
  4530. send1:    cmp    xmtcnt,0        ; number of items to send
  4531.     jne    send1a            ; ne = some
  4532.     clc                ; else don't send null packets
  4533.     ret
  4534. send1a:    push    cx            ; save these regs
  4535.     push    si
  4536.     push    di
  4537.     push    es
  4538.     push    ds
  4539.     pop    es            ; set es to data segment
  4540.     mov    si,offset xmtbufx    ; external buffer
  4541.     mov    di,offset xmtbuf    ; copy for network packets
  4542.     mov    cx,xmtcnt        ; buffer length
  4543.     mov    xmt.scb_length,cx    ; tell buffer length
  4544.     shr    cx,1            ; divide by two (words), set carry
  4545.     jnc    send2            ; nc = even number of bytes
  4546.     movsb                ; do single move
  4547. send2:    rep    movsw            ; copy the data
  4548.     pop    es
  4549.     pop    di
  4550.     pop    si
  4551.     pop    cx
  4552.     mov    xmtcnt,0        ; say xmtbufx is available again
  4553.     mov    xmt.scb_cmd,nsend+nowait ; send, don't wait for completion
  4554.     mov    sposted,1        ; say send posted
  4555.     mov    bx,offset xmt        ; set pointer to scb
  4556.     call    nbsession
  4557.                     ; success or failure?
  4558.     cmp    xmt.scb_err,0        ; good return?
  4559.     je    send4            ; e = yes
  4560.     cmp    xmt.scb_err,npending    ; pending?
  4561.     je    send4            ; e = yes
  4562.     cmp    xmt.scb_err,18h        ; session ended abnormally?
  4563.     jbe    send3            ; e = yes, b = other normal errors
  4564.     push    ax
  4565.     push    dx            ; another kind of error, show message
  4566.     mov    ah,prstr
  4567.     mov    dx,offset sndmsg    ; say send failed
  4568.     int    dos
  4569.     mov    al,xmt.scb_err        ; show error code
  4570.     call    decout
  4571.     pop    dx
  4572.     pop    ax
  4573.                     ; Error return
  4574. send3:    call    nbclose            ; close connection
  4575.     test    flags.remflg,dserver    ; server mode?
  4576.     jz    send3a            ; z = no
  4577.     call    serini            ; reinitialize it for new session
  4578. send3a:    stc                ; set carry for failure to send
  4579.     ret
  4580. send4:    clc
  4581.     ret
  4582. SEND    ENDP
  4583.  
  4584. ; NetBios Send packet completion interrupt routine. At entry CS is our
  4585. ; code segment, es:bx points to scb, netbios stack, interrupts are off.
  4586. SPOST    PROC    NEAR            ; post routine for Send packets
  4587.     push    ds
  4588.     push    ax
  4589.     mov    ax,data
  4590.     mov    ds,ax
  4591.     mov    sposted,0        ; clear send interlock
  4592.     pop    ax
  4593.     pop    ds
  4594.     iret
  4595. SPOST    ENDP    
  4596.  
  4597. ; TES block send. Destroys BX
  4598. TESSND    proc    near
  4599.     mov    bx,xmtcnt        ; count of chars in buffer
  4600.     mov    xmtbufx[bx],ah        ; put char in buffer
  4601.     inc    xmtcnt            ; count of items in this buffer
  4602.     and    ah,7fh            ; strip parity
  4603.     cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  4604.     jae    tessen22        ; ae = buffer is full, send it now
  4605.     cmp    ah,trans.seol        ; end of packet?
  4606.     je    tessen22        ; e = yes, send buffer
  4607.     test    flowcnt,1        ; using output XON/XOFF flow control?
  4608.     jz    tessen21        ; z = no
  4609.     cmp    ah,flowon        ; flow control?
  4610.     je    tessen22        ; e = yes, always expedite
  4611.     cmp    ah,flowoff        ; ditto for flow off
  4612.     je    tessen22
  4613. tessen21:cmp    ttyact,0        ; are we in Connect mode?
  4614.     jne    tessen22        ; ne = yes, send now
  4615.     clc                ; e = no, wait for more before sending
  4616.     ret
  4617.  
  4618. tessen22:push    ax
  4619.     push    cx
  4620.     push    dx
  4621.     push    di
  4622.     push    es
  4623.     mov    cx,xmtcnt        ; number of chars
  4624.     jcxz    tessnd4            ; don't send zero chars
  4625.     mov    di,offset xmtbufx    ; buffer address in es:di
  4626.     mov    ax,data
  4627.     mov    es,ax
  4628. tessnd1:mov    temp,0            ; retry counter
  4629. tessnd2:mov    ah,tesbwrite        ; block write
  4630.     mov    dx,tesport        ; operational port
  4631.     int    rs232
  4632.     or    ax,ax            ; number of chars sent, zero?
  4633.     jnz    tessnd3            ; nz = sent some
  4634.     mov    ax,10            ; wait 10ms
  4635.     call    pcwait
  4636.     inc    temp            ; count retry
  4637.     cmp    temp,5            ; done all retries?
  4638.     jb    tessnd2            ; b = no
  4639.     call    tesclose        ; close sessioin, declare failure
  4640.     stc
  4641.     jmp    short tessnd5        ; exit failure
  4642.  
  4643. tessnd3:cmp    ax,cx            ; check that all characters were sent
  4644.     je    tessnd4            ; e = yes
  4645.     add    di,ax            ; point to remaining chars
  4646.     sub    cx,ax            ; count of remaining characters
  4647.     mov    xmtcnt,cx        ; need count in xmtcnt too
  4648.     jmp    short tessnd1        ; try again to send
  4649. tessnd4:clc                ; success, need failure case too
  4650. tessnd5:mov    xmtcnt,0
  4651.     pop    es
  4652.     pop    di
  4653.     pop    dx
  4654.     pop    cx
  4655.     pop    ax
  4656.     ret
  4657. TESSND    endp
  4658.  
  4659. ; Block send routine shared by many networks.
  4660. ; Enter with char to be sent in AH. Destroys BX.
  4661. ubsend    proc    near
  4662.     mov    bx,xmtcnt        ; count of chars in buffer
  4663.     mov    xmtbufx[bx],ah        ; put char in buffer
  4664.     inc    xmtcnt            ; count of items in this buffer
  4665.     and    ah,parmsk        ; strip parity
  4666.     test    nettype,tcpnet        ; TCP/IP Telnet?
  4667.     jz    ubsen24            ; z = no
  4668.     cmp    ah,CR            ; carriage return?
  4669.     jne    ubsen24            ; ne = no
  4670.     cmp    xmtcnt,length xmtbuf    ; is buffer full?
  4671.     jb    ubsen22            ; b = no, else take special setps
  4672.     call    ubsen28            ; send what we have now
  4673. ubsen22:mov    bx,xmtcnt
  4674.     xor    al,al            ; CR -> CR NUL
  4675.     push    bx
  4676.     mov    bx,tcpdata[24]        ; tcpnewline offset
  4677.     cmp    byte ptr [bx],0        ; newline mode is off?
  4678.     pop    bx
  4679.     je    ubsend23        ; e = yes
  4680.     mov    al,LF            ; CR -> CR/LF
  4681. ubsend23:mov    xmtbufx[bx],al        ; append this char
  4682.     inc    xmtcnt
  4683.     jmp    short ubsen28        ; send buffer now
  4684.  
  4685. ubsen24:cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  4686.     jae    ubsen28            ; ae = buffer is full, send it now
  4687.     cmp    ah,trans.seol        ; end of packet?
  4688.     je    ubsen28            ; e = yes, send buffer
  4689.     test    flowcnt,1        ; using output XON/XOFF flow control?
  4690.     jz    ubsen25            ; z = no
  4691.     cmp    ah,flowon        ; flow control?
  4692.     je    ubsen28            ; e = yes, always expedite
  4693.     cmp    ah,flowoff        ; ditto for flow off
  4694.     je    ubsen28
  4695. ubsen25:cmp    ttyact,0        ; are we in Connect mode?
  4696.     jne    ubsen28            ; ne = yes, send now
  4697.     clc                ; e = no, wait for more before sending
  4698.     ret
  4699. ubsen28:push    ax
  4700.     push    cx
  4701.     push    es
  4702.     mov    cx,xmtcnt        ; number of chars
  4703.     jcxz    ubsend1            ; z = nothing to send
  4704.     mov    bx,offset xmtbufx    ; buffer address in es:bx
  4705. ubsend2:mov    ax,data
  4706.     mov    es,ax
  4707.     test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet?
  4708.     jz    ubsend2a        ; z = no
  4709.     mov    ah,bapiwrit        ; 3Com block write
  4710.     xor    dh,dh            ; session 0
  4711.     test    nettype,tcpnet        ; TCP/IP Telnet?
  4712.     jz    ubsend2d        ; z = no
  4713.     call    ktcpcom            ; Far call TCP/IP Telnet code
  4714.     jmp    short ubsend2e
  4715. ubsend2d:int    bapiint
  4716. ubsend2e:cmp    ah,3            ; status, no session and above
  4717.     jae    ubsend2b        ; ae = no session and above, fail
  4718.     jmp    short ubsend3        ; process data
  4719.  
  4720. ubsend2a:test    nettype,telapi        ; Novell TELAPI?
  4721.     jz    ubsend2c        ; z = no, Int 6Bh kind
  4722.     push    si
  4723.     push    bx            ; preserve buffer offset
  4724.     mov    si,bx            ; use es:si for buffer address
  4725.     mov    ah,telwrite
  4726.     mov    bx,telses        ; session number
  4727.     int    rs232
  4728.     pop    bx
  4729.     pop    si
  4730.     mov    cx,ax            ; TELAPI returns sent count in AX
  4731.     or    ax,ax            ; error response (sign bit set)?
  4732.     jns    ubsend3            ; ns = no error
  4733.  
  4734. ubsend2b:call    ubclose            ; failure, close the connection
  4735.     pop    es
  4736.     pop    cx
  4737.     pop    ax
  4738.     stc                ; failure
  4739.     ret
  4740.  
  4741. ubsend2c:test    nettype,netone        ; UB?
  4742.     jz    ubsend1            ; no, do nothing
  4743.     mov    ax, nciwrit        ; write function, port 0     [ohl]
  4744.     int    netci
  4745. ubsend3:cmp    cx,xmtcnt        ; check that all characters sent [ohl]
  4746.     je    ubsend1            ; e = yes             [ohl]
  4747.     add    bx,cx            ; point to remaining chars     [ohl]
  4748.     sub    xmtcnt,cx        ; count of remaining characters     [ohl]
  4749.     mov    cx,xmtcnt        ; need count in cx too
  4750.     jmp    short ubsend2        ; try again to send         [ohl]
  4751. ubsend1:mov    xmtcnt,0
  4752.     pop    es
  4753.     pop    cx
  4754.     pop    ax
  4755.     clc                ; success, need failure case too
  4756.     ret
  4757. ubsend    endp
  4758.  
  4759. ; Block send routine for Beame & Whiteside TCP
  4760. ; Enter with char to be sent in AH. Destroys BX. [JRS]
  4761. bwsend    proc    near
  4762.     test    nettype,bwtcp        ; active?
  4763.     jnz    bwsend0            ; nz = yes
  4764.     stc
  4765.     ret
  4766. bwsend0:mov    bx,xmtcnt        ; [JRS] count of chars in buffer
  4767.     mov    xmtbufx[bx],ah        ; [JRS] put char in buffer
  4768.     inc    xmtcnt            ; [JRS] count of items in this buffer
  4769.     and    ah,7fh            ; [JRS] strip parity
  4770.     cmp    ah,CR            ; [JRS] carriage return?
  4771.     jne    bwsend1            ; [JRS] ne = no
  4772.     inc    bx            ; [JRS]
  4773.     xor    al,al            ; CR -> CR NUL
  4774.     push    bx
  4775.     mov    bx,tcpdata[24]        ; tcpnewline offset
  4776.     cmp    byte ptr [bx],0        ; newline mode is off?
  4777.     pop    bx
  4778.     je    bwsend0a        ; e = yes
  4779.     mov    al,LF            ; CR -> CR/LF
  4780. bwsend0a:call    dopar            ; [JRS] apply parity
  4781.     mov    xmtbufx[bx],al        ; [JRS] append this char
  4782.     inc    xmtcnt            ; [JRS]
  4783.     jmp    short bwsend2        ; [JRS]
  4784.  
  4785. bwsend1:cmp    ttyact,0        ; [JRS] are we in Connect mode?
  4786.     jne    bwsend2            ; [JRS] ne = yes, send now
  4787.     cmp    xmtcnt,length xmtbuf-1    ; [JRS] is buffer full? (room for lf)
  4788.     jb    bwsend3            ; [JRS] b = no, else take special step
  4789. bwsend2:mov    ah,40h            ; [JRS] write to device
  4790.     mov    bx,bwhandle        ; [JRS] device handle
  4791.     mov    cx,xmtcnt        ; [JRS] number of bytes to write
  4792.     mov    dx,offset xmtbufx    ; [JRS] data buffer
  4793.     int    dos            ; [JRS] ask dos to send it
  4794.     jc    bwsend4            ; c = failed
  4795.     mov    xmtcnt,0        ; [JRS] clear the buffer
  4796. bwsend3:clc                ; [JRS] e = no, wait for more
  4797.     ret
  4798. bwsend4:call    bwclose            ; failed to send, quit
  4799.     stc
  4800.     ret
  4801. bwsend    endp
  4802.  
  4803. ; Dispatch prebuilt NetBios session scb, enter with bx pointing to scb.
  4804. ; Returns status in al (and ah too). Allows STARLAN Int 2ah for netint.
  4805. NBSESSION PROC    NEAR    
  4806.     push    es            ; save es around call
  4807.     mov    ax,ds
  4808.     mov    es,ax            ; make es:bx point to scb in data seg
  4809.     mov    ax,exnbios        ; funct 4 execute netbios, for Int 2ah
  4810.     int    netint            ; use NetBios interrupt
  4811.     pop    es            ; saved registers
  4812.     ret                ; exit with status in ax
  4813. NBSESSION ENDP
  4814.  
  4815. ; Start a TCP/IP Telnet session. Set nettype if successful.
  4816. ; Uses sescur to determine new (-1) or old (0..MAXSESSIONS-1) session.
  4817. ; Returns carry clear if success, else carry set.
  4818. tcpstart proc    near
  4819.     mov    bx,sescur        ; current session index for seslist
  4820.     or    bx,bx            ; non-negative means active
  4821.     jns    tcpstar1        ; ns = active
  4822.     mov    decbuf,0        ; ensure cmd line is cleared too
  4823.     call    sesmgr            ; init a fresh session
  4824.     mov    sescur,bx        ; get its index
  4825.     jmp    short tcpstar2        ; start fresh session
  4826. tcpstar1:mov    al,seslist[bx]        ; get the state value
  4827.     xor    ah,ah
  4828.     or    al,al            ; is session active now?
  4829.     jns    tcpstar3        ; ns = yes, else start fresh session
  4830.  
  4831. tcpstar2:mov    vtinited,0        ; MSY terminal emulation
  4832.     mov    tekflg,0        ; clear all graphics mode material
  4833.     call    ktcpopen        ; open a new TCP connection
  4834.     jmp    short tcpstar4        ; check status in AX
  4835.  
  4836. tcpstar3:call    ktcpswap        ; switch to Telnet session in AL
  4837. tcpstar4:or    al,al            ; Telnet status, successful?
  4838.     jns    tcpstar5        ; ns = yes
  4839.     jmp    tcpclose        ; fail, close this failed session
  4840.  
  4841.                     ; started/swapped sessions ok
  4842. tcpstar5:mov    bx,sescur        ; current session, local basis
  4843.     mov    seslist[bx],al        ; update local session mgr with status
  4844.     push    ax
  4845.     push    si
  4846.     push    di
  4847.     mov    al,seshostlen        ; length of name fields
  4848.     mul    bl            ; times number of entries
  4849.     add    ax,offset sesname
  4850.     mov    si,ax            ; name of current host
  4851.     mov    di,offset tcphost    ; update main table
  4852.     call    strcpy
  4853.     pop    di
  4854.     pop    si
  4855.     pop    ax
  4856.     mov    pcnet,2            ; net open and going
  4857.     or    nettype,tcpnet        ; say a session is active (ses = BL)
  4858.     clc                ; success
  4859.     ret
  4860. tcpstart endp
  4861.  
  4862. ; Close/shutdown/terminate a TCP/IP Telnet session. Sescur is session
  4863. ; number, -1 closes all sessions and TCP/IP.
  4864. tcpclose proc    near
  4865.     mov    ax,sescur
  4866.     or    ax,ax            ; close active (>=0) or all (-1)?
  4867.     js    tcpclo1            ; s = all (-1)
  4868.     mov    bx,ax
  4869.     call    termswapdel        ; delete term save block for ses BX
  4870.     mov    al,-1            ; session closed marker
  4871.     xchg    al,seslist[bx]        ; get tcpident from local list to AL
  4872.     or    al,al            ; is this Telnet session active?
  4873.     jns    tcpclo1            ; ns = yes, close it
  4874.     xor    bx,bx            ; find a new active session
  4875.     mov    cx,maxsessions        ; number session slots
  4876. tcpclo0:cmp    seslist[bx],0        ; session status, active?
  4877.     jge    tcpclo3a        ; ge = yes, make this the active one
  4878.     inc    bx
  4879.     loop    tcpclo0
  4880.     jmp    short tcpclo4        ; no active sessions, quit
  4881.  
  4882. tcpclo1:call    ktcpclose        ; AL = close this particular session
  4883.     or    al,al            ; status from ktcpclose
  4884.     jns    tcpclo3            ; ns = have ses, -1 = no more sessions
  4885.     call    ktcpclose        ; close TCP/IP as a whole after last
  4886.     and    nettype,not tcpnet    ; clear activity flag
  4887.     mov    cx,maxsessions        ; clear all local table entries
  4888.     xor    bx,bx
  4889. tcpclo2:mov    seslist[bx],-1        ; status is inactive
  4890.     push    ax
  4891.     call    termswapdel        ; delete terminal save block
  4892.     pop    ax
  4893.     inc    bx
  4894.     loop    tcpclo2
  4895.     
  4896. tcpclo3:call    tcptoses        ; convert next tcp ident AL to sescur
  4897.  
  4898. tcpclo3a:mov    sescur,bx        ; next new session
  4899.     or    bx,bx            ; closing last session?
  4900.     js    tcpclo4            ; s = yes, no more sessions
  4901.     call    termswapin        ; swap in next session's emulator
  4902.     mov    port_tn.portrdy,0    ; say the comms port is not ready
  4903.     mov    kbdflg,' '        ; stay in connect mode
  4904.     stc
  4905.     ret
  4906. tcpclo4:mov    port_tn.portrdy,0    ; say the comms port is not ready
  4907.     mov    pcnet,0            ; say no network
  4908.     mov    portin,0        ; reset the serial port for reiniting
  4909.     mov    kbdflg,'C'        ; quit connect mode
  4910.     stc
  4911.     ret
  4912. tcpclose endp
  4913.  
  4914. ; Make a NetBios virtual circuit Session, given preset scb's from proc chknet.
  4915. ; For Server mode, does a Listen to '*', otherwise does a Call to indicated
  4916. ; remote node. Updates vcid number in scb's. Shows success or fail msg.
  4917. ; Updates network status byte pcnet to 2 if session is established.
  4918. ; Does nothing if a session is active upon entry; otherwise, does a network
  4919. ; hangup first to clear old session material from adapter board. This is
  4920. ; the second procedure to call in initializing the network for usage.
  4921. ; If success nettype is set to netbios and return is carry clear; else 
  4922. ; if failure nbclose is called to clean up connections and remove the nettype
  4923. ; bit and return is carry set.
  4924. SETNET    PROC    NEAR            ; NetBios, make a connection
  4925.     cmp    lposted,1        ; Listen pending?
  4926.     je    setne0            ; e = yes, exit now
  4927.     cmp    pcnet,1            ; session active?
  4928.     jbe    setne1            ; be = no
  4929.     clc
  4930. setne0:    ret
  4931.                     ; No Session
  4932. setne1:    test    flags.remflg,dserver    ; Server mode?
  4933.     jz    setne2            ; z = no, file xfer or Connect
  4934.                     ; Server mode, post a Listen (async)
  4935.     mov    lsn.scb_rname,'*'    ; accept anyone
  4936.     mov    ax,500
  4937.     call    pcwait            ; 0.5 sec wait
  4938.     or    nettype,netbios        ; set net type
  4939.     mov    lposted,1        ; set listen interlock flag
  4940.     mov    lsn.scb_cmd,nlisten+nowait ; do LISTEN command, no wait
  4941.     push    bx            ; save reg
  4942.     mov    bx,offset lsn
  4943.     call    nbsession
  4944.     pop    bx
  4945.     clc
  4946.     ret
  4947. setne2:                    ; Non-server (Client) mode
  4948.     cmp    starlan,0        ; STARLAN?
  4949.     je    setne2a            ; e = no
  4950.     cmp    xmt.scb_vrlen,0        ; yes, using long name support?
  4951.     je    setne2a            ; e = no
  4952.     push    es            ; save reg
  4953.     push    ds
  4954.     pop    es            ; make es:bx point to xmt scb
  4955.     push    bx            ; save reg
  4956.     mov    bx,offset xmt        ; use xmt scb for the call
  4957.     mov    xmt.scb_cmd,ncall    ; CALL_ISN, vrname + vrlen are ready
  4958.     int    5bh            ; STARLAN CALL Int 5bh, wait
  4959.     pop    bx
  4960.     pop    es            ; restore regs
  4961.     jmp    short setne3        ; finish up
  4962.  
  4963.                     ; Regular Netbios Call
  4964. setne2a:cmp    flags.comflg,'O'    ; Opennet network? (FGR)
  4965.     jne    setne2b            ; ne = no
  4966.     mov    xmt.scb_rname+15,'v' ; fix name to use VT port under nameserver
  4967.     mov    rcv.scb_rname+15,'v'
  4968. setne2b:mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  4969.     push    bx            ; save reg
  4970.      mov    bx,offset xmt        ; setup scb pointer
  4971.     call    nbsession
  4972.     pop    bx            ; restore register
  4973.  
  4974. setne3:                    ; common Call completion, show status
  4975.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  4976.     jnz    setne3a            ; nz = yes, do bad return
  4977.     or    al,al            ; check error return
  4978.     jnz    setne3b            ; nz = bad connection
  4979.     jmp    short setne4        ; good connection so far
  4980.  
  4981.                     ; We try twice to allow for R1, and R3
  4982.                     ; versions of the nameservers
  4983. setne3b:cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  4984.     jne    setne3a            ; ne = no
  4985.     mov    xmt.scb_rname+15,' '    ; try generic port under nameserver
  4986.     mov    rcv.scb_rname+15,' '
  4987.                     ; Regular Netbios Call
  4988.     mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  4989.     mov    bx,offset xmt        ; setup scb pointer
  4990.     call    nbsession
  4991.  
  4992.                     ; common Call completion, show status
  4993.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  4994.     jnz    setne3a            ; nz = yes, do bad return
  4995.     or    al,al            ; check error return
  4996.     jz    setne4            ; z = good connection so far
  4997. setne3a:mov    dx,offset nbadset    ; say can't reach remote node
  4998.     mov    ah,prstr
  4999.     int    dos
  5000.     call    saynode            ; show remote host node name
  5001.     jmp    setne4c
  5002.                     ; keep results of Call (vcid)
  5003. setne4:    mov    al,xmt.scb_vcid        ; local session number
  5004.     mov    rcv.scb_vcid,al        ; for receiver too
  5005.     mov    can.scb_vcid,al        ; for sending Breaks
  5006.     mov    pcnet,2            ; say session has started
  5007.  
  5008. ; Here is the real difference between Opennet and generic Netbios.
  5009. ; The Opennet Virtual Terminal Services exchange a small handshake at connect
  5010. ; time. After that it is just normal Netbios data transfer between the host
  5011. ; and Kermit.
  5012.     cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  5013.     jne    setne4o            ; ne = no
  5014.     push    si
  5015.     push    di
  5016.     mov    si,offset ivt1str    ; protocol string "iVT1\0"
  5017.     mov    di,offset xmtbufx    ; buffer
  5018.     call    strcpy            ; copy asciiz string
  5019.     mov    xmtcnt,5        ; length of asciiz string, for send
  5020.     pop    di
  5021.     pop    si
  5022.     call    send            ; send signon packet
  5023. ; Note to Opennet purists: this just sends the handshake string to the host
  5024. ; system without checking for an appropriate response. Basically, I am just
  5025. ; very willing to talk to ANY VT server, and do the host response checking
  5026. ; (if desired) in a Kermit script file (so its optional).
  5027.  
  5028. setne4o:cmp    flags.comflg,'E'    ; ACSI version of EBIOS?
  5029.     jne    setnet4p        ; ne = no
  5030.     mov    word ptr xmtbufx,6    ; internal word count
  5031.     mov    xmtcnt,6        ; four bytes
  5032.     mov    word ptr xmtbufx+2,acenable*256+3 ; raise DTR and RTS
  5033.     mov    bx,portval
  5034.     mov    ax,[bx].baud        ; get baud rate index
  5035.     cmp    al,0ffh            ; unknown baud rate?
  5036.     jne    setnet4pa        ; ne = no
  5037.     mov    ax,11            ; 2400,n,8,1
  5038.     mov    [bx].baud,ax        ; set index into port info structure
  5039. setnet4pa:shl    ax,1            ; make a word index
  5040.     mov    bx,ax
  5041.     mov    ax,clbddat[bx]        ; Bios style speed setting
  5042.     cmp    al,0ffh            ; unimplemented baud rate?
  5043.     jne    setnet4pb        ; ne = no
  5044.     mov    bx,portval        ; set index into port info structure
  5045.     mov    [bx].baud,3        ; 110 baud -> 19200 for ACSI
  5046.     mov    al,3            ; default to 19200,n,8,1
  5047. setnet4pb:mov    ah,acsetmode        ; ACSI cmd for Mode set
  5048.     mov    word ptr xmtbufx+4,ax    ; Mode setting
  5049.     or    nettype,acsi        ; set special net operation
  5050.     call    send
  5051. setnet4p:
  5052.     test    flags.remflg,dregular+dquiet ; regular or quiet display?
  5053.     jnz    setne4c            ; nz = yes, show only no-connect msg
  5054.     mov    dx,offset ngodset    ; say good connection
  5055.     mov    ah,prstr
  5056.     int    dos
  5057.     call    saynode            ; show remote host name
  5058. setne4c:cmp    pcnet,1            ; check connection again
  5059.     ja    setne5            ; a = good so far
  5060.     call    nbclose            ; shut down NetBios
  5061.     stc                ; set carry for failure
  5062.     ret
  5063. setne5:    or    nettype,netbios        ; set net type
  5064.     clc                ; carry clear for success
  5065.     ret
  5066. SETNET    ENDP
  5067.  
  5068. saynode    proc    near        ; display node name on screen, si=name ptr
  5069.     push    ax
  5070.     push    cx
  5071.     push    dx
  5072.     push    si
  5073.     mov    ah,conout
  5074.     mov    si,offset nambuf    ; remote node string
  5075.     mov    cx,64            ; up to 64 bytes long
  5076. saynod1:cld
  5077.     lodsb                ; get remote node name char into al
  5078.     mov    dl,al
  5079.     int    dos            ; display it
  5080.     cmp    al,' '            ; was it a space?
  5081.     jbe    saynod2            ; be = yes, quit here
  5082.     loop    saynod1            ; do all chars
  5083. saynod2:mov    ah,prstr
  5084.     mov    dx,offset crlf
  5085.     int    dos
  5086.     pop    si
  5087.     pop    dx
  5088.     pop    cx
  5089.     pop    ax
  5090.     ret
  5091. saynode    endp
  5092.  
  5093. LPOST    PROC    FAR        ; Interrupt Post routine for Listen call
  5094.     push    ds        ; update vcid and calling node name in scb's
  5095.     push    cx    
  5096.     push    es
  5097.     push    si
  5098.     push    di
  5099.     mov    cx,data        ; reestablish data segment
  5100.     mov    ds,cx
  5101.     mov    es,cx
  5102.     mov    si,offset lsn.scb_rname    ; copy remote name to rcv and xmt scbs
  5103.     push    si
  5104.     mov    di,offset rcv.scb_rname
  5105.     mov    cx,8            ; 16 byte field
  5106.     cld
  5107.     rep    movsw
  5108.     mov    cx,8
  5109.     pop    si
  5110.     push    si
  5111.     mov    di,offset xmt.scb_rname
  5112.     rep    movsw
  5113.     mov    cx,8
  5114.     pop    si
  5115.     mov    di,offset nambuf    ; and to nambuf for display
  5116.     rep    movsw
  5117.     mov    cl,lsn.scb_vcid        ; local session number
  5118.     mov    rcv.scb_vcid,cl
  5119.     mov    xmt.scb_vcid,cl
  5120.     mov    can.scb_vcid,cl
  5121.     mov    lposted,0        ; clear interlock flag
  5122.     mov    pcnet,2            ; say net ready due to a Listen
  5123.     pop    di
  5124.     pop    si
  5125.     pop    es
  5126.     pop    cx
  5127.     pop    ds
  5128.     iret                ; return from interrupt
  5129. LPOST    ENDP
  5130.  
  5131. ; Close all network connections
  5132. NETHANGUP PROC    NEAR             ; disconnect network session, keep names
  5133.     call    ubclose            ; close Ungermann Bass Int 6Bh class
  5134.     mov    xmtcnt,0
  5135.     call    decclose        ; close DECnet connection
  5136.     call    telapiclose        ; close Telapi session
  5137.     mov    sescur,-1        ; say close all sessions, stop TCP/IP
  5138.     call    tcpclose        ; close internal TCP/IP sessions
  5139.     call    ebiclose        ; close EBIOS session
  5140.     call    tesclose        ; close TES session, ignore failures
  5141.     call    nbclose            ; close NetBios and ACSI
  5142.     call    bwclose            ; close BW TCP
  5143.     mov    portin,0        ; reset the serial port for reiniting
  5144.     mov    kbdflg,'C'        ; quit connect mode
  5145.     clc
  5146.     ret
  5147. NETHANGUP ENDP
  5148.  
  5149. ; Close NetBios connection. Clears nettype of netbios
  5150. nbclose proc    near
  5151.     test    nettype,(netbios+acsi)    ; NetBios or ACSI active?
  5152.     jz    nbclose2        ; z = no
  5153.     cmp    pcnet,0            ; network started?
  5154.     je    nbclose2        ; e = no
  5155.     test    nettype,acsi        ; ACSI?
  5156.     jz    nbclose1        ; z = no
  5157.     mov    word ptr xmtbufx,4    ; four bytes
  5158.     mov    word ptr xmtbufx+2,acdisable*256 ; drop all modem leads
  5159.     mov    xmtcnt,4        ; four bytes
  5160.     call    send            ; tell the server
  5161.     mov    ax,500            ; wait 0.5 sec
  5162.     call    pcwait            ; for pkt to reach host
  5163. nbclose1:push    bx            ; NetBios network
  5164.     mov    bx,offset can 
  5165.     mov    can.scb_cmd,ncancel    ; set cancel op code
  5166.     mov    can.scb_baddr,offset lsn ; cancel listens
  5167.     mov    lposted,0        ; say no listen
  5168.     call    nbsession
  5169.     mov    can.scb_baddr,offset rcv ; cancel receives
  5170.     call    nbsession
  5171.     mov    rposted,0        ; say no receives posted
  5172.     mov    can.scb_baddr,offset xmt ; cancel sends
  5173.     call    nbsession
  5174.     mov    sposted,0        ; say no sends posted
  5175.     mov    xmtcnt,0        ; reset output buffer counter
  5176.     mov    xmt.scb_cmd,nhangup    ; hangup, and wait for completion
  5177.     mov    bx,offset xmt
  5178.     call    nbsession
  5179.     pop    bx
  5180.     and    nettype,not (netbios+acsi)
  5181.     mov    pcnet,1            ; net but no connection
  5182.     mov    port_nb.portrdy,0    ; say the comms port is not ready
  5183.     mov    portin,0
  5184.     mov    kbdflg,'C'        ; quit connect mode
  5185.     stc
  5186. nbclose2:ret
  5187. nbclose endp
  5188.  
  5189. decclose proc    near
  5190.     test    nettype,declat        ; DECnet LAT active?
  5191.     jz    decclos3        ; z = no
  5192.     mov    dx,lathand        ; LAT handle
  5193.     or    dx,dx            ; invalid handle?
  5194.     jz    decclos2        ; z = yes
  5195.     mov    ax,latclose
  5196.     int    latint
  5197.     mov    ax,latseg        ; allocated memory segment
  5198.     or    ax,ax            ; was it used?
  5199.     jz    decclos1        ; z = no
  5200.     push    es
  5201.     mov    es,ax
  5202.     mov    ah,freemem        ; free allocated memory segment @ES
  5203.     int    dos            ; free the block
  5204.     pop    es
  5205.     mov    latseg,0        ; clear remembered segment address
  5206.     mov    word ptr latscbptr+2,0    ; clear this pointer (same as latseg)
  5207. decclos1:cmp    latversion,4        ; version 4?
  5208.     jb    decclos2        ; b = no
  5209.     push    es
  5210.     les    bx,latscbptr+4        ; address of exterior SCB
  5211.     mov    dx,lathand
  5212.     mov    ax,latscbfree        ; free SCB interior to LAT
  5213.     int    latint
  5214.     mov    word ptr latscbptr+2,0
  5215.     pop    es
  5216. decclos2:and    nettype,not declat    ; remove net type bit
  5217.     mov    lathand,0        ; invalidate the handle
  5218.  
  5219. decclos3:test    nettype,decnet        ; DEC CTERM active?
  5220.     jz    decclos4        ; z = no
  5221.     mov    dx,decneth        ; DECnet CTERM handle
  5222.     or    dx,dx            ; invalid handle?
  5223.     jz    decclos5        ; z = yes
  5224.     mov    ax,dclose        ; CTERM close
  5225.     int    decint
  5226.     mov    decneth,0        ; invalidate the handle
  5227.     mov    ax,decseg        ; allocated memory segment
  5228.     or    ax,ax            ; ever used?
  5229.     jz    decclos4        ; z = no
  5230.     mov    es,ax
  5231.     mov    ah,freemem        ; free allocated memory segment @ES
  5232.     int    dos            ; free the block
  5233.     mov    decseg,0        ; clear remembered segment address
  5234. decclos4:and    nettype,not decnet    ; remove net type bit
  5235.     mov    port_dec.portrdy,0    ; say port is not ready
  5236.     mov    pcnet,0            ; say no network
  5237.     mov    portin,0
  5238.     mov    kbdflg,'C'        ; quit connect mode
  5239.     stc
  5240. decclos5:ret
  5241. decclose endp
  5242.  
  5243. telapiclose proc near
  5244.     test    nettype,telapi        ; Novell TELAPI?
  5245.     jz    telapiclo1        ; e = no
  5246.     mov    xmtcnt,0
  5247.     push    bx
  5248.     mov    bx,telses        ; session number
  5249.     mov    ah,telclose        ; close session
  5250.     int    rs232
  5251.     pop    bx
  5252.     and    nettype,not telapi    ; remove active net type bit
  5253.     mov    portin,0
  5254.     mov    pcnet,1
  5255.     push    bx
  5256.     mov    bx,portval
  5257.     mov    [bx].portrdy,0        ; say port is not ready
  5258.     pop    bx
  5259.     mov    kbdflg,'C'        ; quit connect mode
  5260.     stc
  5261. telapiclo1:ret
  5262. telapiclose endp
  5263.  
  5264. ; Close EBIOS communications link
  5265. ebiclose proc near
  5266.     test    nettype,ebios        ; EBIOS?
  5267.     jz    ebiclos1        ; z = no
  5268.     mov    dx,ebport        ; EBIOS
  5269.     mov    ax,ebmodem*256+0    ; reset outgoing DTR and RTS leads
  5270.     int    rs232
  5271.     push    es
  5272.     mov    bx,ds
  5273.     mov    es,bx
  5274.     mov    bx,offset ebcoms    ; es:bx is parameter block ebcoms
  5275.     mov    ah,ebredir        ; do redirect away from EBIOS
  5276.     mov    ebcoms+1,0        ; set port to hardware
  5277.     int    rs232
  5278.     mov    dx,ebport        ; port 0..3
  5279.     mov    bx,offset rcvbuf    ; receive buffer for EBIOS
  5280.     xor    cx,cx            ; set to zero to stop buffering
  5281.     mov    ax,ebbufset*256+2    ; reset rcvr buffered mode
  5282.     int    rs232
  5283.     xor    cx,cx
  5284.     mov    bx,offset xmtbuf    ; EBIOS transmitter work buffer
  5285.     mov    ax,ebbufset*256+1    ; reset xmtr buffered mode
  5286.     int    rs232
  5287.     pop    es
  5288.     mov    bx,offset portb1    ; use Bios data structure
  5289.     mov    ax,type prtinfo        ; portinfo item size
  5290.     mul    dl            ; times actual port (0..3)
  5291.     add    bx,ax            ; new portb<n> offset
  5292.     mov    [bx].portrdy,0        ; say port is not ready
  5293.     and     nettype,not ebios
  5294.     mov    portin,0
  5295.     mov    kbdflg,'C'        ; quit connect mode
  5296.     stc
  5297. ebiclos1:ret
  5298. ebiclose endp
  5299.  
  5300. ; TES close session
  5301. tesclose proc    near
  5302.     test    nettype,tes        ; TES?
  5303.     jz    tesclo3            ; z = no
  5304.     mov    temp,0            ; retry counter
  5305.     call    tesstate        ; get session state to AH
  5306.     test    ah,2            ; is this session active?
  5307.     jz    tesclo2            ; z = no, but keep held sessions
  5308.     mov    ah,tesdrop        ; drop a session
  5309.     mov    al,tesses        ; the session
  5310.     call    tes_service
  5311.     or    ah,ah            ; status
  5312.     jz    tesclo2            ; z = success
  5313.     stc                ; say failure
  5314.     ret
  5315. tesclo2:and    nettype,not tes        ; successful hangup
  5316.     mov    tesses,0        ; clear session
  5317.     mov    port_tes.portrdy,0    ; say the comms port is not ready
  5318.     mov    pcnet,1            ; say network but no session
  5319.     mov    portin,0
  5320.     mov    kbdflg,'C'        ; quit connect mode
  5321.     stc
  5322.     ret
  5323. tesclo3:clc
  5324.     ret
  5325. tesclose endp
  5326.  
  5327. ; Ungermann Bass. Do a disconnect from the current connection.
  5328. ubclose proc    near
  5329.     push    ax
  5330.     push    cx
  5331.     test    nettype,netone        ; UB network has been activated?
  5332.     jz    ubclos4            ; z = no
  5333.     mov    ax,ncistat        ; get status             [ohl]
  5334.     int    netci
  5335.      or    ch,ch            ; check if we have a connection     [ohl]
  5336.     jz    ubclos2            ; z = no             [ohl]
  5337.     mov    ax,ncicont        ; control function         [ohl]
  5338.     mov    cx,ncidis        ; say disconnect         [ohl]
  5339.     int    netci
  5340. ubclos1:call    ubrecv            ; read response from net cmdintpr[ohl]
  5341.     jnc    ubclos1            ; continue till no chars     [ohl]
  5342.     mov    ax,ncistat        ; get status again
  5343.     int    netci
  5344.     or    ch,ch            ; check if we have a connection
  5345.     jnz    ubclos3            ; nz = yes, had more than one
  5346. ubclos2:and    nettype,not netone    ; remove network type
  5347.     mov    pcnet,1            ; net but no connection
  5348.     mov    port_ub.portrdy,0    ; say the comms port is not ready
  5349.     mov    portin,0
  5350.     mov    kbdflg,'C'        ; quit connect mode
  5351.     stc
  5352. ubclos3:pop    cx
  5353.     pop    ax
  5354.     ret
  5355. ubclos4:test    nettype,bapi+tcpnet    ; 3Com BAPI or TCP Telnet in use?
  5356.     jz    ubclos6            ; z = no
  5357.     mov    ah,bapieecm        ; control Enter Command Mode char
  5358.     mov    al,1            ; enable it
  5359.     test    nettype,tcpnet        ; TCP/IP Telnet?
  5360.     jz    ubclos5            ; z = no
  5361.     call    tcpclose        ; tell Telnet to close current session
  5362.     jmp    short ubclos3
  5363. ubclos5:int    bapiint
  5364.     jmp    short ubclos3
  5365. ubclos6:test    nettype,telapi        ; Novell TELAPI Int 6Bh interface?
  5366.     jz    ubclos3            ; z = no
  5367.     call    telapiclose
  5368.     jmp    short ubclos3
  5369. ubclose endp
  5370.  
  5371. ; Ungermann Bass/Novell. Put current connection on Hold. Requires keyboard
  5372. ; verb \knethold to activate. Should return to Connect mode to see NASI. [jrd]
  5373. ubhold    proc    near
  5374.     push    ax
  5375.     push    cx
  5376.     test    nettype,netone        ; UB/Novell network active?
  5377.     jz    ubhold1            ; z = no
  5378.     mov    ax,ncistat        ; get link status
  5379.     int    netci
  5380.     or    ch,ch            ; connection active?
  5381.     jz    ubhold1            ; z = no
  5382.     mov    ax,ncicont        ; control command
  5383.     mov    cl,ncihld        ; place circuit on HOLD
  5384.     int    netci
  5385.     jmp    short ubhold3
  5386. ubhold1:test    nettype,bapi        ; 3Com BAPI
  5387.     jz    ubhold2            ; z = no
  5388.     mov    ah,bapiecm        ; do Enter Command Mode char
  5389. ubhold1b:int    bapiint
  5390.     jmp    short ubhold3
  5391. ubhold2:test    nettype,tes        ; TES?
  5392.     jz    ubhold3            ; z = no
  5393.     mov    ah,testalk        ; TES get command interpreter
  5394.     mov    dx,tesport        ; "serial port"
  5395.     int    rs232
  5396. ubhold3:pop    cx
  5397.     pop    dx
  5398.     clc
  5399.     ret
  5400. ubhold    endp
  5401.  
  5402. ; Beame & Whiteside TCP close session [JRS]
  5403. bwclose    proc    near            ; [JRS]
  5404.     mov    bx,bwhandle        ; [JRS] get file handle
  5405.     or    bx,bx            ; [JRS] if zero, we're done
  5406.     jz    bwclos1            ; [JRS] z= done
  5407.     mov    ah,close2        ; [JRS] close device
  5408.     int    dos            ; [JRS]
  5409.     mov    bwhandle,0        ; [JRS] clear the handle value
  5410. bwclos1:and    nettype,not bwtcp
  5411.     mov    portin,0        ; say serial port is closed
  5412.     mov    pcnet,0
  5413.     mov    port_tn.portrdy,0    ; say port is not ready
  5414.     mov    kbdflg,'C'        ; quit connect mode
  5415.     clc                ; [JRS]    flag success
  5416.     ret
  5417. bwclose    endp
  5418.  
  5419. ; Called when Kermit exits. Name passed to mssker by initialization lclini
  5420. ; in word lclexit.
  5421. NETCLOSE PROC    NEAR            ; close entire network connection
  5422.     call    nethangup        ; close connections
  5423.     push    bx
  5424.     mov    bx,offset xmt
  5425.     cmp    xmt.scb_lname,' '    ; any local name?
  5426.     je    netclo2            ; e = none
  5427.     mov    xmt.scb_cmd,ndelete    ; delete our local Kermit name
  5428.     call    nbsession        ;  from net adapter board
  5429.     mov    xmt.scb_lname,' '    ; clear name
  5430. netclo2:pop    bx
  5431.     mov    pcnet,0            ; say no network
  5432.     mov    lnamestat,0        ; local name not present, inactive
  5433.     mov    port_nb.portrdy,0    ; say comms port is not ready
  5434.     and    nettype,not (netbios+acsi) ; remove network kind
  5435. netclo1:clc
  5436.     ret
  5437. NETCLOSE ENDP    
  5438.  
  5439. ; Start connection process to network. Obtains Network board local name
  5440. ; and appends '.K' to form Kermit's local name (removed when Kermit exits).
  5441. ; If no local name is present then use name 'mskermit.K'.
  5442. ; Sets local name in scb's for xmt, rcv, lsn. (Does not need DOS 3.x)
  5443. ; Sets NETDONE pointer to procedure netclose for Kermit exit.
  5444. ; Verifies existance of interrupt 5ch support, verifies vendor specific
  5445. ; support for BREAK and other features, sets network type bit in nettype,
  5446. ; sets BREAK support in nsbrk, hangsup old session if new node name given,
  5447. ; fills in local and remote node names and name number in scbs (including ISN
  5448. ; names for STARLAN), and sets network status byte pcnet to 0 (no net) or
  5449. ; to 1 (net ready). This is the first procedure called to init network usage.
  5450. ; Byte count of new host name is in temp from COMS.
  5451. chknet    proc    near
  5452.     cmp    flags.comflg,'U'    ; Ungermann Bass network?
  5453.     jb    chknea            ; b = no, (ae includes U and W)
  5454.     mov    pcnet,0            ; force reactivation of UB net
  5455. chknea:    cmp    pcnet,2            ; session active now?
  5456.     jb    chknec            ; b = no
  5457.     cmp    newnambuf,0        ; non-zero if new destination name
  5458.     je    chkneb            ; e = none, resume old session
  5459.     call    chknew            ; Resume current session?
  5460.     jnc    chkneb            ; nc = no
  5461. chknex:    ret                ; resume old one
  5462. chkneb:    jmp    chknet1            ; skip presence tests
  5463.  
  5464. chknec:                ; setup addresses and clear junk in scb's
  5465.     cmp    pcnet,0            ; have we been here already?
  5466.     je    chkned            ; e = no
  5467.     jmp    chknet1            ; yes, skip init part
  5468. chkned:    mov    xmtcnt,0        ; say buffer is empty
  5469.     mov    nsbrk,0            ; assume no BREAK across network
  5470.     and    nettype,not netbios    ; say no NetBios network yet
  5471.     mov    starlan,0        ; no Starlan yet
  5472.     call    chknetbios        ; is Netbios present?
  5473.     jc    chknet0            ; c = not present
  5474.     or    nettype,netbios        ; say have NetBios network
  5475.     call    chkstarlan        ; is AT&T StarLAN present?
  5476.     jc    chknet1            ; c = no
  5477.     inc    starlan            ; say using STARLAN, have int 2ah
  5478.     mov    nsbrk,1            ; network BREAK supported
  5479.     jmp    short chknet1
  5480.  
  5481. chknet0:mov    pcnet,0            ; no network yet
  5482.     push    dx
  5483.     mov    ah,prstr
  5484.     mov    dx,offset nonetmsg    ; say network is not available
  5485.     int    dos
  5486.     pop    dx
  5487.     stc                ; set carry for failure
  5488.     ret                ; and exit now
  5489.  
  5490.                     ; net ready to operate
  5491. chknet1:mov    port_nb.portrdy,1    ; say the comms port is ready
  5492.     cmp    newnambuf,0        ; non-zero if new destination name
  5493.     jne    chkne1e            ; ne = new name given
  5494.     jmp    chknet2            ; nothing, so leave names intact
  5495. chkne1e:cmp    pcnet,2            ; is session active now?
  5496.     jb    chkne1d            ; b = no
  5497.     call    nbclose            ; close to clear old connection
  5498.  
  5499. chkne1d:push    si            ; start fresh connection
  5500.     push    di
  5501.     push    es
  5502.     push    ds
  5503.     pop    es            ; make es:di point to data segment
  5504.     cld
  5505.     mov    cx,8            ; 16 bytes for a node name
  5506.     mov    ax,'  '            ; first, fill with spaces
  5507.     mov    di,offset xmt.scb_rname ; remote name field, clear it
  5508.     rep    stosw
  5509.     cmp    starlan,0        ; STARLAN?
  5510.     jne    chkne1b            ; ne = no
  5511.                     ; begin STARLAN section    
  5512.     mov    xmt.scb_vrname,0    ; STARLAN var length name ptr
  5513.     mov    xmt.scb_vrname+2,0    ; segement of name    
  5514.     mov    xmt.scb_vrlen,0        ; and its length
  5515.     mov    di,offset nambuf    ; source of text
  5516.     mov    dx,di
  5517.     call    strlen            ; length of new name to cx
  5518.     cmp    cx,16            ; > 16 chars in remote node name?
  5519.     ja    chkne1a            ; a = yes, too long for Netbios
  5520.     mov    al,'/'            ; scan for slashes in name
  5521.     cld
  5522.     repne    scasb            ; look for the slash
  5523.     jne    chkne1b        ; ne = none, do regular Netbios name storage
  5524. chkne1a:                ; STARLAN ISN long remote name support
  5525.     mov    dx,offset nambuf    ; STARLAN var length name ptr
  5526.     mov    xmt.scb_vrname,dx    
  5527.     mov    xmt.scb_vrname+2,data    ; segment of remote name
  5528.     call    strlen            ; get name length again (in cx)
  5529.     mov    xmt.scb_vrlen,cl    ; indicate its length
  5530.     jmp    short chkne1c        ; copy blanks in remote name field
  5531.                     ; end STARLAN section
  5532.  
  5533. chkne1b:                ; Regular Netbios form
  5534.     mov    si,offset nambuf    ; source of text
  5535.     mov    dx,si
  5536.     call    strlen            ; length to cx
  5537.     cmp    cx,16
  5538.     jbe    chkne1f            ; be = in bounds
  5539.     mov    cx,16            ; chop to 16 (prespace filled above)
  5540. chkne1f:mov    di,offset xmt.scb_rname ; destination is remote name
  5541.     rep    movsb            ; copy text to transmitter's scb
  5542. chkne1c:mov    cx,8            ; 8 words
  5543.     mov    si,offset xmt.scb_rname ; from here
  5544.     mov    di,offset rcv.scb_rname ; to receiver's scb also
  5545.     rep    movsw
  5546.     pop    es
  5547.     pop    di
  5548.     pop    si
  5549.     mov    newnambuf,0        ; say new name is established now
  5550.  
  5551. chknet2:cmp    pcnet,0            ; started net?
  5552.     je    chknet2c        ; e = no
  5553.     clc
  5554.     ret                ; else quit here
  5555. chknet2c:call    setnbname        ; establish local Netbios name
  5556.     jnc    chknet9            ; nc = success
  5557.     ret
  5558. chknet9:mov    pcnet,1            ; network is present (but not active)
  5559.     mov    al,xmt.scb_num        ; name number
  5560.     mov    rcv.scb_num,al
  5561.     mov    lsn.scb_num,al
  5562.     push    es
  5563.     push    si
  5564.     push    di
  5565.     mov    si,ds
  5566.     mov    es,si
  5567.     mov    si,offset xmt.scb_lname
  5568.     mov    di,offset rcv.scb_lname ; put in receiver scb too
  5569.     mov    cx,8
  5570.     rep    movsw
  5571.     mov    cx,8
  5572.     mov    si,offset xmt.scb_lname
  5573.     mov    di,offset lsn.scb_lname    ; in Listen scb also
  5574.     rep    movsw
  5575.     pop    si
  5576.     pop    di
  5577.     pop    es
  5578.     clc
  5579.     ret
  5580. chknet    endp
  5581.  
  5582. ; Service SET NETBIOS-NAME name   command at Kermit prompt level
  5583. setnbios    proc    near
  5584.     mov    dx,offset decbuf    ; work buffer
  5585.     mov    bx,offset setnbhlp    ; help
  5586.     mov    ah,cmword        ; get netbios name
  5587.     call    comnd
  5588.     jc    setnb3            ; c = failure
  5589.     push    ax            ; save char count
  5590.     mov    ah,cmeol        ; get a confirmation
  5591.     call    comnd
  5592.     pop    ax
  5593.     jc    setnb3            ; c = failure
  5594.     cmp    lnamestat,2        ; is name fixed already?
  5595.     je    setnb2            ; e = yes
  5596.     mov    cx,ax            ; char count
  5597.     jcxz    setnb3            ; z = enter no new name
  5598.     cmp    cx,16            ; too long?
  5599.     jbe    setnb1            ; be = no
  5600.     mov    cx,16            ; truncate to 16 chars
  5601. setnb1:    mov    si,offset decbuf    ; work buffer
  5602.     mov    di,offset deflname    ; default name
  5603.     push    es
  5604.     mov    ax,ds
  5605.     mov    es,ax
  5606.     cld
  5607.     rep    movsb            ; copy the name
  5608.     mov    al,' '            ; pad with spaces
  5609.     mov    cx,offset deflname+16    ; stopping place+1
  5610.     sub    cx,di            ; number of spaces to write
  5611.     rep    stosb            ; won't do anything if cx == 0
  5612.     pop    es
  5613.     mov    lnamestat,1        ; say have new local name
  5614.     call    setnbname        ; do the real NetBios resolution
  5615.     ret                ; returns carry set or clear
  5616. setnb2:    mov    ah,prstr
  5617.     mov    dx,offset setnbad    ; say name is fixed already
  5618.     int    dos
  5619. setnb3:    stc                ; failure
  5620.     ret
  5621. setnbios endp
  5622.  
  5623. chknetbios proc    near            ; Test for Netbios presence, IBM way
  5624.     push    es
  5625.     mov    ah,35h            ; DOS get interrupt vector
  5626.     mov    al,netint        ; the netbios vector
  5627.     int    dos            ; returns vector in es:bx
  5628.     mov    ax,es
  5629.     or    ax,ax            ; undefined interrupt?
  5630.     jz    chknb1            ; z = yes
  5631.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  5632.     je    chknb1            ; e = yes
  5633.     mov    xmt.scb_cmd,7fh ; presence test, 7fh is illegal command code
  5634.     mov    xmt.scb_err,0        ; clear response field
  5635.     push    bx
  5636.     mov    bx,offset xmt        ; address of the session control block
  5637.     call    nbsession        ; execute operation
  5638.     pop    bx
  5639.     mov    al,xmt.scb_err        ; get response
  5640.     cmp    al,3            ; 'illegal function', so adapter is ready
  5641.     je    chknb1            ; e = success
  5642.     or    al,al
  5643.     jnz    chknb2            ; nz = not "good response" either
  5644. chknb1:    pop    es
  5645.     clc                ; netbios is present
  5646.     ret
  5647. chknb2:    pop    es
  5648.     stc                ; netbios is not present
  5649.     ret
  5650. chknetbios endp
  5651.  
  5652. chkstarlan proc near            ; AT&T STARLAN board check
  5653.     push    es
  5654.     mov    ah,35h            ; DOS get interrupt vector
  5655.     mov    al,2ah            ; PC net vector 2ah
  5656.     int    dos            ; returns vector in es:bx
  5657.     mov    ax,es
  5658.     or    ax,ax            ; undefined interrupt?
  5659.     jz    chkstar1        ; z = yes
  5660.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  5661.     je    chkstar1        ; e = yes
  5662.     xor    ah,ah            ; vendor installation check on int 2ah
  5663.     xor    al,al            ; do error retry
  5664.     int    2ah            ; session level interrupt
  5665.     cmp    ah,0ddh            ; 0ddh = magic number, success?
  5666.     jne    chkstar1        ; ne = no
  5667.                     ; Test for vector
  5668.     mov    ah,35h            ; DOS get interrupt vector
  5669.     mov    al,5bh            ; 5bh = STARLAN netbios ext'd vector
  5670.     int    dos            ; returns vector in es:bx
  5671.     mov    ax,es
  5672.     or    ax,ax            ; undefined interrupt?
  5673.     jz    chkstar1        ; z = yes
  5674.     cmp    byte ptr es:[bx],0cfh    ; points to IRET?
  5675.     je    chkstar1        ; e = yes
  5676.     pop    es
  5677.     clc                ; StarLAN is present
  5678.     ret
  5679. chkstar1:pop    es
  5680.     stc                ; StarLAN is not present
  5681.     ret
  5682. chkstarlan endp
  5683.  
  5684. ; Put a local name into the Netbios name table, ask user if conflicts.
  5685. setnbname proc    near
  5686.     cmp    lnamestat,2        ; validiated local Netbios name?
  5687.     jb    setnbn1            ; b = no
  5688.     ret                ; else quit here
  5689. setnbn1:call    chknetbios        ; Netbios presence check
  5690.     jnc    setnbn1a        ; nc = present
  5691.     ret
  5692.  
  5693. setnbn1a:mov    ah,prstr
  5694.     mov    dx,offset netmsg1    ; say checking node name
  5695.     int    dos
  5696.     push    word ptr xmt.scb_rname    ; save first two bytes (user spec)
  5697.     mov    byte ptr xmt.scb_rname,'*' ; call to local name
  5698.     push    bx
  5699.     mov    xmt.scb_cmd,naustat    ; get Network Adapter Unit status
  5700.     mov    bx,offset xmt
  5701.     call    nbsession
  5702.     pop    bx
  5703.     pop    word ptr xmt.scb_rname    ; restore remote name first two bytes
  5704. setnbn2:push    es
  5705.     push    si
  5706.     push    di
  5707.     mov    si,ds
  5708.     mov    es,si
  5709.     cld
  5710.     cmp    lnamestat,0        ; local name specified?
  5711.     jne    setnbn3            ; ne = yes
  5712.     mov    si,offset xmtbuf+60 ; where local name is returned (1st entry)
  5713.     cmp    word ptr xmtbuf+58,0    ; is local name empty?
  5714.     jne    setnbn4            ; ne = no, use name from table
  5715. setnbn3:mov    si,offset deflname    ; else use default local name
  5716. setnbn4:mov    di,offset xmt.scb_lname ; where to put it in scb
  5717.     mov    cx,14            ; 16 bytes minus extension of '.K'
  5718.     cld                ; append extension of '.K' to loc name
  5719. setnbn5:cmp    byte ptr[si],' ' ; find first space (end of regular node name)
  5720.     jbe    setnbn6            ; be = found one (or control code)
  5721.     movsb                ; copy local name to scb
  5722.     loop    setnbn5            ; continue though local name
  5723. setnbn6:cmp    word ptr [di-2],'K.'    ; is extension '.K' present already?
  5724.     je    setnbn7            ; e = yes, nothing to add
  5725.     cmp    word ptr [di-2],'k.'    ; check lower case too
  5726.     je    setnbn7            ; e = yes, nothing to add
  5727.     mov    word ptr [di],'K.'    ; append our extension of '.K'
  5728.     add    di,2            ; step over our new extension
  5729.     sub    cx,2
  5730.                     ; complete field with spaces
  5731. setnbn7:add    cx,2            ; 15th and 16th chars
  5732.     mov    al,' '            ; space as padding
  5733.     rep    stosb
  5734.     pop    di            ; clean stack from work above
  5735.     pop    si
  5736.     pop    es
  5737.  
  5738.     push    bx            ; Put our new local name in NAU
  5739.     mov    xmt.scb_cmd,nadd    ; ADD NAME, wait
  5740.     mov    bx,offset xmt
  5741.     call    nbsession
  5742.     pop    bx
  5743.     mov    al,xmt.scb_err        ; get error code
  5744.     or    al,al            ; success?
  5745.     jnz    setnbn8            ; nz = no
  5746.     jmp    setnbn12        ; success
  5747. setnbn8:cmp    al,0dh            ; duplicate name in local table?
  5748.     je    setnbn9            ; e = yes
  5749.     cmp    al,16h            ; name used elsewhere?
  5750.     je    setnbn9            ; e = yes
  5751.     cmp    al,19h            ; name conflict?
  5752.     je    setnbn9            ; e = yes
  5753.     push    ax
  5754.     mov    ah,prstr        ; another kind of error
  5755.     mov    dx,offset chkmsg1    ; say can't construct local name
  5756.     int    dos
  5757.     pop    ax
  5758.     call    decout            ; display it (in al)
  5759.     mov    ah,prstr
  5760.     mov    dx,offset crlf
  5761.     int    dos
  5762.     stc                ; set carry for failure
  5763.     ret
  5764.  
  5765. setnbn9:mov    ah,prstr        ; ask for another name
  5766.     mov    dx,offset chkmsg2    ; prompt message
  5767.     int    dos
  5768.     mov    ah,conout        ; show name itself
  5769.     push    si
  5770.     push    cx
  5771.     mov    cx,16            ; 16 bytes in name field
  5772.     mov    si,offset xmt.scb_lname
  5773. setnbn10:lodsb                ; get name char into al
  5774.     mov    dl,al
  5775.     int    dos
  5776.     mov    byte ptr[si-1],' '    ; clear old name as we go
  5777.     loop    setnbn10
  5778.     pop    cx
  5779.     pop    si
  5780.     mov    ah,prstr
  5781.     mov    dx,offset chkmsg3    ; rest of prompt
  5782.     int    dos
  5783.  
  5784.     mov    ah,0ah            ; read buffered line from stdin
  5785.     mov    dx,offset xmtbuf+58    ; where to put text (xmtbuf+60=text)
  5786.     mov    xmtbuf+58,15        ; buf capacity, including cr at end
  5787.     mov    xmtbuf+59,0        ; say text in buffer = none
  5788.     int    dos
  5789.     jc    setnbn11        ; c = error
  5790.     cmp    xmtbuf+59,0        ; any bytes read?
  5791.     je    setnbn11        ; e = no, exit failure
  5792.     mov    ah,prstr        ; say rechecking name
  5793.     mov    dx,offset netmsg1
  5794.     int    dos
  5795.     push    es
  5796.     mov    si,ds
  5797.     mov    es,si
  5798.     mov    si,offset xmtbuf+60    ; where text went
  5799.     mov    di,offset deflname    ; where local name is stored
  5800.     mov    cx,8
  5801.     cld
  5802.     rep    movsw            ; copy 14 chars to deflname
  5803.     mov    byte ptr [di],0        ; null terminator, to be safe
  5804.     pop    es
  5805.     mov    lnamestat,1        ; say local name specified
  5806.     jmp    setnbn2            ; go reinterpret name
  5807.  
  5808. setnbn11:stc                ; set carry for failure
  5809.     ret
  5810.  
  5811. setnbn12:mov    dx,offset netmsg2     ; say net is going
  5812.     mov    ah,prstr
  5813.     int    dos
  5814.     push    si
  5815.     push    di
  5816.     push    es
  5817.     mov    si,ds
  5818.     mov    es,si
  5819.     mov    si,offset xmt.scb_lname ; display our local name
  5820.     mov    di,offset deflname    ; local Netbios name
  5821.     mov    ah,conout
  5822.     mov    cx,16
  5823.     cld
  5824. setnbn13:lodsb                ; byte from si to al
  5825.     stosb                ; and store in local Netbios name
  5826.     mov    dl,al
  5827.     int    dos            ; display it
  5828.     loop    setnbn13
  5829.     pop    es
  5830.     pop    di
  5831.     pop    si
  5832.     mov    lnamestat,2        ; say local name is fixed now
  5833.     mov    ah,prstr
  5834.     mov    dx,offset crlf        ; add cr/lf
  5835.     int    dos
  5836.     clc                ; carry clear for success
  5837.     ret
  5838. setnbname endp
  5839.  
  5840. ; Network session exists. Tell user and ask for new node or Resume.
  5841. ; Returns carry set if Resume response, else carry clear for New.
  5842. chknew    proc    near
  5843.     mov    ax,takadr        ; we could be in a macro or Take file
  5844.     push    ax            ; save Take address
  5845.     mov    al,taklev
  5846.     xor    ah,ah
  5847.     push    ax            ; and Take level
  5848.     push    dx
  5849.     mov    dx,size takinfo        ; bytes for each current Take
  5850.     mul    dx            ; times number of active Take/macros
  5851.     pop    dx
  5852.     sub    takadr,ax        ; clear Take address as if no
  5853.     mov    taklev,0        ;  Take/macro were active so that
  5854.  
  5855.     mov    dx,offset naskpmt    ; prompt for New or Resume
  5856.     call    prompt
  5857.     mov    dx,offset nettab    ; table of answers
  5858.     xor    bx,bx            ; help for the question
  5859.     mov    ah,cmkey        ; get answer keyword
  5860.     mov    comand.cmcr,1        ; allow bare CR's
  5861.     call    comnd
  5862.     mov    comand.cmcr,0        ; dis-allow bare CR's
  5863.     jc    chknew1            ; c = failure, means Resume
  5864.     push    bx
  5865.     mov    ah,cmeol        ; get a confirm
  5866.     call    comnd
  5867.     pop    bx
  5868.     jc    chknew1            ; c = failure, resume session
  5869.     or    bx,bx            ; 0 for new?
  5870.     jz    chknew1            ; z = yes, return carry clear
  5871.     stc                ; set carry for resume
  5872. chknew1:pop    ax
  5873.     mov    taklev,al        ; restore Take level
  5874.     pop    takadr            ; restore Take address
  5875.     ret                ; carry may be set
  5876. chknew    endp
  5877.  
  5878. ;                    ; [ohl] ++++
  5879. ; Verifies existance of interrupt 6Bh support, verifies vendor specific
  5880. ; support for BREAK and other features, sets network type bit in nettype,
  5881. ; sets BREAK support in nsbrk and sets network status byte pcnet to 0
  5882. ; (no net) or to 1 (net ready). This is the first procedure called to
  5883. ; init Ungermann-Bass NETCI terminal port network usage.
  5884. chkub  proc    near
  5885.     push    bx
  5886.         push    es                      ; Test for vector
  5887.         mov     ah,35h                  ; DOS get interrupt vector
  5888.         mov     al,6bh                  ; 6bh = Net/One command interpreter
  5889.                     ;  interface, with break support
  5890.         int     dos                     ; returns vector in es:bx
  5891.     mov    ax,es            ; is vector in rom bios?
  5892.     or    ax,ax            ; undefined vector?
  5893.     jz    chkub0            ; z = yes
  5894.     cmp    byte ptr es:[bx],0cfh    ; points at IRET?
  5895.     je    chkub0            ; e = yes
  5896. ;some    mov    al,0ffh            ; test value (anything non-zero)
  5897. ;emulators mov    ah,2            ; function code for testing net board
  5898. ;flunk    int    netci
  5899. ;this    or    al,al            ; al = 0 means board is ok
  5900. ;test    jnz    chkub0            ; nz = not ok
  5901.     pop    es
  5902.     pop    bx
  5903.         mov     nsbrk,1                 ; network BREAK supported
  5904.         or      nettype,netone        ; say have Net/One
  5905.     clc                ; return success
  5906.     ret
  5907.  
  5908. chkub0:    pop    es            ; clean stack from above
  5909.     pop    bx
  5910.     push    ax
  5911.         push    dx
  5912.         mov     ah,prstr
  5913.         mov     dx,offset nonetmsg      ; say network is not available
  5914.         int     dos
  5915.         pop     dx
  5916.         pop     ax
  5917.         stc                             ; set carry for failure
  5918.         ret                             ; and exit now
  5919. chkub  endp
  5920.  
  5921. ; local routine to see if we have to transmit an xon
  5922. chkxon    proc    near
  5923.     test    flowcnt,1+4        ; doing output/RTS flow control?
  5924.     jz    chkxo1            ; z = no, skip all this
  5925.     test    xofsnt,usron        ; did user send an xoff?
  5926.     jnz    chkxo1            ; nz = yes, don't contradict it here
  5927.     test    xofsnt,bufon        ; have we sent a buffer level xoff?
  5928.     jz    chkxo1            ; z = no, forget it
  5929.     cmp    count,mntrgl        ; below (low water mark) trigger?
  5930.     jae    chkxo1            ; no, forget it
  5931.     test    flowcnt,4        ; using RTS/CTS kind?
  5932.     jz    chkxo2            ; z = no
  5933.     cmp    flags.comflg,4        ; using uart?
  5934.     ja    chkxo1            ; a = no, ignore situation
  5935.     push    ax
  5936.     push    dx
  5937.     mov    dx,modem.mddat        ; serial port base address
  5938.     add    dx,4            ; increment to control register
  5939.     in    al,dx
  5940.     or    al,2            ; assert RTS for flow-on
  5941.     push    ax
  5942.     in    al,ppi_port        ; delay
  5943.     pop    ax
  5944.     out    dx,al
  5945.     and    xofsnt,off        ; remember we've sent the "xon"
  5946.     pop    dx
  5947.     pop    ax
  5948.                     ; do software flow control too
  5949. chkxo2:    test    flowcnt,1        ; using outgoing XON/XOFF kind?
  5950.     jz    chkxo1            ; z = no
  5951.     mov    ah,flowon        ; ah gets xon
  5952.     and    xofsnt,off        ; remember we've sent the xon
  5953.     call    outch2            ; send via non-flow controlled entry point
  5954. chkxo1:    ret
  5955. chkxon    endp
  5956.  
  5957. ; IHOSTS - Initialize the host by sending XOFF, or equivalent.
  5958. ; Requires that the port be initialized before hand.
  5959. ; Do not send flow control if doing half duplex.
  5960.  
  5961. IHOSTS    PROC    NEAR
  5962.     push    ax        ; save the registers
  5963.     push    bx
  5964.     push    cx
  5965.     push    dx
  5966.     mov    xofrcv,off    ; clear old xoff received flag
  5967.     mov    xofsnt,off    ; and old xoff sent flag
  5968.     cmp    portin,0    ; is a comms port active?
  5969.     jle    ihosts1        ; le = no
  5970.     mov    bx,portval
  5971.     cmp    flowcnt,4    ; using CTS/RTS?
  5972.     je    ihosts2        ; e = yes
  5973.     mov    ah,byte ptr [bx].flowc ; put wait flow control char in ah
  5974.     or    ah,ah        ; check for null char
  5975.     jz    ihosts1        ; z = null, don't send it
  5976.     cmp    dupflg,0    ; full duplex?
  5977.     jne    ihosts1        ; ne = no, half
  5978.     call    outchr        ; send it
  5979.     jmp    short ihosts1
  5980. ihosts2:cmp    flags.comflg,4        ; using uart?
  5981.     ja    ihosts1            ; a = no, ignore situation
  5982.     mov    dx,modem.mddat        ; serial port base address
  5983.     add    dx,4            ; increment to control register
  5984.     in    al,dx
  5985.     and    al,not 2        ; clear RTS for flow-off
  5986.     push    ax
  5987.     in    al,ppi_port        ; delay
  5988.     pop    ax
  5989.     out    dx,al
  5990.     or    xofsnt,bufon        ; remember we've sent the "xoff"
  5991. ihosts1:pop    dx
  5992.     pop    cx
  5993.     pop    bx
  5994.     pop    ax
  5995.     ret
  5996. IHOSTS    ENDP
  5997.  
  5998. ; IHOSTR - initialize the remote host for our reception of a file by
  5999. ; sending the flow-on character (XON typically) to release any held
  6000. ; data. Do not send flow control if doing half duplex.
  6001. IHOSTR    PROC    NEAR
  6002.     push    ax        ; save regs
  6003.     push    bx
  6004.     push    cx
  6005.     mov    xofrcv,off    ; clear old xoff received flag
  6006.     mov    xofsnt,off    ; and old xoff sent flag
  6007.     cmp    portin,0    ; is a comms port active?
  6008.     jle    ihostr1        ; le = no
  6009.     mov    bx,portval
  6010.     cmp    flowcnt,4    ; using CTS/RTS?
  6011.     je    ihostr2        ; e = yes
  6012.     mov    ah,byte ptr [bx].flowc+1; put go-ahead flow control char in ah
  6013.     or    ah,ah        ; check for null char
  6014.     jz    ihostr1        ; z = null, don't send it
  6015.     cmp    dupflg,0    ; full duplex?
  6016.     jne    ihostr1        ; ne = no, half
  6017.     call    outchr        ; send it (release Host's output queue)
  6018.     jmp    short ihostr1
  6019. ihostr2:cmp    flags.comflg,4        ; using uart?
  6020.     ja    ihostr1            ; a = no, ignore situation
  6021.     push    dx
  6022.     mov    dx,modem.mddat        ; serial port base address
  6023.     add    dx,4            ; increment to control register
  6024.     in    al,dx
  6025.     or    al,2            ; assert RTS for flow-on
  6026.     push    ax
  6027.     in    al,ppi_port        ; delay
  6028.     pop    ax
  6029.     out    dx,al
  6030.     and    xofsnt,off        ; remember we've sent the "xon"
  6031.     pop    dx
  6032. ihostr1:pop    cx
  6033.     pop    bx
  6034.     pop    ax
  6035.     ret
  6036. IHOSTR    ENDP
  6037.  
  6038. ; Send a break out the current serial port.  Returns normally.
  6039. ; Do both regular and long Break.
  6040. ; Networks use flags.comflg so that more than one net can be active
  6041. SENDBR    PROC    NEAR
  6042.     push    cx        ; Regular Break entry point
  6043.     mov    cx,275        ; 275 milliseconds in regular Break
  6044.     call    sendbw        ; call worker routine to do it
  6045.     pop    cx
  6046.     mov    flags.cxzflg,0    ; clear in case Control-Break
  6047.     clc            ; don't exit Connect mode
  6048.     ret
  6049. SENDBL:    push    cx        ; Long Break entry point
  6050.     mov    cx,1800        ; 1.8 second long break
  6051.     call    sendbw        ; call worker routine to do it
  6052.     pop    cx
  6053.     mov    flags.cxzflg,0    ; clear in case Control-Break
  6054.     clc            ; don't exit Connect mode
  6055.     ret
  6056.                 ; worker - send Break for cx millisec
  6057. sendbw:    mov    al,flags.comflg    ; get type of port
  6058.     cmp    al,4        ; running on a UART or network?
  6059.     ja    sendbw2        ; a = yes
  6060.     push    dx        ; UART BREAK
  6061.     mov    dx,modem.mdcom    ; port address
  6062.     in    al,dx        ; get current setting
  6063.     push    ax        ; save setting on the stack
  6064.     or    al,brkbit    ; set send-break bit(s)
  6065.     out    dx,al        ; start the break
  6066.     mov    ax,cx        ; # of ms to wait
  6067.     call    pcwait        ; hold break for desired interval
  6068.     pop    ax        ; restore Line Control Register
  6069.     out    dx,al        ; stop the break
  6070.     pop    ax
  6071.     ret
  6072. sendbw2:cmp    al,'N'        ; is this a NetBios network port?
  6073.     jne    sendbw3        ; ne = no
  6074.     cmp    starlan,0    ; STARLAN: network break supported?
  6075.     jne    sendbw2a    ; ne = no
  6076.     push    bx
  6077.     push    es        ; save es around call
  6078.     push    ds
  6079.     pop    es        ; make es:bx point to scb in data segment
  6080.     mov    bx,offset can    ; use Cancel control block
  6081.     mov    can.scb_cmd,netbrk ; send net Break command
  6082.     int    5bh        ; use network Break interrupt
  6083.     pop    es        ; saved registers
  6084.     pop    bx
  6085. sendbw2a:ret
  6086.  
  6087. sendbw3:cmp    al,'E'            ; EBIOS?
  6088.     jne    sendbw6            ; ne = no
  6089.     test    nettype,acsi        ; using EBIOS.COM?
  6090.     jnz    sendbw4            ; nz = no
  6091.     push    ax
  6092.     push    dx
  6093.     mov    dx,ebport        ; port 0..3
  6094.     mov    ah,ebbreak        ; EBIOS send BREAK
  6095.     int    rs232            ; bios send
  6096.     pop    dx
  6097.     pop    ax
  6098.     ret
  6099. sendbw4:call    send            ; send current buffer first
  6100.     mov    word ptr xmtbufx,4    ; four bytes in packet
  6101.     mov    word ptr xmtbufx+2,acbreak*256+0 ; BREAK cmd, null char
  6102.     call    send            ; send the command
  6103.     ret
  6104.  
  6105. sendbw6:cmp    al,'U'            ; UB NETCI or Novell NASI/NACS?
  6106.     je    sendbw6a        ; e = yes
  6107.     cmp    al,'W'            ; NASI/NACS?
  6108.     jne    sendbw7            ; ne = no
  6109. sendbw6a:push    cx            ; UB port send break         [ohl]
  6110.     mov    ax,ncicont+0    ; call control, use 0 for network port num
  6111.     mov    cl,ncibrk        ; request break             [ohl]
  6112.     int    netci        ; Net/One command interface int. (6Bh)     [ohl]
  6113.     pop    cx
  6114.     ret
  6115.  
  6116. sendbw7:cmp    al,'D'            ; DECnet?
  6117.     jne    sendbw9            ; ne = no
  6118.     test    nettype,declat        ; LAT?
  6119.     jz    sendbw9            ; z = no, CTERM cannot send a BREAK
  6120.     mov    ax,latbreak        ; LAT BREAK command
  6121.     push    dx
  6122.     mov    dx,lathand        ; LAT handle
  6123.     int    latint
  6124.     pop    dx
  6125.     ret
  6126.  
  6127. sendbw9:cmp    al,'C'            ; 3Com BAPI or TCP Telnet?
  6128.     je    sendbw9a        ; e = yes
  6129.     cmp    al,'t'
  6130.     jne    sendbw10        ; ne = no
  6131. sendbw9a:mov    ah,bapibrk        ; BAPI, send BREAK
  6132.     xor    dh,dh            ; session id of 0 (external sessions)
  6133.     cmp    al,'t'            ; TCP/IP Telnet?
  6134.     jne    sendbw9b        ; ne = no
  6135.     call    ktcpcom            ; Far call TCP/IP Telnet code
  6136.     ret
  6137. sendbw9b:int    bapiint
  6138.     ret
  6139. sendbw10:cmp    al,'T'            ; Novell TELAPI?
  6140.     jne    sendbw11        ; ne = no
  6141.     mov    ah,255            ; Telnet Interpret As Command char
  6142.     call    outchr            ; send it
  6143.     mov    ah,244            ; Telnet Interrupt Process char
  6144.     call    outchr            ; send it
  6145.     ret
  6146. sendbw11:cmp    al,'I'            ; TES?
  6147.     jne    sendbw12        ; ne = no
  6148.     cmp    teslat,0        ; using LAT?
  6149.     je    sendbw11a        ; e = no, older TES
  6150.     mov    ax,latbreak        ; LAT BREAK command
  6151.     push    dx
  6152.     mov    dx,lathand        ; LAT handle
  6153.     int    latint
  6154.     pop    dx
  6155.     ret
  6156. sendbw11a:mov    ah,testalk        ; get command interpreter
  6157.     mov    dx,tesport
  6158.     int    rs232
  6159. sendbw12:ret
  6160. SENDBR    ENDP
  6161.  
  6162. ; Initialization for using serial port.  This routine performs
  6163. ; any initialization necessary for using the serial port, including
  6164. ; setting up interrupt routines, setting buffer pointers, etc.
  6165. ; Doing this twice in a row should be harmless (this version checks
  6166. ; a flag and returns if initialization has already been done).
  6167. ; SERRST below should restore any interrupt vectors that this changes.
  6168. ;
  6169. ; Revised slightly by Joe R. Doupnik 22 Dec 1985 to prevent interrupts
  6170. ; being enabled until we're done, to stop interrupts from occurring when
  6171. ; TX holding buffer becomes empty (a useless interrupt for us), and to
  6172. ; shorten the time between enabling interrupts and our exit.
  6173. ; Returns carry clear if success, else carry set.
  6174. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  6175. SERINI    PROC    NEAR
  6176.     call    pcwtst            ; recalibrate pcwait loop timer
  6177.     cmp    portin,0        ; did we initialize port already?
  6178.     je    serin4            ; e = yes
  6179.     jl    serin3            ; l = no, not yet
  6180.     jmp    serin30            ; yes, update flow and leave
  6181. serin3:    mov    bl,flags.comflg        ; pass current port ident
  6182.     mov    portin,0        ; say have been here once
  6183.     call    comstrt            ; do SET PORT now
  6184.     jnc    serin4            ; nc = success
  6185.     ret                ; failed, exit now
  6186. serin4:    push    bx
  6187.     mov    bx,portval
  6188.     mov    bl,[bx].duplex        ; get full/half duplex flag, local cpy
  6189.     mov    dupflg,bl
  6190.     pop    bx
  6191.     cmp    flags.comflg,4        ; UART?
  6192.     jbe    serin5            ; be = yes, real thing
  6193.     jmp    serin8            ; else try other port kinds
  6194.  
  6195. serin5:    push    bx
  6196.     push    es
  6197.     mov    dx,modem.mdmintc    ; interrupt controller
  6198.     inc    dx            ; look at interrupt mask
  6199.     in    al,dx            ; get interrupt mask
  6200.     mov    savirq,al        ; save state here for restoration
  6201.     or    al,modem.mddis        ; inhibit our IRQ
  6202.     out    dx,al
  6203.     mov    al,byte ptr modem.mdintv ; desired interrupt vector
  6204.     mov    ah,35H            ; Int 21H, function 35H = Get Vector
  6205.     int    dos            ; get vector into es:bx
  6206.     mov    word ptr savsci,bx    ; save address offset of original vector
  6207.     mov    word ptr savsci+2,es     ;  and its segment
  6208.     mov    al,byte ptr modem.mdintv ; interrupt number for IRQ
  6209.     mov    dx,offset serint    ; offset of our interrupt routine
  6210.     push    ds            ; save ds around next DOS call
  6211.     mov    bx,seg serint        ; compose full address of our routine
  6212.     mov    ds,bx            ; segment is the code segment
  6213.     mov    ah,setintv        ; set interrupt address from ds:dx
  6214.     int    dos
  6215.     pop    ds
  6216.     mov    al,rs232        ; interrupt number for Bios serial port
  6217.     mov    ah,getintv        ; get vector into es:bx
  6218.     int    dos
  6219.     mov    word ptr sav232,bx    ; save offset
  6220.     mov    word ptr sav232+2,es    ; save segment
  6221.     mov    dx,offset serdum    ; offset of our interrupt routine
  6222.     push    ds            ; save ds around next DOS call
  6223.     mov    bx,seg serdum        ; compose full address of our routine
  6224.     mov    ds,bx            ; segment is the code segment
  6225.     mov    ah,setintv        ; set interrupt address from ds:dx
  6226.     int    dos
  6227.     pop    ds
  6228.     pop    es
  6229.     pop    bx
  6230.     mov    portin,1        ; Remember port has been initialized
  6231.     mov    ax,modem.mdstat
  6232.     mov    mst,ax            ; Use this address for status
  6233.     mov    ax,modem.mddat
  6234.     mov    mdat,ax            ; Use this address for data
  6235.     mov    ax,modem.mdiir
  6236.     mov    miir,ax            ; uart interrupt ident register
  6237.     cli                ; Disable interrupts
  6238.     cld                ; Do increments in string operations
  6239.     mov    al,modem.mdmeoi
  6240.     mov    mdeoi,al        ; Use to signify end-of-interrupt
  6241.     mov    dx,modem.mdmintc    ; interrupt controller cntl address
  6242.     mov    mdintc,dx
  6243.     inc    dx            ; access OCW1, interrupt mask byte
  6244.     in    al,dx            ; get 8259 interrupt mask
  6245.     and    al,modem.mden        ; enable IRQ. (bit=0 means enable)
  6246.     out    dx,al            ; rewrite interrupt mask byte
  6247.     mov    dx,modem.mdcom
  6248.     inc    dx            ; modem control register (3fch)
  6249.     mov    al,0fh            ; set DTR, RTS, OUT1, OUT2
  6250.     out    dx,al
  6251.     call    delay
  6252.     dec    dx            ; set up serial card Line Control Reg
  6253.     in    al,dx            ; get present settings
  6254.     mov    savlcr,al        ; save them for restoration
  6255.     call    delay            ; Telepath with this delay removed
  6256.     mov    al,3            ; 8 data bits. DLAB = 0
  6257.     out    dx,al
  6258.     call    delay            ; Telepath fails if this is removed
  6259.     mov    dx,modem.mddat
  6260.     inc    dx            ; int enable reg (03f9)
  6261.     in    al,dx
  6262.     mov    savier,al        ; save for restoration
  6263.     mov    dx,modem.mdiir        ; Interrupt Ident reg (03fah)
  6264.     in    al,dx            ; read current setting
  6265.     call    delay            ; Telepath fails if this is removed
  6266.     mov    al,087h    ; 8 byte trigger (80), reset fifos (2/4), Rx fifo(1) 
  6267.     out    dx,al
  6268.     mov    fifo,al            ; assume FIFO is active
  6269.     call    delay            ; Telepath fails if this is removed
  6270.     in    al,dx            ; read back iir
  6271.     and    al,0c0h    ; select BOTH fifo bits: 16550A vs 16550 (bad fifo)
  6272.     cmp    al,0c0h            ; are both fifo enabled bits set?
  6273.     je     serin6            ; e = yes, rcvr fifo is ok (16550/A)
  6274.     call    delay            ; Telepath fails if this is removed
  6275.     xor    al,al            ; else turn off fifo mode (16550/etc)
  6276.     out    dx,al
  6277.     mov    fifo,al            ; say no FIFO
  6278.     call    delay
  6279. serin6:mov    dx,modem.mddat       ; data and command port, read and flush any    
  6280.     in    al,dx            ; char in UART's receive buffer
  6281.     inc    dx              ; interrupt enable register 3f9h
  6282.     call    delay            ; Telepath fails if this is removed
  6283.     mov    al,1            ; set up interrupt enable register
  6284.     out    dx,al            ;  for Data Available only
  6285.     call    delay            ; Telepath fails if this is removed
  6286.     add    dx,3               ; modem control register 3fch
  6287.     in    al,dx            ; read original
  6288.     mov    savstat,al        ; save original
  6289.     mov    al,0bh          ; assert DTR, RTS, not OUT1, and OUT2
  6290.     cmp    dupflg,0        ; full duplex?
  6291.     je    serin7            ; e = yes
  6292.     mov    al,9h            ; assert DTR, not RTS, not OUT1, OUT2
  6293. serin7:out    dx,al          ; OUT2 high turns on interrupt driver chip
  6294.     sti
  6295.     jmp    serin30            ; finish up
  6296.  
  6297. serin8:    mov    al,flags.comflg
  6298.     cmp    al,'N'            ; NetBios?
  6299.     je    serin9            ; e = yes
  6300.     cmp    al,'O'            ; Opennet Network? (FGR)
  6301.     jne    serin11            ; ne = no
  6302. serin9:mov    port_nb.portrdy,0    ; say port is not ready yet
  6303.     call    setnet            ; setup network session and pcnet flag
  6304.     jc    serin10            ; c = failed
  6305.     jmp    serin30            ; nc = success
  6306. serin10:ret                ; fail, carry set, leave portin at 0
  6307. serin11:cmp    al,'E'            ; using EBIOS?
  6308.     jne    serin13            ; ne = no
  6309.     test    nettype,acsi        ; using EBIOS.COM?
  6310.     jnz    serin9            ; nz = not using it
  6311.     mov    bx,offset ebcoms    ; es:bx to ebcoms structure
  6312.     mov    ebcoms+1,80h        ; force a network connection
  6313.     mov    ah,ebredir        ; do redirection
  6314.     xor    al,al
  6315.     mov    dx,ebport
  6316.     int    rs232
  6317.     or    ax,ax
  6318.     jz    serin12            ; ax = 0 is success
  6319.     stc                ; fail
  6320.     ret
  6321. serin12:mov    dx,ebport        ; port 0..3
  6322.     mov    bx,offset rcvbuf    ; receive buffer for EBIOS
  6323.     push    es
  6324.     mov    ax,ds
  6325.     mov    es,ax            ; set es:bx to the buffer address
  6326.     mov    cx,nbuflen        ; set cx to buffer's length
  6327.     mov    ax,ebbufset*256+2    ; set rcvr buffered mode
  6328.     int    rs232
  6329.     mov    cx,nbuflen
  6330.     mov    bx,offset xmtbuf    ; EBIOS transmitter work buffer
  6331.     mov    ax,ebbufset*256+1    ; set xmtr buffered mode
  6332.     int    rs232
  6333.     mov    ax,ebmodem*256+3    ; set outgoing DTR and RTS modem leads
  6334.     int    rs232            ;  and ignore incoming leads
  6335.     mov    pcnet,1
  6336.     pop    es
  6337.     jmp    short serin30
  6338. serin13:cmp    al,'D'            ; DECnet?
  6339.     jne    serin14            ; ne = no
  6340.     call    decstrt            ; reinit
  6341.     jnc    serin30            ; nc = success
  6342.     ret                ; fail, carry set, leave portin at 0
  6343. serin14:cmp    al,'T'            ; Novell TELAPI?
  6344.     jne    serin15            ; ne = no
  6345.     cmp    pcnet,2            ; going already?
  6346.     je    serin30            ; e = yes
  6347.     call    telstrt            ; start Telnet session
  6348.     jnc    serin30            ; nc = success
  6349.     call    telapiclose        ; close session
  6350.     stc
  6351.     ret                ; fail, leave portin at 0
  6352. serin15:cmp    al,'I'            ; TES?
  6353.     jne    serin17            ; ne = no
  6354.     cmp    teslat,0        ; using LAT?
  6355.     je    serin16            ; e = no, older style
  6356.     call    decstrt            ; reinit
  6357.     jnc    serin30            ; nc = success
  6358.     ret                ; fail, carry set, leave portin at 0
  6359. serin16:call    tesstrt            ; start a TES session
  6360.     jnc    serin30            ; nc = success
  6361.     mov    ax,2000            ; pause 2 sec for any msg
  6362.     call    pcwait
  6363.     stc
  6364.     ret
  6365. serin17:cmp    al,'t'            ; TCP/IP?
  6366.     jne    serin18            ; ne = no
  6367.     call    tcpstart        ; start TCP connection
  6368.     jnc    serin30
  6369.     ret                ; fail
  6370. serin18:cmp    al,'U'            ; Ungermann Bass?
  6371.     je    serin20            ; e = yes
  6372.     cmp    al,'C'            ; 3Com BAPI?
  6373.     je    serin20            ; e = yes
  6374. serin19:cmp    al,'b'            ; [JRS] Beame & Whiteside TCP
  6375.     jne    serin20            ; [JRS] ne = no
  6376.     call    bwstart            ; [JRS] start a Telnet session w/BWTCP
  6377.     jnc    serin30            ; [JRS] nc = success
  6378.     ret                ; [JRS]
  6379. serin20:mov    bl,al            ; preset net type
  6380.     call    comstrt            ; start net
  6381.     jnc    serin30
  6382.     ret                ; c = failure
  6383.  
  6384. serin30:push    bx
  6385.     mov    bx,portval        ; get port data structure
  6386.     mov    [bx].portrdy,1        ; say the comms port is ready
  6387.     mov    parmsk,0ffh        ; parity mask, assume parity is None
  6388.     cmp    [bx].parflg,parnon    ; is it None?
  6389.     je    serin31            ; e = yes
  6390.     mov    parmsk,07fh        ; no, pass lower 7 bits as data
  6391. serin31:xor    ax,ax
  6392.     mov    al,[bx].floflg        ; flow control kind
  6393.     mov    flowcnt,al        ; save here for active use
  6394.     mov    ax,[bx].flowc        ; get flow control chars
  6395.     mov    flowoff,al        ; xoff or null
  6396.     mov    flowon,ah        ; xon or null
  6397.     mov    xofrcv,off        ; clear xoff received flag
  6398.     pop    bx
  6399.     mov    quechar,0        ; clear outchr queued flow control
  6400.     mov    portin,1        ; say initialized
  6401.     clc                ; carry clear for success
  6402.     ret                ; We're done
  6403. SERINI    ENDP
  6404.  
  6405. ; Gateway 2000 Telepath internal modem extra delay routine
  6406. delay    proc    near
  6407.     push    ax
  6408.     mov    ax,1            ; 1 millisecond
  6409.     call    pcwait
  6410.     pop    ax
  6411.     ret
  6412. delay    endp
  6413.  
  6414. ; Reset the serial port.  This is the opposite of serini.  Calling
  6415. ; this twice without intervening calls to serini should be harmless.
  6416. ; Moved push/pop es code to do quicker exit before interrupts enabled.
  6417. ; Returns normally.
  6418. ; 22 June 1986 Leave OUT1 low to avoid resetting Hayes 1200B's. [jrd]
  6419. ; 21 Feb 1987 Add support for Bios calls [jrd]
  6420. ; 17 May 1987 Redo for COM3/4 support [jrd]
  6421. ; 9 July 1989 Accomodate 16550/A receiver fifo mode. [jrd]
  6422. SERRST    PROC    NEAR
  6423.     cmp    portin,0        ; Reset already? 
  6424.     jg    srst3            ; g = no
  6425.     clc
  6426.     ret                ; e = yes, l=not used yet, just leave
  6427. srst3:    cmp    flags.comflg,'0'    ; Bios or networks?
  6428.     jb    srst4            ; b = no, real UART
  6429.     jmp    srst8            ; finish up
  6430.  
  6431. srst4:    push    word ptr savsci        ; save original interrupt owner
  6432.     push    word ptr savsci+2    ; offset and segment
  6433.     mov    word ptr savsci,offset nulint ; redirect to our null routine
  6434.     mov    ax,seg nulint        ; segment of null routine is code
  6435.     mov    word ptr savsci+2,ax
  6436.     xor    cx,cx            ; loop counter
  6437. srst2:    mov    dx,modem.mdstat        ; status register
  6438.     in    al,dx
  6439.     call    delay            ; delay
  6440.         and     al,60h            ; Shift Reg Empty & Holding Reg Empty
  6441.         cmp     al,60h            ; are both set?
  6442.         loopne  srst2               ; ne = no, wait until so (or timeout)
  6443.     xor    al,al
  6444.     mov    dx,modem.mdiir        ; modem Interrupt Ident reg (03fah)
  6445.     out    dx,al            ; turn off FIFO mode
  6446.     call    delay
  6447.     dec    dx            ; point at int enable reg 3f9h
  6448.     out    dx,al            ; disable interrupts from this source
  6449.     call    delay            ; delay, let stray ints occur now
  6450.     add    dx,2            ; point at Line Control Register 3fbh
  6451.     mov    al,savlcr        ; saved bit pattern
  6452.     and    al,not 80h        ; force DLAB bit to 0
  6453.     out    dx,al            ; restore line control state
  6454.     call    delay
  6455.         ; clear modem's delta status bits and reassert DTR etc
  6456.     inc    dx        ; increment to modem control register 3fch
  6457.     mov    al,savstat        ; saved modem control reg (03fch)
  6458.     or    al,3            ; ensure DTR and RTS are asserted
  6459.     cmp    dupflg,0        ; full duplex?
  6460.     je    srst2a            ; e = yes
  6461.     xor    cx,cx
  6462.     push    dx            ; save dx around test below
  6463. srst2b:    mov    dx,modem.mdstat        ; modem line status reg
  6464.     in    al,dx            ; read transmitter shift reg empty bit
  6465.     call    delay
  6466.     test    al,40h            ; is it empty?
  6467.     loopz    srst2b            ; z = no, not yet
  6468.     pop    dx
  6469.     mov    al,savstat        ; saved modem control reg
  6470.     or    al,1            ; assert DTR
  6471.     and    al,not 2        ; unassert RTS
  6472. srst2a:    out    dx,al            ; restore modem control reg (03fch)
  6473.     call    delay        ; pause, in case stray interrupt is generated
  6474.     add    dx,2            ; modem status register 3feh
  6475.     in    al,dx            ; clear status register by reading it
  6476.     mov    mdmhand,al        ; save here for Show Modem
  6477.     call    delay
  6478.     cli                ; Disable interrupts
  6479.     mov    dx,modem.mdmintc
  6480.     inc    dx
  6481.     in    al,dx            ; Interrupt controller int mask
  6482.     or    al,modem.mddis        ; inhibit our IRQ line
  6483.     call    delay
  6484.     out    dx,al
  6485.     pop    word ptr savsci+2    ; recover original int owner's addr
  6486.     pop    word ptr savsci
  6487.                     ; replace original IRQ intrpt vector
  6488.     push    bx
  6489.     mov    al,byte ptr modem.mdintv ; vector number to do
  6490.     mov    dx,word ptr savsci     ; offset part
  6491.     push    ds
  6492.     mov    bx,word ptr savsci+2    ; segment part
  6493.     mov    ds,bx            ; ds:dx has interrupt vector
  6494.     mov    ah,setintv        ; set interrupt vector
  6495.     int    dos            ; replaced
  6496.     pop    ds
  6497.     mov    al,rs232    ; Bios serial port interrupt vector to restore
  6498.     mov    dx,word ptr sav232    ; offset part
  6499.     push    ds
  6500.     mov    bx,word ptr sav232+2    ; segment part
  6501.     mov    ds,bx
  6502.     mov    ah,setintv        ; set interrupt vector
  6503.     int    dos
  6504.     pop    ds
  6505.     pop    bx
  6506.     cli
  6507.     mov    ah,savirq        ; saved Interrupt state
  6508.     and    ah,modem.mddis        ; pick out our IRQ bit
  6509.     mov    dx,modem.mdmintc    ; interrupt controller cntl address
  6510.     inc    dx
  6511.     in    al,dx            ; get current intrpt controller state
  6512.     push    ax
  6513.     in    al,ppi_port        ; delay
  6514.     pop    ax
  6515.     and    al,modem.mden        ; set our bit to zero
  6516.     or    al,ah            ; set previous state of our IRQ
  6517.     out    dx,al            ; reset IRQ to original state
  6518.     sti
  6519.     mov    dx,modem.mddat        ; base address, 03f8h
  6520.     inc    dx                  ; Interrupt Enable Reg (03f9h)
  6521.     mov    al,savier        ; saved IER
  6522.     out    dx,al            ; restore setting
  6523.                     ; non-UART processes
  6524. srst8:    mov    portin,0        ; reset flag
  6525.     push    bx
  6526.     mov    bx,portval        ; port data structure
  6527.     mov    [bx].portrdy,0        ; say port is not ready
  6528.     pop    bx
  6529.     mov    quechar,0        ; clear any outchr queued char
  6530.     clc
  6531.     ret
  6532. SERRST    ENDP
  6533. code    ends
  6534.  
  6535. code1    segment
  6536.     assume    cs:code1
  6537. ; Null interrupt routine, to handle strays
  6538. nulint    proc    near
  6539.     push    ax
  6540.     push    dx
  6541.     push    ds
  6542.     mov    ax,data            ; set data seg addressibility
  6543.     mov    ds,ax
  6544.     mov    al,mdeoi        ; specific EOI
  6545.     mov    dx,mdintc        ; interrupt controller control word
  6546.     out    dx,al
  6547.     test    dl,80h            ; slave controller?
  6548.     jz    nulint1            ; z = no
  6549.     mov    al,20h            ; general EOI
  6550.     out    20h,al            ; EOI to master 8259
  6551. nulint1:pop    ds
  6552.     pop    dx
  6553.     pop    ax
  6554.     iret
  6555. nulint    endp
  6556.  
  6557. ; Dummy Interrupt 14H to defeat DOS interference with serial port when CTTY
  6558. ; and Kermit use the port simultaneously. If ports differ then chain DOS to
  6559. ; original Int 14H Bios code. Else return dummy status=ok reports and
  6560. ; Backspace for Read, ignore char for Write.
  6561. ; Entered with AH = function request, AL = char to be sent, DX = com port num
  6562. ; CS is our code segment, DS is DOS's, SS is ours or DOS's, interrupts off.
  6563. ; 25 June 1987 [jrd]
  6564. SERDUM    PROC    FAR
  6565.     push    ds            ; preserve all registers
  6566.     push    ax
  6567.     mov    ax,seg data        ; get our data segment
  6568.     mov    ds,ax
  6569.     mov    al,flags.comflg        ; get port id (COM1 = 1, COM2 = 2)
  6570.     and    al,7            ; use lower three bits
  6571.     dec    al            ; DOS counts COM1 as 0, etc
  6572.     mov    dosctty,0        ; assume DOS not using our comms line
  6573.     cmp    dl,al        ; referencing same port as Kermit is using?
  6574.     pop    ax            ; recover request parameters
  6575.     jne    serdu1            ; ne = no, chain to Bios routine
  6576.     mov    dosctty,1        ; say DOS is using our comms line
  6577.     pop    ds
  6578.     cmp    ah,1            ; send char in al?
  6579.     jb    serdu3            ; b = no, init, return dummy status=ok
  6580.     ja    serdu2            ; a = no, other
  6581.     mov    ah,60h            ; yes, set line status=ok in ah
  6582.     iret
  6583. serdu2:    cmp    ah,2            ; receive char (and wait for it)?
  6584.     jne    serdu3            ; ne = no, return dummy report
  6585.     mov    al,BS            ; yes, return ascii BS to DOS
  6586.     xor    ah,ah            ; ah = errors (none here)
  6587.     iret
  6588. serdu3:    mov    ax,60b0h        ; dummy status report:xmtr empty, CD,
  6589.     iret                ;  DSR, and CTS are on
  6590.  
  6591. serdu1:    pop    tempdum            ; save old ds
  6592.     push    word ptr sav232+2    ; push Bios int 14H handler segment
  6593.     push    word ptr sav232        ; push Bios int 14H handler offset
  6594.     push    tempdum            ; recover old ds
  6595.     pop    ds
  6596.     ret                ; do a ret far (chain to Bios)
  6597. SERDUM    ENDP
  6598.  
  6599. ; Serial port interrupt routine.  This is not accessible outside this
  6600. ; module, handles serial port receiver interrupts.
  6601. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's.
  6602. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  6603. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  6604. ; done modulo size of Source. All pointer management is handled here.
  6605. ; Control-G char substituted for char(s) lost in overrun condition.
  6606. ; Upgraded to read cause of interrupt from interrupt ident reg (accepts only
  6607. ;  data ready), chain to old interrupt if source is not our device.
  6608. ; 9 Feb 1988 Add storage of interrupt cause in intkind. [jrd]
  6609. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  6610.  
  6611. SERINT  PROC  FAR
  6612.      push    ax            ; save registers
  6613.     push    dx            ; 
  6614.     push    ds
  6615.     mov    ax,seg data
  6616.     mov    ds,ax            ; address data segment
  6617.     mov    dx,miir            ; modem interrupt ident reg
  6618.     in    al,dx            ; get interrupt cause
  6619.     mov    intkind,al        ; save cause here
  6620.     test    al,1        ; interrupt available if this bit is zero
  6621.     jz    srintc            ; z = interrupt is from our source
  6622. ; temporary item to side step chaining for noisy buses and funny Bios'
  6623. ;    push    ds            ; preserve data seg addressibility
  6624. ;    pushf                ; call the old int handler
  6625. ;    call    dword ptr savsci    ;  via pseudo INT
  6626. ;    pop    ds            ; recover data seg
  6627.     and    intkind,not 4        ; say not-data-ready, to exit below
  6628. srintc:    mov    al,mdeoi        ; specific EOI
  6629.     mov    dx,mdintc        ; interrupt controller control word
  6630.     out    dx,al
  6631.     test    dl,80h            ; slave controller?
  6632.     jz    srintd            ; z = no
  6633.     mov    al,22h            ; specific EOI for IRQ 2 (cascade)
  6634.     out    20h,al            ; EOI the master 8259
  6635. srintd:    test    intkind,4        ; data ready?
  6636.     jnz    srint0a            ; nz = yes, else ignore
  6637. srint0:    sti                ; else turn on interrupts
  6638.     jmp    retint            ;  and exit now (common jump point)
  6639.  
  6640. srint0a:mov    dx,mst            ; asynch status    port
  6641.     in    al,dx
  6642. srint0b:cli                ; no interrupts permitted here
  6643.     and    al,mdmover        ; select overrun bit
  6644.     mov    ah,al            ; save it for later
  6645.     mov    dx,mdat
  6646.     in    al,dx            ; read the received character into al
  6647.     test    flowcnt,2        ; incoming XON/XOFF flow control?
  6648.     jz    srint2            ; z = no
  6649.     mov    dh,al               ; dh = working copy. Check flow cntl
  6650.     and    dh,parmsk        ; strip parity temporarily, if any
  6651.     cmp    dh,flowoff        ; acting on Xoff?
  6652.     jne    srint1            ; ne = no, go on
  6653.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  6654.     jne    srint4e            ; ne = yes, ignore (possible echo)
  6655.     mov    xofrcv,bufon        ; set the flag saying XOFF received
  6656.     jmp    short srint4e        ;  and continue the loop
  6657. srint1:    cmp    dh,flowon        ; acting on Xon?
  6658.     jne    srint2            ; ne = no, go on
  6659.     mov    xofrcv,off        ; clear the XOFF received flag
  6660.     jmp    short srint4e        ;  and continue the loop
  6661. srint2:    push    bx            ; save register
  6662.     or    ah,ah            ; overrun?
  6663.     jz    srint2a            ; z = no
  6664.     mov    ah,al            ; yes, save present char
  6665.     mov    al,bell            ; insert control-G for missing char 
  6666. srint2a:mov    bx,srcpnt        ; address of buffer storage slot
  6667.     mov    byte ptr [bx],al       ; store the new char in buffer "source"
  6668.     inc    srcpnt            ; point to next slot
  6669.     inc    bx
  6670.     cmp    bx,offset source + bufsiz ; beyond end of buffer?
  6671.     jb    srint3            ; b = not past end
  6672.     mov    srcpnt,offset source     ; wrap buffer around
  6673. srint3:    cmp    count,bufsiz        ; filled already?
  6674.     jae    srint4            ; ae = yes
  6675.     inc    count            ; no, add a char
  6676. srint4:    or    ah,ah            ; anything in overrun storage?
  6677.     jz    srint4a            ; z = no
  6678.     mov    al,ah            ; recover any recent char from overrun
  6679.     xor    ah,ah            ; clear overrun storage
  6680.     jmp    short srint2a        ; yes, go store real second char
  6681. srint4a:pop    bx            ; restore reg
  6682. srint4e:mov    dx,mst            ; uart line status register
  6683.     in    al,dx            ; get status
  6684.     test    al,1            ; data ready?
  6685.     jnz    srint0b            ; nz = yes, and preserve al
  6686.     sti                 ; ok to allow interrupts now, not before
  6687.     cmp    count,mntrgh        ; past the high trigger point?
  6688.     jbe    retint            ; be = no, we're within our limit
  6689.     test    xofsnt,bufon        ; has an XOFF been sent by buffer control?
  6690.     jnz    retint            ; nz = Yes
  6691.     test    flowcnt,4        ; using RTS/CTS flow control?
  6692.     jz    srint4b            ; z = no
  6693.     mov    dx,mst            ; modem status port (03fdh)
  6694.     dec    dx            ; modem control reg (03fch)
  6695.     in    al,dx
  6696.     and    al,not 2        ; reset RTS bit
  6697.     push    ax
  6698.     in    al,ppi_port        ; delay
  6699.     pop    ax
  6700.     out    dx,al            ; tell the UART to drop RTS
  6701.     mov    xofsnt,bufon           ; remember RTS reset at buffer level
  6702.     jmp    short retint
  6703.  
  6704. srint4b:test    flowcnt,1        ; send outgoing XON/XOFF?
  6705.     jz    retint            ; z = no
  6706.     mov    al,flowoff        ; get the flow off char (XOFF or null)
  6707. ;    or    al,al            ; do not send null chars
  6708. ;    jz    retint            ; z = null, nothing to send
  6709.     push    bx
  6710.     mov    bx,portval
  6711.     cmp    [bx].baud,Bsplit    ; doing 75/1200 baud stuff?
  6712.     pop    bx
  6713.     jne    srint4c            ; ne = no
  6714.     mov    quechar,al        ; put char in outchr queue for sending
  6715.     cmp    timeract,0        ; is timer being used at task level?
  6716.     jne    srint4d            ; ne = yes, just queue the char
  6717.     mov    ah,al            ; put char into ah
  6718.     call    foutchr            ; send the char now, non-blocking
  6719. srint4d:jmp    short retint
  6720.  
  6721. srint4c:call    fdopar            ; set parity appropriately
  6722.     mov    ah,al               ; don't overwrite character with status
  6723.     push    cx            ; save reg
  6724.     xor    cx,cx            ; loop counter
  6725. srint5:    mov    dx,mst            ; get port status
  6726.     in    al,dx
  6727.     test    al,20H            ; transmitter ready?
  6728.     jnz    srint6            ; nz = yes
  6729.     in    al,ppi_port        ; delay
  6730.     in    al,ppi_port        ; delay
  6731.     in    al,ppi_port        ; delay
  6732.     loop    srint5            ; else wait loop, cx times
  6733.     jmp    short srint7        ; timeout
  6734. srint6:    mov    al,ah            ; now send out the flow control char
  6735.     mov    dx,modem.mddat
  6736.     push    ax
  6737.     in    al,ppi_port        ; delay
  6738.     pop    ax
  6739.     out    dx,al
  6740.     mov    xofsnt,bufon       ; remember we sent an XOFF at buffer level
  6741. srint7:    pop    cx            ; restore reg
  6742. retint:    pop    ds
  6743.     pop    dx
  6744.     pop    ax
  6745.     iret
  6746. SERINT    ENDP
  6747.  
  6748. code1    ends
  6749.  
  6750. code    segment
  6751.     assume    cs:code
  6752.  
  6753. DTRLOW    PROC    NEAR        ; Global proc to Hangup the Phone or Network
  6754.                 ; by making DTR and RTS low (phone).
  6755.     mov    ah,cmword    ; allow text, to be able to display help
  6756.     mov    dx,offset rdbuf        ; dummy buffer
  6757.     mov    bx,offset hnghlp    ; help message
  6758.     call    comnd
  6759.     jc    dtrlow3            ; c = failure
  6760.     mov    ah,cmeol
  6761.     call    comnd            ; get a confirm
  6762.     jc    dtrlow3
  6763.     cmp    flags.comflg,'0'    ; Bios?
  6764.     jb    dtrlow1            ; b = no, UART
  6765.     cmp    flags.comflg,'4'    ; Bios?
  6766.     jbe    dtrlow2            ; be = yes, can't access modem lines
  6767. dtrlow1:call    serhng            ; drop DTR and RTS
  6768.     cmp    taklev,0        ; in a Take file or macro?
  6769.     jne    dtrlow2            ; ne = yes, no message
  6770.     mov    ah,prstr        ; give a nice message
  6771.     mov    dx,offset hngmsg
  6772.     int    dos
  6773. dtrlow2:clc                ; success
  6774. dtrlow3:ret
  6775. DTRLOW    ENDP
  6776.  
  6777. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  6778. ; to terminate the connection. 29 March 1986 [jrd]
  6779. ; 5 April 1987 Add 500 millisec wait with lines low before returning. [jrd]
  6780. ; Calling this twice without intervening calls to serini should be harmless.
  6781. ; If network then call session close procedure to hangup the session without
  6782. ; losing local name information; serrst does this.
  6783. ; Returns normally.
  6784.  
  6785. serhng    proc    near    ; clear modem's delta status bits and lower DTR & RTS
  6786.     cmp    apctrap,0        ; APC disable?
  6787.     je    shng1            ; e = no
  6788.     stc                ; fail
  6789.     ret
  6790. shng1:    call    serrst            ; reset port so can be opened again
  6791.     cmp    flags.comflg,4        ; UART port?
  6792.     jbe    shng2            ; be = yes
  6793.     push    bx
  6794.     mov    bx,portval
  6795.     call    [bx].cloproc        ; close the active network session
  6796.     pop    bx
  6797.     clc
  6798.     ret
  6799. shng2:    call    serini            ; energize, maybe for first time
  6800.     call    serrst            ; back to sleep
  6801.     cli                ; Disable interrupts
  6802.     push    ax
  6803.     push    dx
  6804.     mov    dx,modem.mddat        ; serial port base address
  6805.     add    dx,4            ; increment to control register
  6806.     mov    al,08h               ; reassert OUT2, un-assert DTR,RTS,OUT1
  6807.     out    dx,al
  6808.     in    al,ppi_port        ; delay
  6809.     add    dx,2            ; increment to modem status register
  6810.     in    al,dx            ; Clear Status reg by reading it
  6811.     sti                ; Enable interrupts
  6812.     mov    ax,1000            ; 1000 millisec, for pcwait
  6813.     call    pcwait            ; keep lines low for at least 500 millisec
  6814. ;    call    serini            ; energize port to set DTR high again
  6815. ;    call    serrst            ; leave port off for CTTY actions
  6816.     pop    dx
  6817.     pop    ax
  6818.     clc
  6819.     ret
  6820. serhng    endp
  6821.  
  6822.  
  6823. ; TCP/IP Telnet session manager.
  6824. ; Enter with SET PORT TCP/IP command line in buffer decbuf.
  6825. ; Syntax of that line is
  6826. ;   empty - resume current session, error return if none.
  6827. ;   digit - start or resume session digit, with digit being a local number.
  6828. ;   host  - ask if resume or new. If resume call ktcpswap, else tcpstart.
  6829. ;    *    - server mode
  6830. ; Returns sescur as index (0..maxsessions-1) for seslist action.
  6831. ; Successful return is carry clear, else carry set. 
  6832.  
  6833. sesmgr    proc    near
  6834.     push    bx
  6835.     mov    bx,sescur        ; current session
  6836.     call    termswapout        ; swap out current session's emulator
  6837.     pop    bx
  6838.     cmp    decbuf,1        ; byte count, anything given?
  6839.     jb    sesmgr24        ; b = no, use tcphost default
  6840.     ja    sesmgr40        ; ja = yes, but more than one char
  6841.     mov    bl,decbuf+1        ; get single char
  6842.     mov    al,bl
  6843.     and    al,not 20h        ; upper case, for letters only
  6844.     jmp    short sesmgr13
  6845.     
  6846. sesmgr10:cmp    sescur,-1        ; any session yet?
  6847.     je    sesmgr22        ; e = no, use command line
  6848.     call    sesdisp        ; display the table for guidance, inc help
  6849.     mov    dx,offset seshelp
  6850.     mov    ah,prstr
  6851.     int    dos
  6852.     mov    flags.cxzflg,0        ; clear Control-C flag
  6853.     mov    ax,0c0ah        ; clear buffer and read line
  6854.     mov    decbuf+100,80        ; length of our buffer
  6855.     mov    dx,offset decbuf+100    ; start of buffer (len, cnt, data)
  6856.     int    dos
  6857.     cmp    flags.cxzflg,'C'    ; Control-C entered?
  6858.     je    sesmgr28        ; e = yes, quit
  6859.     mov    al,decbuf+101        ; number of printables entered
  6860.     or    al,al            ; need at least one
  6861.     jz    sesmgr15        ; default is NEW
  6862.     mov    bl,decbuf+102        ; get first byte
  6863.     mov    al,bl
  6864.     and    al,not 20h        ; upper case, for letters only
  6865.  
  6866. sesmgr13:cmp    bl,'*'            ; "*" for server mode?
  6867.     je    sesmgr15        ; e = yes, use as host name
  6868.     cmp    al,'R'            ; RESUME current?
  6869.     jne    sesmgr14        ; ne = no
  6870.     clc                ; resume current session
  6871.     ret
  6872. sesmgr14:cmp    al,'N'            ; NEW?
  6873.     jne    sesmgr20        ; ne = no
  6874.  
  6875. sesmgr15:mov    cx,maxsessions        ; find an opening for NEW
  6876.     xor    bx,bx
  6877. sesmgr16:mov    al,seslist[bx]
  6878.     or    al,al            ; session in use?
  6879.     jns    sesmgr18        ; ns = yes
  6880.     mov    sescur,bx        ; set current session ident
  6881.     jmp    short sesmgr22        ; s = no
  6882. sesmgr18:inc    bx            ; next slot
  6883.     loop    sesmgr16
  6884.     mov    dx,offset sesnone    ; say no more sessions available
  6885.     mov    ah,prstr
  6886.     int    dos
  6887.     stc                ; fail out
  6888.     ret
  6889. sesmgr20:xor    bh,bh            ; ensure high byte is clear
  6890.     sub    bx,'1'            ; assume digit 1..6, remove bias
  6891.     cmp    bx,6            ; legal values are 0..5
  6892.     jae    sesmgr10        ; ae = out of range
  6893.     mov    sescur,bx        ; return slist index for action
  6894.     mov    al,bl
  6895.     mov    cx,seshostlen        ; length of a table entry
  6896.     mul    cl            ; skip to correct sesname
  6897.     cmp    decbuf,1        ; host name given on command line?
  6898.     ja    sesmgr22        ; a = yes, use it as host name
  6899.     add    ax,offset sesname    ; get host name from table
  6900.     mov    si,ax
  6901.     mov    di,offset tcphost    ; update active host name
  6902.     jmp    short sesmgr26        ; and switch terminal configuration
  6903.  
  6904. sesmgr22:mov    si,offset decbuf+1    ; name of new host
  6905.     cmp    byte ptr [si-1],0    ; byte count, anything given?
  6906.     je    sesmgr24        ; e = no, use tcphost default
  6907.     mov    di,offset tcphost
  6908.     call    strcpy            ; copy new host name
  6909.  
  6910. sesmgr24:mov    si,offset tcphost    ; host name
  6911.     cmp    byte ptr [si],0        ; is this empty too?
  6912.     je    sesmgr27        ; e = yes, no host name, fail
  6913.     cmp    sescur,0        ; inited current session ident?
  6914.     jge    sesmgr25        ; ge = yes
  6915.     mov    sescur,0        ; start with session 0
  6916. sesmgr25:mov    bx,sescur        ; return slist index for action
  6917.     mov    al,bl
  6918.     mov    cx,seshostlen        ; length of a table entry
  6919.     mul    cl            ; skip to correct sesname
  6920.     add    ax,offset sesname    ; destination table
  6921.     mov    di,ax
  6922. sesmgr26:call    strcpy
  6923.     push    bx
  6924.     mov    bx,sescur        ; new session
  6925.     call    termswapin        ; swap in new session's emulator
  6926.     pop    bx
  6927.     clc
  6928.     ret
  6929. sesmgr27:mov    dx,offset sesnohost    ; say have no host name 
  6930.     mov    ah,prstr
  6931.     int    dos
  6932. sesmgr28:stc
  6933.     ret
  6934.                     ; user specified host name
  6935.                     ; see if name is already in use
  6936. sesmgr40:mov    si,offset decbuf+1    ; user string
  6937.     mov    cl,[si-1]        ; user string length
  6938.     xor    ch,ch
  6939.     cld
  6940. sesmgr41:lodsb                ; read a byte
  6941.     call    tolowr            ; to lower case
  6942.     mov    [si-1],al        ; store letter
  6943.     loop    sesmgr41
  6944.     mov    cx,maxsessions
  6945.     xor    bx,bx            ; session subscript, assummed
  6946.     mov    si,offset decbuf    ; user len+string
  6947.     mov    di,offset sesname    ; session list of host names
  6948.     cld
  6949. sesmgr42:push    cx
  6950.     push    si
  6951.     push    di
  6952.     push    es
  6953.     mov    cl,[si]            ; length of user string
  6954.     xor    ch,ch
  6955.     inc    si            ; skip user string count byte
  6956.     inc    cl            ; include null termintors
  6957.     mov    ax,seg sesname
  6958.     mov    es,ax
  6959.     repe    cmpsb            ; compare host names
  6960.     pop    es
  6961.     pop    di
  6962.     pop    si
  6963.     pop    cx
  6964.     jne    sesmgr43        ; ne = no match, try next entry
  6965.     cmp    seslist[bx],0        ; is session active?
  6966.     jl    sesmgr43        ; l = no, ignore this entry
  6967.     jmp    sesmgr10        ; active, ask NEW/RESUME
  6968. sesmgr43:add    di,seshostlen        ; next entry in our table
  6969.     inc    bx            ; next session subscript
  6970.     loop    sesmgr42
  6971.     jmp    sesmgr15        ; start a New session
  6972. sesmgr    endp
  6973.  
  6974. sesdisp    proc    near
  6975.     mov    ah,prstr
  6976.     mov    dx,offset sesheader
  6977.     int    dos
  6978.     push    bx
  6979.     xor    bx,bx            ; number of sessions
  6980. sesdis1:mov    al,bl            ; get our local counter
  6981.     mov    dl,seshostlen        ; length of host name array row
  6982.     mul    dl
  6983.     add    ax,offset sesname    ; asciiz host name
  6984.     mov    si,ax            ; save host name pointer in cx
  6985.     cmp    byte ptr [si],0        ; ever had a host name?
  6986.     jz    sesdis3            ; z = no, don't display info
  6987.     mov    al,seslist[bx]        ; get Telnet session number
  6988.     mov    dx,offset sesinact    ; inactive msg
  6989.     or    al,al            ; seslist status
  6990.     js    sesdis2            ; s = inactive
  6991.     mov    dx,offset sesactive     ; active msg
  6992.     cmp    bx,sescur        ; same as current?
  6993.     jne    sesdis2            ; ne = no
  6994.     mov    dx,offset curmsg     ; current msg
  6995. sesdis2:mov    ah,prstr        ; show status, ses #, host name
  6996.     int    dos
  6997.     mov    dl,bl            ; count local session idents
  6998.     add    dl,'1'            ; bias
  6999.     mov    ah,conout
  7000.     int    dos
  7001.     mov    dl,' '
  7002.     int    dos
  7003.     int    dos
  7004.     int    dos
  7005.     int    dos
  7006.     int    dos
  7007.     int    dos
  7008.     int    dos
  7009.     mov    dx,si
  7010.     call    prtasz            ; show host name
  7011. sesdis3:inc    bx            ; next item
  7012.     cmp    bx,maxsessions        ; done all?
  7013.     jb    sesdis1            ; b = no
  7014.     pop    bx
  7015.     ret
  7016. sesdisp    endp
  7017.  
  7018. ; Returns session ident in BL when given a Telnet ident in AL. Also updates
  7019. ; tcphost from session table.
  7020. ; Returns -1 if no correspondence
  7021. tcptoses proc    near
  7022.     push    ax
  7023.     push    cx
  7024.     mov    cx,maxsessions        ; number session slots
  7025.     xor    bx,bx
  7026. tcptose1:mov    ah,seslist[bx]        ; session status
  7027.     or    ah,ah            ; active?
  7028.     js    tcptose2        ; s = no
  7029.     cmp    ah,al            ; same active session? 
  7030.     je    tcptose3        ; e = yes, return BL
  7031. tcptose2:inc    bx
  7032.     loop    tcptose1
  7033.     mov    bx,-1            ; return -1 for failure to find
  7034.     pop    cx
  7035.     pop    ax
  7036.     ret
  7037. tcptose3:
  7038.     push    si
  7039.     push    di
  7040.     mov    di,offset tcphost    ; host name
  7041.     mov    al,bl
  7042.     mov    cx,seshostlen        ; length of a table entry
  7043.     mul    cl            ; skip to correct sesname
  7044.     add    ax,offset sesname    ; source table
  7045.     mov    si,ax
  7046.     call    strcpy
  7047.     pop    di
  7048.     pop    si
  7049.     pop    cx
  7050.     pop    ax
  7051.     ret
  7052. tcptoses endp
  7053.  
  7054. ; Compute number of iterations needed in procedure pcwait inner loop
  7055. ; to do one millisecond delay increments. Uses Intel 8253/8254 timer chip
  7056. ; (timer #2) to measure elapsed time assuming 1.193182 MHz clock.
  7057. ; For IBM PC compatible machines.
  7058. pcwtst    proc    near
  7059.     push    cx
  7060.     mov    cx,10        ; number of tests to perform
  7061. pcwtst1:call    pcwtst2        ; do the test and new pcwcnt calculation
  7062.     loop    pcwtst1        ; repeat several times for convergence
  7063.     pop    cx
  7064.     ret
  7065.  
  7066. pcwtst2:push    ax
  7067.     push    bx
  7068.     push    cx
  7069.     push    dx
  7070.     in    al,ppi_port    ; 8255 chip port B, 61h
  7071.     and    al,0fch        ; speaker off (bit 1), stop timer (bit 0)
  7072.     out    ppi_port,al    ; do it
  7073.   ; 10 = timer 2, 11 = load low byte then high byte, 010 = mode 2, 0 = binary
  7074.     mov    al,10110100B    ; command byte
  7075.     out    timercmd,al    ; timer command port, 43h
  7076.     xor    al,al        ; clear initial count for count-down
  7077.     out    timer2data,al    ; low order byte of count preset, to port 42h
  7078.     out    timer2data,al    ; high order byte, to the same place
  7079.     in    al,ppi_port    ; get 8255 setting
  7080.     mov    dl,al        ; remember it in dl
  7081.     and    al,0fch        ; clear our control bits
  7082.     or    al,1           ; start counter now (Gate = 1, speaker is off)
  7083.     out    ppi_port,al    ; do it, OUT goes low
  7084.                 ; this is the test loop
  7085.     mov    ax,8        ; wait 8 millisec
  7086.     call    pcwait        ; call the software timer
  7087.                 ; end test loop
  7088.     mov    al,dl        ; restore ppi port, stop timer
  7089.     out    ppi_port,al
  7090.     in    al,timer2data    ; read count down value
  7091.     xchg    al,ah        ; save low order byte
  7092.     in    al,timer2data    ; get high order byte
  7093.     xchg    ah,al        ; put in correct sequence
  7094.     neg    ax        ; subtract from zero to get elapsed tics
  7095.     mov    bx,ax        ; save observed tics
  7096.     mov    ax,pcwcnt    ; current pcwcnt value
  7097.     ; new pcwcnt= old pcwcnt * [1193(tics/ms) / (observed tics / loops)]
  7098.     mov    cx,8*1193
  7099.     mul    cx    
  7100.     or    bx,bx        ; zero observed tics?
  7101.     jz    pcwtst3        ; z = yes, divide by one
  7102.     div    bx        ; divided by observed tics
  7103. pcwtst3:mov    pcwcnt,ax    ; store quotient as new inner loop counter
  7104.     pop    dx
  7105.     pop    cx
  7106.     pop    bx
  7107.     pop    ax
  7108.     ret
  7109. pcwtst    endp
  7110.     
  7111. ;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
  7112. ;; Thanks to Bernie Eiben for this one. Modified to use adjustable 
  7113. ; inner loop counter (pcwcnt, adjusted by proc pcwtst) by [jrd].
  7114. pcwait    proc    near
  7115.     push    cx
  7116. pcwai0:    mov    cx,pcwcnt    ; inner loop counter for 1 ms (240 @ 4.77 MHz)
  7117. pcwai1:    sub    cx,1        ; inner loop takes 20 clock cycles
  7118.     jnz    pcwai1
  7119.     dec    ax        ; outer loop counter
  7120.     jnz    pcwai0        ; wait another millisecond
  7121.     pop    cx
  7122.     ret
  7123. pcwait    endp
  7124. code    ends 
  7125.     end
  7126.