home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / mskermit / msxibm.asm < prev    next >
Assembly Source File  |  2020-01-01  |  260KB  |  8,223 lines

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