home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / msk316src.zip / MSXIBM.ASM < prev    next >
Assembly Source File  |  1999-04-24  |  266KB  |  8,426 lines

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