home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / extra / nyenhuis3.arc / MSXIBM.ASM < prev    next >
Assembly Source File  |  1990-01-16  |  135KB  |  3,933 lines

  1. ; File MSXIBM.ASM
  2. ; Kermit system dependent module for IBM-PC
  3.     include mssdef.h
  4. ; Edit History
  5. ; Last edit 16 Jan 1990
  6. ; 30 Sept 1989 Incorporate Opennet networking material from Fred Richter.
  7. ; 30 Sept 1989 Fred Richter (FGR) Intel Corp, Hauppauge NY
  8. ;  polyof!inthap!fred or fred@polyof.poly.edu
  9. ;  Added support for Intel Opennet Networking Virtual Terminal Services
  10. ;  added "set port opennet xxx", also modified (slightly)
  11. ;  the Netbios code (rpost) to always have the next Netbios receive posted
  12. ;  as a small efficiency gain. Added error checking for received Netbios
  13. ;  packets (there was none for async receives), also fix problem when the
  14. ;  receives are canceled, where the data was being accepted anyway.
  15. ; 3 Sept 1989 Add DECnet CTERM and LAT support, plus Novell Int 6Bh.
  16. ; 9 July 1989 Add automatic usage of National Semiconductor 16550A UART in
  17. ;  receiver fifo mode. Thanks to Dan Norstedt, danne@kicki.stacken.kth.se,
  18. ;  and Campbell Scientific, Logan Utah for urging and supporting information.
  19. ; 17 June 1989 Add transparent interrupt driven support for IBM's Extended
  20. ;  Bios via SET PORT BIOSn.
  21. ; 8 June 1989 Add Wyse-700 support from (Mikko Laanti (mjl).
  22. ; 6 March 1989 Add SET TERMINAL REPLAY FILESPEC command.
  23. ; 21 Jan 1989 Avoid initializing a port until the port is accessed for regular
  24. ;  use, baud rate setting, or modem status. portin=-1 means unaccessed.
  25. ; 2 Dec 1988 Preserve UART parity etc bits in Line Control Reg.
  26. ; 30 Nov 1988 Add SET TERM CLEAR screen clear command (uses byte VTCLEAR).
  27. ; 26 Nov 1988 Add SET TERM TAB SET/CLEAR AT start-col:spacing notation.
  28. ; 21 Nov 1988 Version 2.32
  29. ; 25 Oct 1988 Add Ungermann Bass network board status check in proc chkub,
  30. ;  thanks to Fritz Buetikofer and Rene Rehmann in Switzerland.
  31. ; 9 Oct 1988 Add byte vtemu.vtchset to hold choices for VT102 emulator
  32. ;  character sets (US, UK, or Alternate-ROM). Tnx to Baruch Cochavy. The value
  33. ;  of vtemu.vtchset must match definitions in emulator file mszibm.asm.
  34. ; 5 Oct 1988 Add SET TERMINAL DIRECTION command and status display line.
  35. ; 21 August 1988 Move tests for NUL and DEL received chars to prtchr routine
  36. ;  for uniform application of tests.
  37. ; 28 July 1988 Add more UB details from Henrik Levkowetz. Double check serial
  38. ;  port address for 02f8h with COM1, for PCjr, and shift to COM2 addresses.
  39. ; 16 July 1988 Use null interrupt routine, nulint, when resetting serial port
  40. ;  because setting OUT2 low generates stray ints on some UARTs. [jrd]
  41. ; 1 July 1988 Version 2.31
  42. ; 12 June 1988 Add small changes to handle network session failures, and
  43. ;  add carry set if serini fails to init port.
  44. ; 29 May 1988 Add Ungermann Bass NetOne NETCI support from Henrik Levkowetz
  45. ;  [ohl]. Revise same to test for actual network presence and to avoid
  46. ;  interference with NetBios operations. Use "SET PORT UB-Net1"
  47. ; 23 May 1988 Hangup now resets serial port so can be re-inited with DTR high
  48. ; 21 May 1988 Tweak serrst to allow stray interrupts while resetting UART,
  49. ;  clear outstanding network requests when changing ports.
  50. ; 6 May 1988 Introduce xmtbufx for explict network double buffering of
  51. ;   xmitted data.
  52. ; 28 April 1988 fix set port bios register problem.
  53. ; 18 April 1988 Network: do another READ when char count < low water mark.
  54. ;  If BIOSn is selected skip test of Bios 40:0h for port presence.
  55. ; 3 April 1988 Ignore NUL and DEL at serial port unless DEBUG or TRANSLATE
  56. ;  INPUT are active, but pass DEL if Tek mode is active. Replace netdone
  57. ;  with new lclexit global word to shut net when Kermit exits.
  58. ; 22 March 1988 Add global byte Tekgraf which forces graphics board type
  59. ;   0=auto-sensing, 1=cga, 2=ega, 3=VGA, 5=Hercules, 5=ATT. Tekgraf stored
  60. ;   and set in this file by Set Term Graphics <board type>. [jrd]
  61. ; 6 March 1988 Ignore received XOFF's if we have already sent one. [jrd]
  62. ; 27 Feb 1988 Add global routine getmodem to return modem status in al. [jrd]
  63. ; 9 Feb 1988 Automaticallly find Interrupt ReQuest level for a port.
  64. ;   No Modem Status for network. [jrd]
  65. ; 25 Jan 1988 Revise outchr waiting on XON to use 4 millisec increments. [jrd]
  66. ; 1 Jan 1988 version 2.30
  67. ; 24 Dec 1987 Revise selection of COM1 to use COM1 name but COM2 addresses
  68. ;  if base address of 02f8 (COM2) is found in 40:00h and display notice.
  69. ;  Restore state of IRQ interrupt line when finished with serial port. [jrd]
  70. ; 31 Oct 1987 Add terminal type Tek4010, with Tek submode Tekflg. [jrd]
  71. ; 24 Oct 1987 Enhance clrbuf to empty any intermediate (net) buffers. [jrd]
  72. ; 19 Oct 1987 Fix stray tab-set at column 32. [jrd]
  73. ; 2 Oct 1987 Add PCjr baud rate table, from Ted Medin. [jrd]
  74. ; 6 Sept 1987 Allow serial port serint to send xoff when buffer fills even
  75. ;  though user may have sent xoff by hand. [jrd]
  76. ; 27 Aug 1987 Skip timeout test in OUTCHR if receive timeout is zero. [jrd]
  77. ; 23 August 1987 Add vtemu.vtflgop to hold runtime terminal settings so that
  78. ;  a reset command restores them to the Setup values, vtemu.vtflgst. Show
  79. ;  displays the vtemu.vtflgop operational values. [jrd]
  80. ; 17 August 1987 Make timing adjustments for Token Passing and single buffered
  81. ;  network adapter boards. Byte netdbfr indicates presence of double buffering;
  82. ;  it is set in chknet as a vendor option. To test your boards force dbl buf
  83. ;  then look for missing 256 byte parts of long packets sent out; missing parts
  84. ;  mean new material overwrote not-yet-sent old == single buffering. [jrd]
  85. ; 8 August 1987 Add interrupt chaining in serint. [jrd]
  86. ; 23 July 1987 Clear xofsnt and xofrcv xon/xoff flags in ihost(s/r). [jrd]
  87. ; 9 July 1987 Cure confusion about COM1/2 for IBM PCjr (address of regular
  88. ;  COM2 in 40:0h slot for COM1) with info from John Neufeld. [jrd]
  89. ; 2 July 1987 Route NetBios cancels through separate scb for systems, such
  90. ;  as Novell NetWare, which object to having active scbs touched. [jrd]
  91. ; 25 June 1987 Add trapping of Int 14H (Bios RS232 procedure) to allow
  92. ;  CTTY command to function without too much inteference from DOS. [jrd]
  93. ; 17 June 1987 Enlarge tab setting to full 132 columns at all times. [jrd]
  94. ; 11 June 1987 Add Set Term Roll on/off to control auto roll back of screen
  95. ;  when new characters are displayed; default is off (no unwinding). [jrd]
  96. ; 20 May 1987 Remove rejection of NULL and DEL chars, let callers do it. [jrd]
  97. ; 16 May 1987 Add distinction between user typed and receiver threshold
  98. ;  controlled sending of XOFF. User level overrides buffer control.[jrd]
  99. ;  Add COM3 and COM4 support: examine memory 40:00h->40:07h for selected
  100. ;  port COM1..4, resp. If word is null then set flags.comflg to 0 to say
  101. ;  undefined port. Otherwise, use that word in seg 40h as base of UART i/o
  102. ;  ports. Assume IRQ4 for COM1 and COM3 (same except for port addresses)
  103. ;  and IRQ4 for  COM2 and COM4 (again, same except for port addresses).
  104. ;  Serial port info sturcture (not values) assumed identical for all ports.
  105. ; 25 April 1987 Add Netbios compatible local area network support. [jrd]
  106. ;  Set Port command expanded to syntax SET PORT NET nodename. Use nodename
  107. ;  if acting as a client to named remote node, leave blank if running in
  108. ;  Server mode. Byte 'ttyact' is controlled by msster.asm to indicate Connect
  109. ;  mode is being used. Byte 'netdone' (stored in mssker.asm) holds offset of
  110. ;  network hangup procedure 'netclose' to be done when leaving Kermit. Hangup
  111. ;  command extended to to network hangup as well. Network uses IBM Netbios
  112. ;  standard calls (Int 5Ch) and allows for extensions of AT&T STARLAN for
  113. ;  longer node names via Int 2Bh (the later is tested before use). Virtual
  114. ;  circuits are employed. The Redirector is not necessary. Kermit can operate
  115. ;  as either a terminal (does a CALL at Connect mode startup), a file receiver
  116. ;  (does a CALL at startup), or a Kermit server (does an anonomous LISTEN at
  117. ;  startup, hence no nodename). Clients should Set Timer Off.
  118. ; Note -
  119. ; When the Bios is used for serial port i/o the modem signals DSR and CTS
  120. ; must be asserted low before the Bios will access the hardware. Jumpers
  121. ; from pin 20 (DTR) to pin 6 (DSR) and from pin 4 (RTS) to pin 5 (CTS)
  122. ; will probably be necessary.
  123. ;       From Glenn Everhart (who suggested using the Bios alternative)
  124. ;
  125.     public    serini, serrst, clrbuf, outchr, coms
  126.     public    dodel, ctlu, cmblnk, locate, prtchr, baudst, clearl
  127.     public    getbaud, beep, shomodem, getmodem, mdmhand
  128.     public    count, xofsnt, puthlp, putmod, clrmod, poscur, holdscr
  129.     public    sendbr, sendbl, machnam, setktab, setkhlp, lclini, showkey
  130.     public    ihosts, ihostr, dtrlow, serhng, comptab, pcwait
  131.     public    portval, port1, port2, port3, port4, bdtab, ubhold
  132.     public    dupflg
  133.  
  134. off    equ    0
  135. bufon    equ    1        ; buffer level xon/xoff on-state control flag
  136. usron    equ    2        ; user level xon/xoff on-state control flag
  137.  
  138. mntrgh    equ    bufsiz*3/4    ; High point = 3/4 of buffer full
  139. mntrgl    equ    bufsiz/4    ; Low point = 1/4 buffer full
  140.  
  141. BRKBIT    EQU    040H        ; Send-break bit. 
  142. TIMERCMD EQU    43h        ; 8253/4 Timer chip command port
  143. TIMER2DATA EQU    42h        ; 8253/4 Timer 2 data port
  144. PPI_PORT EQU    61h        ; 8255 prog peripheral chip control port
  145. VIDEO    EQU    10H        ; Bios Video display software interrupt
  146. RS232    EQU    14H        ; Bios RS232 serial port s/ware interrupt
  147.  
  148. ; constants used by serial port handler
  149. ;;MDMDAT1    EQU    03F8H        ; Address of port com1 (data)
  150. ;;MDMCOM1    EQU    03FBH        ; Address of port com1 (command)
  151. ;;MDMSTS1    EQU    03FDH        ; Address of port com1 (status)
  152. ;;MDMDAT2    EQU    02F8H        ; Port com2 data
  153. ;;MDMCOM2    EQU    02FBH        ; Port com2 command
  154. ;;MDMSTS2    EQU    02FDH        ; Port com2 status
  155. MDMINTV    EQU    0CH        ; IRQ4 com1/3 port interrupt vector
  156. MDINTV2 EQU    0BH        ; IRQ3 com2/4 port interrupt vector
  157. MDMINTO    EQU    0EFH        ; Mask to enable interrupt level IRQ4
  158. MDINTO2 EQU    0F7H        ; Mask to enable interrupt level IRQ3
  159. MDMINTC    EQU    010H        ; Bit to set to disable interrupts for IRQ4
  160. MDINTC2 EQU    008H        ; Bit to set to disable interrupts for IRQ3
  161. EOICOM    EQU    0064H        ; End of interrupt for IRQ4
  162. EOICOM2    EQU    0063H        ; End of interrupt for IRQ3
  163.  
  164. INTCONT    EQU    0021H        ; Address of 8259 interrupt controller ICW2-3
  165. INTCON1    EQU    0020H        ; Address of 8259 ICW1
  166. MDMINP    EQU    1        ; Input ready bit
  167. MDMOVER    EQU    2        ; Receiver overrun
  168.  
  169. ; external variables used:
  170. ; flags - global flags as per flginfo structure defined in pcdefs
  171. ; trans - global transmission parameters, trinfo struct defined in pcdefs
  172. ; portval - pointer to current portinfo structure (currently either port1
  173. ;    or port2)
  174. ; port1, port2 - portinfo structures for the corresponding ports
  175. ; low_rgt - low byte = last column (typ 79), high byte = last text row
  176. ;  (typ 23) in screen coordinates (start at 0), set by msyibm.
  177.  
  178. ; global variables defined in this module:
  179. ; xofsnt, xofrcv - tell whether we saw or sent an xoff.
  180. ; setktab - keyword table for redefining keys (should contain a 0 if
  181. ;    not implemented)
  182. ; setkhlp - help for setktab.
  183.  
  184. data     segment    public 'data'
  185.     extrn    flags:byte, trans:byte, ttyact:byte, comand:byte
  186.     extrn    lclsusp:word, lclrest:word, lclexit:word, rxtable:byte
  187.     extrn    rdbuf:byte, taklev:byte, tekflg:byte, scbattr:byte
  188.     extrn    low_rgt:word, diskio:byte, crt_cols:byte, repflg:byte
  189.  
  190. ; Modem information
  191. mdminfo    struc
  192. mddat    dw    0        ; data register
  193. mdiir    dw    0        ; interrupt identification register
  194. mdstat    dw    0        ; line status register
  195. mdcom    dw    0
  196. mden    db    0
  197. mddis    db    0
  198. mdmeoi    db    0
  199. mdintv    dw    0
  200. mdminfo    ends
  201. modem    mdminfo <>
  202.  
  203. setktab    db    0        ; superceded by msuibm code, return 0 here
  204. setkhlp    db    '$'        ; and add empty help string
  205. holdscr    db    0        ; Hold-Screen, non-zero to stop reading
  206. savsci    dd    ?        ; old serial port interrupt vector
  207. sav232    dd    ?        ; Original Bios Int 14H address, in Code seg
  208. savirq    db    ?        ; Original Interrupt mask for IRQ
  209. savlcr    db    ?        ; Original Line Control Reg (3fbh) contents
  210. dupflg    db    0        ; full (0) or half (1) duplex on port
  211. brkval    db    BRKBIT        ; What to send for a break
  212. brkadr    dw    0        ; Where to send it
  213. intkind    db    0        ; cause of serial port interrupt
  214. isps2    db    0        ; non-zero if real IBM PS/2
  215. erms40    db    cr,lf,'?Warning: Unrecognized Speed',cr,lf,'$'
  216. badbd    db    cr,lf,'Unimplemented speed$'
  217. badprt    db    cr,lf,'?Warning: no hardware for this serial port$'
  218. biosmsg    db    cr,lf,'?This port will be operated through the Bios as BIOS$'
  219. msmsg1    db    cr,lf,'  Modem is not ready: DSR is off$'
  220. msmsg2    db    cr,lf,'  Modem is ready:     DSR is on$'
  221. msmsg3    db    cr,lf,'  no Carrier Detect:  CD  is off$'
  222. msmsg4    db    cr,lf,'  Carrier Detect:     CD  is on$'
  223. msmsg5    db    cr,lf,'  no Clear To Send:   CTS is off$'
  224. msmsg6    db    cr,lf,'  Clear To Send:      CTS is on$'
  225. msmsg7    db    cr,lf,'  Modem is not used by the Network$'
  226.  
  227. hngmsg    db    cr,lf,' The phone or network connection should have hung up'
  228.     db    cr,lf,'$'
  229. hnghlp    db    cr,lf,' The modem control lines DTR and RTS for the current'
  230.     db    ' port are forced low (off)'
  231.     db    cr,lf,' to hangup the phone. Normally, Kermit leaves them'
  232.     db    ' high (on) when it exits.',cr,lf
  233.     db    ' For networks, the active session is terminated.',cr,lf,'$'
  234.  
  235. machnam    db    'IBM-PC$'
  236. crlf    db    cr,lf,'$'
  237. delstr  db    BS,BS,'  ',BS,BS,'$'     ; Delete string
  238. clrlin  db    BS,BS,'  ',cr,'$'    ; Clear line (just the cr part)
  239. portin    db    -1        ; Has comm port been initialized, -1=not used
  240. xofsnt    db    0        ; Say if we sent an XOFF
  241. xofrcv    db    0        ; Say if we received an XOFF
  242. parmsk    db    0ffh        ; parity mask, 0ffh for no parity, 07fh with
  243. flowoff    db    0        ; flow-off char, Xoff or null (if no flow)
  244. flowon    db    0        ; flow-on char, Xon or null
  245. pcwcnt    dw    240        ; number of loops for 1 millisec in pcwait
  246. temp    dw    0
  247. temp2    dw    0
  248. tempsci dw    0        ; temp storage for serint
  249. tempdum    dw    0        ; temp storage for serdum
  250.  
  251. comptab    db    19            ; communications port options
  252.     mkeyw    'Bios1','0'+1        ; '0' is to flag value as forced Bios
  253.     mkeyw    'Bios2','0'+2
  254.     mkeyw    'Bios3','0'+3
  255.     mkeyw    'Bios4','0'+4
  256.     mkeyw    'COM1',1        ; these go straight to the hardware
  257.     mkeyw    'COM2',2
  258.     mkeyw    'COM3',3
  259.     mkeyw    'COM4',4
  260.     mkeyw    '1',1            ; straight to the hardware
  261.     mkeyw    '2',2
  262.     mkeyw    '3',3
  263.     mkeyw    '4',4
  264.     mkeyw    '3Com(BAPI)','C'    ; 3Com BAPI interface
  265.     mkeyw    'DECnet','D'        ; DECnet-DOS LAT and CTERM
  266.     mkeyw    'NetBios','N'        ; Netbios
  267.     mkeyw    'Novell(NASI)','W'    ; Novell NetWare NASI/NACS
  268.     mkeyw    'OpenNET','O'        ; Intel OpenNET support (FGR)
  269.     mkeyw    'UB-Net1','U'        ; Ungermann Bass Net One
  270.     mkeyw    '   ',0            ; port is not present, for Status
  271.  
  272. portmax    equ    4            ; number of predefined ports
  273.  
  274. port1    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  275. port2    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  276. port3     prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  277. port4    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  278.     rept    portmax-4
  279.     prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0>
  280.     endm
  281. portval    dw    port1            ; Default is to use port 1
  282.  
  283. bdtab    db    18            ; Baud rate table
  284.     mkeyw    '45.5',0
  285.     mkeyw    '50',1
  286.     mkeyw    '75',2
  287.     mkeyw    '110',3
  288.     mkeyw    '134.5',4
  289.     mkeyw    '150',5
  290.     mkeyw    '300',6
  291.     mkeyw    '600',7
  292.     mkeyw    '1200',8
  293.     mkeyw    '1800',9
  294.     mkeyw    '2000',10
  295.     mkeyw    '2400',11
  296.     mkeyw    '4800',12
  297.     mkeyw    '9600',13
  298.     mkeyw    '19200',14
  299.     mkeyw    '38400',15
  300.     mkeyw    '57600',16
  301.     mkeyw    '115200',17
  302.  
  303.  
  304. ; this table is indexed by the baud rate definitions given in bdtab.
  305. ; Unsupported baud rates should contain 0FFh.
  306.  
  307. bddat    label    word
  308.     dw    9E4H        ; 45.5 baud
  309.     dw    900H        ; 50 baud
  310.     dw    600H        ; 75 baud
  311.     dw    417H        ; 110 baud
  312.     dw    359H        ; 134.5 baud
  313.     dw    300H        ; 150 baud
  314.     dw    180H        ; 300 baud
  315.     dw    0C0H        ; 600 baud
  316.     dw    60H        ; 1200 baud
  317.     dw    40H        ; 1800 baud
  318.     dw    3AH        ; 2000 baud
  319.     dw    30H        ; 2400 baud
  320.     dw    18H        ; 4800 baud
  321.     dw    0CH        ; 9600 baud
  322.     dw    06H        ; 19200 baud
  323.     dw    03H        ; 38400 baud
  324.     dw    02h        ; 57600 baud
  325.     dw    01h        ; 115200 baud
  326. baudlen    equ    ($-bddat)/2    ; number of entries above
  327.  
  328. jrbddat    label    word        ; Baud rate table for IBM PCjrs [tm]
  329.     dw    0FFH        ; 45.5 baud  -- Not supported
  330.     dw    8bfH        ; 50 baud
  331.     dw    5d3H        ; 75 baud
  332.     dw    3f9H        ; 110 baud
  333.     dw    340H        ; 134.5 baud
  334.     dw    2e9H        ; 150 baud
  335.     dw    175H        ; 300 baud
  336.     dw    0baH        ; 600 baud
  337.     dw    5dH        ; 1200 baud
  338.     dw    3eH        ; 1800 baud
  339.     dw    38H        ; 2000 baud
  340.     dw    2fH        ; 2400 baud
  341.     dw    18H        ; 4800 baud
  342.     dw    0CH        ; 9600 baud
  343.     dw    06H        ; 19200 baud
  344.     dw    03H        ; 38400 baud
  345.     dw    02h        ; 57600 baud
  346.     dw    01h        ; 115200 baud
  347.  
  348. ; this table is indexed by the baud rate definitions given in
  349. ; pcdefs.  Unsupported baud rates should contain FF.
  350. ; Bits are for Bios speed, no parity, 8 data bits. [jrd]
  351. clbddat   label   word
  352.         dw      0FFH            ; 45.5 baud  -- Not supported
  353.         dw      0FFH            ; 50 baud
  354.         dw      0FFH            ; 75 baud
  355.         dw      03H        ; 110 baud
  356.         dw      0FFH            ; 134.5 baud
  357.         dw      23H        ; 150 baud
  358.         dw      43H        ; 300 baud
  359.         dw      63H        ; 600 baud
  360.         dw      83H        ; 1200 baud
  361.         dw      0ffH        ; 1800 baud
  362.         dw      0FFH        ; 2000 baud
  363.         dw      0a3H        ; 2400 baud
  364.         dw      0c3H        ; 4800 baud
  365.         dw      0e3H        ; 9600 baud
  366.         dw      0FFH        ; 19200 baud
  367.         dw      0FFH        ; 38400 baud
  368.     dw    0FFH        ; 57600 baud
  369.     dw    0FFH        ; 115200 baud
  370. ; variables for serial interrupt handler
  371.  
  372. source    db    bufsiz+2 DUP(?)    ; Buffer for data from port (+ 2 guard bytes)
  373. srcpnt    dw    source        ; Pointer in buffer (DI)
  374. count    dw    0        ; Number of chars in int buffer
  375. mst    dw    0        ; Modem status address
  376. mdat    dw    0        ; Modem data address
  377. miir    dw    0        ; modem interrupt ident register
  378. mdeoi    db    0        ; End-of-Interrupt value
  379. mdmhand    db    0        ; Modem status register, current
  380.  
  381. ; Information structures for IBM Netbios compatible Local Area Networks
  382.                 ; network constants
  383. netint    equ    5ch        ; Netbios interrupt
  384. nadd    equ    30h        ; Add name
  385. ncall    equ    10h        ; CALL, open a virtual circuit session
  386. ncancel    equ    35h        ; Cancel command in scb buffer
  387. ndelete    equ    31h        ; Delete Name
  388. nhangup    equ    12h        ; Hangup virtual circuit session
  389. nlisten    equ    11h        ; Listen for session caller
  390. naustat    equ    33h        ; Network Adapter Unit, get status of
  391. nreceive equ    15h        ; Receive on virtual circuit
  392. nreset    equ    32h        ; Reset NAU and tables
  393. nsend    equ    14h        ; Send on virtual circuit
  394. nsestat    equ    34h        ; Session, get status of
  395. netbrk    equ    70h        ; STARLAN Int 5bh send Break
  396. nowait    equ    80h        ; no-wait, command modifier
  397. npending equ    0ffh        ; Pending request
  398. exnbios    equ    0400h        ; Int 2ah exec netbios call, error retry
  399. nbuflen    equ    256        ; bytes in each network buffer (two of them)
  400.                 ; DEC-LAT requires 259 (256 here + 3 extra)
  401. netbios    equ    8000h        ; network type bit, using NetBios
  402. starlan    equ    1        ; network type bit, AT&T STARLAN
  403. netone    equ    02h        ; [ohl] type bit, Ungermann-Bass Net/One
  404. ;xncall    equ    74h        ; [ohl] Net/One extended call function
  405. netci    equ    6Bh        ; [ohl] Net/One command interface interrupt,
  406.                 ; [ohl]  used for the following functions:
  407. nciwrit equ    0000h        ; [ohl] Net/One write function
  408. nciread equ    0100h        ; [ohl] Net/One read function
  409. ncistat equ    0700h        ; [ohl] Net/One status function
  410. ncicont equ    0600h        ; [ohl] Net/One control function
  411. ncibrk    equ    02h        ; [ohl] Net/One code for a break
  412. ncidis    equ    04h        ; [ohl] Net/One code for disconnect
  413. ncihld    equ    06h        ; [ohl] code for placing a connection on hold
  414. bapi    equ    10h        ; 3Com BAPI, nettype
  415. bapiint    equ    14h        ; 3Com BAPI, interrupt (Bios replacment)
  416. bapicon    equ    0a0h        ; 3Com BAPI, connect to port
  417. bapidisc equ    0a1h        ; 3Com BAPI, disconnect
  418. bapiwrit equ    0a4h        ; 3Com BAPI, write block
  419. bapiread equ    0a5h        ; 3Com BAPI, read block
  420. bapibrk    equ    0a6h        ; 3Com BAPI, send short break
  421. bapistat equ    0a7h        ; 3Com BAPI, read status (# chars to be read)
  422. bapihere equ    0afh        ; 3Com BAPI, presence check
  423. bapieecm equ    0b0h        ; 3Com BAPI, enable/disable ECM char
  424. bapiecm    equ    0b1h        ; 3Com BAPI, trap Enter Command Mode char
  425. ;; pcnet values:    0    no network available at all
  426. ;;            1    network board reports itself as present
  427. ;;            2    and session is in progress
  428. ;; extrn byte pcnet is  defined in msster.
  429.  
  430. portn    prtinfo    <0FFFH,0,defpar,1,0,defhand,floxon,0> ; port struc for PORTN
  431. scbst struc            ; Session (Network) Control Block [PCnet comp]
  432.     scb_cmd        db 0    ; command code for Netbios Int 5ch
  433.     scb_err        db 0    ; error return or request is pending
  434.     scb_vcid    db 0    ; virtual circuit ident number
  435.     scb_num        db 0    ; local name-number
  436.     scb_baddr    dw ?    ; buffer address, offset
  437.             dw data ;  and segment
  438.     scb_length    dw ?    ; length of buffer data
  439.     scb_rname    db '*               ' ; remote name, 16 chars space
  440.     scb_lname    db '                ' ; local name      filled 
  441.             db 0    ; reserved
  442.             db 0    ; reserved
  443.     scb_post    dw ?    ; interrupt driven post address, offset
  444.             dw code ;  and segment
  445.             db 0    ; LAN_num (adapter #), set to zero for STARLAN
  446.     scb_done    db 0    ; command complete status
  447.                 ; the 14 bytes below are normally 'reserved'
  448.                 ; STARLAN uses 5 for long/special call names
  449.                 ;  together with STARLAN specific Int 5bh
  450.     scb_vrname    dw 0,0    ; Variable length call name ptr offset,segment
  451.     scb_vrlen    db 0    ; length of vrname
  452.             db 9 dup (0)    ; reserved
  453. scbst    ends
  454.  
  455. rcv    scbst    <,,,,rcvbuf,,length rcvbuf,,,,,rpost>; declare scb for rcvr
  456. xmt    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,spost>;  for xmtr
  457. lsn    scbst    <,,,,xmtbuf,,length xmtbuf,,,,,lpost>;  for server listen
  458. can    scbst    <>                     ;  for cancels
  459.                     ; DECnet material
  460. decneth    dw    0            ; session handle
  461. decseg    dw    0            ; segment of SCB memory block
  462. decint    equ    69h            ; CTERM interrupt
  463. decnet    equ    4            ; for DECnet/CTERM nettype
  464. declat    equ    8            ; for LAT nettype
  465. dpresent equ    100h            ; Installation check for CTERM
  466. dsend    equ    101h            ; CTERM send byte
  467. dread    equ    102h            ; CTERM read byte
  468. dcstat    equ    103h            ; CTERM status
  469. ddstat    equ    104h            ; CTERM Decnet status
  470. dopen    equ    105h            ; CTERM open session
  471. dclose    equ    106h            ; CTERM close session
  472. dgetscb    equ    10ah            ; CTERM get SCB size
  473. latint    equ    6ah            ; LAT interrupt
  474. latsrv    equ    0d500h            ; LAT Get next service name
  475. latopen    equ    0d0ffh            ; LAT open
  476. latclose equ    0d000h            ; LAT close
  477. latsend equ    1            ; LAT send byte
  478. latread    equ    2            ; LAT read byte
  479. latstat    equ    3            ; LAT status
  480. latbreak equ    0d100h            ; LAT send a BREAK
  481. lcbst    struc                ; LAT control block structure
  482.     service    db    18 dup (0)    ; service
  483.         db    18 dup (0)    ; node, for future use
  484.         db    18 dup (0)    ; port, for future use
  485.     stopped    dd    0        ; session stopped post routine addr
  486.     overflow dd    0        ; service table overflow post addr
  487.     xnotify    dd    0        ; transmit post routine addr
  488.     rnotify    dd    0        ; receive post routine addr
  489.     sstatus    dw    0        ; session status
  490.         dw    0        ; slot state, LAT driver use
  491.         db    0        ; local credits, LAT driver use
  492.         dw    0        ; vcb offset, LAT driver use
  493.         dw    0        ; vcb segment, LAT driver use
  494.         dw    0        ; back slot, LAT driver use
  495.         dw    0        ; forward slot, LAT driver use
  496.         db    0        ; rem slot id, LAT driver use
  497.         db    0        ; loc slot id, LAT driver use
  498.         db    0        ; slot byte count, LAT driver use
  499.         db    0        ; remote credits, LAT driver use
  500.     xdata    db    255 dup (0)    ; transmitted data slot
  501.     slotqty    db    2        ; number receive data slots
  502.     slotused db    0        ; number occupied slots
  503.     slotnr    db    0        ; index of next rcv slot to use
  504.     slotcur    db    0        ; index of current rcv slot
  505.     slotptr dw    0        ; ptr to first received char
  506.         dw    0        ; ptrs to slots
  507.         dw    0
  508.     ; reuse NetBios buffers xmtbufx, rcvbuf for slot1, slot2, resp.
  509.     ; init these address in proc chkdec below.
  510. lcbst    ends
  511. lat    lcbst    <>            ; LAT data structure
  512. decmsg1    db    cr,lf,'Cannot create DECnet session.$'
  513. decmsg3    db    ' DECnet Error $'
  514. decmsg4    db    cr,lf,'DECnet CTERM session started.$'
  515. decmsg5    db    cr,lf,'DECnet LAT session started.$'
  516.                 ; end of DECnet
  517.  
  518. pcnet    db    0        ; Network is functioning
  519. xmtbuf    db    nbuflen dup (0) ; network buffer for transmitter
  520. xmtcnt    dw    0        ; occupancy in current output buffer
  521. xmtbufx    db    nbuflen+3 dup (0) ; external version of xmtbuf (dbl buffers)
  522. rcvbuf    db    nbuflen+3 dup (0) ; network buffer for receiver
  523. nambuf    db    65 dup (?)    ; network long name storage (STARLAN)
  524. sposted    db    0        ; send interlock, 0 if no send posted
  525. rposted    db    0        ; rcv interlock, 0 if no receive posted
  526. lposted    db    0        ; listen outstanding (if non-zero)
  527. netdbfr    db    0        ; non-zero if net board is double buffered
  528. deflname db    'mskermit.K      ' ; default local name, 16 bytes
  529. ivt1str    db    'iVT1',0    ; FGR - OpenNet VT handshake string
  530. inettyp    db    0        ; FGR - network type 'N' or 'O'
  531. nsbrk    dw    0        ; net can send Break
  532. nettype    dw    0        ; kind of local area net (vendor bit field)
  533. chkmsg1    db    cr,lf,' Cannot construct a local Kermit name, error = $'
  534. chkmsg2    db    cr,lf,lf,' Name $'
  535. chkmsg3    db    ' is already in use. Please enter another of'
  536.     db    cr,lf,' 1 - 14 letters or numbers (or nothing to quit): $'
  537. netmsg1    db    cr,lf,' Checking if our node name is unique ...$'
  538. netmsg2    db    cr,lf,' The network is active, our name is $'
  539. netmsg3 db    cr,lf,'  NetBios Local name: $'
  540. netmsg4    db    '  Remote host: $'
  541. netmsg5 db    cr,lf,'  DECnet host: $'
  542. nonetmsg db    cr,lf,'?The network is not available$'
  543. noname    db    cr,lf,'?No name exists for the remote host.$'
  544. nethlp    db    cr,lf,'  node name of remote system,'
  545.     db    cr,lf,'  or press ENTER to use current name,'
  546.     db    cr,lf,'  or press ENTER for server mode (NetBios only).$'
  547. dnethlp    db    cr,lf,'  node name of remote system,'
  548.     db    cr,lf,'  or press ENTER to use current name,'
  549.     db    cr,lf,'  or  *  to see a list of LAT service names.$'
  550. nethlp2    db    cr,lf,' Optional LAT password, if using a LAT connection$'
  551. dnetsrv    db    cr,lf,' Available LAT service names:',cr,lf,'$'
  552. ngodset    db    cr,lf,' Connecting to network node: $'
  553. nbadset    db    bell,cr,lf,' Cannot reach network node: $'
  554. recmsg    db    cr,lf,' Network receive failed, status = $'
  555. sndmsg    db    cr,lf,' Network send failed, status = $'
  556. naskpmt    db    cr,lf,' A network session is active.',cr,lf
  557.     db    ' Enter RESUME to resume it or NEW to start a new session:',0
  558. nettab    db    2
  559.     mkeyw    'New',0
  560.     mkeyw    'Resume',1
  561. biosbuf    db    20 dup (0)        ; IBM EBIOS receive buffer
  562. biosblen equ    $-biosbuf        ; its length
  563. data    ends
  564.  
  565. code    segment    public 'code'
  566.     extrn    comnd:near, prompt:near, dopar:near, lclyini:near, atsclr:near
  567.     extrn    strcpy:near, strlen:near,decout:near, prtasz:near, prtscr:near
  568.     extrn    kbsusp:near, kbrest:near        ; in msuibm.asm
  569.     assume    cs:code, ds:data, es:nothing
  570.  
  571. ; local initialization
  572.  
  573. lclini    proc    near
  574.     mov    flags.comflg,1    ; assume COM1 for communications port
  575. ;;;    call    coms2        ; setup serial port modem.info for COM1
  576.     call    model        ; get model of IBM machine
  577.     mov    lclsusp,offset suspend ; call this when suspending to DOS
  578.     mov    lclrest,offset restore ; call this when returning from DOS
  579.     mov    lclexit,offset finexit ; call this when exiting Kermit
  580.     call    lclyini        ; let other modules initialize too...
  581.     ret
  582. lclini    endp
  583.  
  584. ; Call these routines when suspending Kermit to go to DOS
  585. suspend    proc    near
  586.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  587.     call    ihosts        ; suspend the host
  588.     call    serrst
  589.     ret
  590. suspend    endp
  591.  
  592. ; Call these routines when returning to Kermit from DOS
  593. restore    proc    near
  594.     call    kbrest        ; DEC LK250 keyboard, set back to DEC mode
  595.     call    serini        ; reinit serial port
  596.     call    ihostr        ; resume the host
  597.     ret
  598. restore    endp
  599.  
  600. ; Call these routines when doing final exit of Kermit
  601. finexit    proc    near
  602.     call    netclose    ; close network connections
  603.     call    kbsusp        ; DEC LK250 keyboard, set back to DOS mode
  604.     call    serrst        ; reset serial port
  605.     ret
  606. finexit    endp
  607.  
  608. ; The IBM PC's. If jr then redo IBM baud rate with jr's values. [jrd]
  609. model    proc    near
  610.     mov    isps2,0            ; PS/2 present indicator
  611.     push    es
  612.     push    ax            ; get IBM model code at F000:FFFEh
  613.     mov    ax,0f000h        ; address ROM
  614.     mov    es,ax
  615.     mov    al,byte ptr es:[0fffeh]    ; get model id byte
  616.     cmp    al,0fdh            ; PC jr?
  617.     jne    modelx            ; ne = no
  618.     push    ds
  619.     pop    es            ; set es to data segment
  620.     mov    si,offset bddat        ; regular IBM baud rate table
  621.     mov    di,offset jrbddat    ; PCjr baud rate table
  622.     mov    cl,baudlen        ; number of words to copy
  623.     xor    ch,ch
  624.     cld
  625.     rep    movsw            ; copy PCjr values to IBM table
  626.     jmp    short modelx
  627.     mov    ah,0ch            ; AT and PS/2 configuration call
  628.     xor    al,al
  629.     int    15h            ; IBM Bios
  630.     jc    modelx            ; c = no information
  631.     cmp    word ptr es:[bx+2],040fch ; PS/2 model 50?
  632.     je    model3            ; e = yes
  633.     cmp    word ptr es:[bx+2],050fch ; PS/2 model 60?
  634.     je    model3            ; e = yes
  635.     cmp    byte ptr es:[bx+2],0f8h ; PS/2 model 80?
  636.     jne    modelx            ; ne = no
  637. model3:    mov    isps2,1            ; say real PS/2 for IRQ setting
  638. modelx:    pop    ax
  639.     pop    es
  640.     ret
  641. model    endp
  642.  
  643. ; show the definition of a key.  The terminal argument block (which contains
  644. ; the address and length of the definition tables) is passed in ax.
  645. ; Returns a string to print in AX, length of same in CX.
  646. ; Returns normally. Obsolete, name here for external reference only.
  647. showkey    proc    near
  648.     ret                ; return
  649. showkey    endp
  650.  
  651. ; SHOW MODEM, displays current status of lines DSR, CD, and CTS.
  652. ; Uses byte mdmhand, the modem line status register. [jrd]
  653. shomodem proc    near
  654.     mov    ah,cmeol        ; get a confirm
  655.     call    comnd
  656.     jc    shomd5            ; c = failure
  657.     mov    dx,offset msmsg7    ; no modem status for network
  658.     call    getmodem        ; get modem status
  659.     mov    mdmhand,al
  660.     mov    ah,prstr
  661.     mov    dx,offset msmsg1    ; modem ready msg
  662.     test    mdmhand,20h        ; is DSR asserted?
  663.     jz    shomd1            ; z = no
  664.     mov    dx,offset msmsg2    ; say not asserted
  665. shomd1:    int    dos
  666.     mov    dx,offset msmsg3    ; CD asserted msg
  667.     test    mdmhand,80h        ; CD asserted?
  668.     jz    shomd2            ; z = no
  669.     mov    dx,offset msmsg4    ; say not asserted
  670. shomd2:    int    dos
  671.     mov    dx,offset msmsg5    ; CTS asserted msg
  672.     test    mdmhand,10h        ; CTS asserted?
  673.     jz    shomd3            ; z = no
  674.     mov    dx,offset msmsg6    ; say not asserted
  675. shomd3:    mov    ah,prstr
  676.     int    dos
  677.     cmp    rcv.scb_lname,' '    ; have NetBios name yet?
  678.     jbe    shomd4            ; be = no, skip this part
  679.     mov    dx,offset netmsg3    ; local name
  680.     int    dos
  681.     mov    cx,16
  682.     mov    di,offset rcv.scb_lname
  683.     call    prtscr
  684.     mov    ah,prstr
  685.     mov    dx,offset netmsg4    ; remote name
  686.     int    dos
  687.     mov    cx,16
  688.     mov    di,offset rcv.scb_rname
  689.     call    prtscr
  690. shomd4:    cmp    lat.service,0        ; DECnet name available?
  691.     je    shomd5            ; e = no
  692.     mov    ah,prstr
  693.     mov    dx,offset netmsg5
  694.     int    dos
  695.     mov    dx,offset lat.service    ; network host name, asciiz
  696.     call    prtasz
  697.     clc
  698. shomd5:    ret
  699. shomodem endp
  700.  
  701. ; Get modem status and set global byte mdmhand. Preserve all registers.
  702. getmodem proc    near            ; gets modem status upon request
  703.     cmp    portin,-1        ; done any port yet?
  704.     jne    getmod1            ; ne = yes
  705.     mov    bl,flags.comflg        ; pass current port ident
  706.     cmp    bl,'4'            ; above UART and Bios?
  707.     ja    getmod1            ; a = yes, do not start the port
  708.     call    comstrt            ; do SET PORT command now
  709.     jnc    getmod1            ; nc = success
  710.     ret                ; failed to set port
  711. getmod1:xor    al,al            ; assume nothing is on
  712.     cmp    flags.comflg,'1'    ; UART?
  713.     jae    getmod2            ; ae = no
  714.     cmp    flags.comflg,0        ; null port?
  715.     je    getmodx            ; e = yes, no status
  716.     mov    dx,mst            ; hardware
  717.     inc    dx            ; uart status reg
  718.     in    al,dx
  719.     jmp    short getmodx
  720. getmod2:cmp    flags.comflg,'4'    ; above Bios? (networks)
  721.     ja    getmodx            ; a = yes, no status
  722.     mov    ah,3            ; ask Bios for modem status into al
  723.     push    dx
  724.     mov    dl,flags.comflg        ; get port id
  725.     sub    dl,'1'            ; remove ascii bias (BIOS1 -> 0)
  726.     int    rs232
  727.     pop    dx
  728. getmodx:xor    ah,ah            ; return status in al
  729.     clc
  730.     ret
  731. getmodem endp
  732.  
  733. ; Clear the input buffer. This throws away all the characters in the
  734. ; serial interrupt buffer.  This is particularly important when
  735. ; talking to servers, since NAKs can accumulate in the buffer.
  736. ; Returns normally.
  737.  
  738. CLRBUF    PROC    NEAR
  739.     cli
  740.     mov    srcpnt,offset source    ; receive circular buffer
  741.     mov    count,0            ; receive circular buffer
  742.     sti
  743.     call    prtchr            ; empty any intermediate (net) buffers
  744.     cli
  745.     mov    srcpnt,offset source    ; receive circular buffer
  746.     mov    count,0            ; receive circular buffer
  747.     mov    xmtcnt,0        ; network output buffer count
  748.     sti
  749.     clc
  750.     cmp    flags.comflg,'0'    ; using Bios?
  751.     jb    clrbuf3            ; b = no
  752.     cmp    flags.comflg,'4'    ; using Bios?
  753.     ja    clrbuf3            ; a = no
  754.     call    chkbios            ; check for IBM EBIOS and set dl
  755.     jc    clrbuf3            ; c = not present
  756.     mov    ah,0f9h            ; do a Regain Control operation
  757.     int    rs232
  758. clrbuf1:mov    ax,0fd02h        ; see if buffer has chars already
  759.     int    rs232
  760.     jcxz    clrbuf2            ; z = no, ok to reset buffering
  761.     mov    ah,0fch            ; do receive /nowait to clear buff
  762.     int    rs232
  763.     jmp    short clrbuf1        ; repeat til empty
  764. clrbuf2:mov    bx,offset biosbuf    ; receive buffer for EBIOS
  765.     push    ds
  766.     pop    es            ; set es:bx to the buffer address
  767.     xor    cx,cx            ; set cx to zero to terminate buffering
  768.     mov    ax,0ff02h        ; reset buffered mode for receiving
  769.     int    rs232
  770. clrbuf3:ret
  771. CLRBUF    ENDP
  772.  
  773. ; Clear to the end of the current line.  Returns normally.
  774. ; Upgraded for Topview compatibility.
  775. CLEARL    PROC    NEAR
  776.     push    ax
  777.     push    bx
  778.     push    dx
  779.     mov    ah,3            ; Clear to end of line
  780.     xor    bh,bh
  781.     int    video            ; Get current cursor position into dx
  782.     mov    ax,dx            ; Topview compatible clear line
  783.     mov    bh,ah            ; same row
  784.     mov    bl,byte ptr low_rgt    ; last column
  785.     call    atsclr            ; clear from ax to bx, screen coord
  786.     pop    dx
  787.     pop    bx
  788.     pop    ax
  789.     ret
  790. CLEARL    ENDP
  791.  
  792. ; This routine blanks the screen.  Returns normally.
  793. ; Upgraded to Topview compatiblity. [jrd]
  794. CMBLNK    PROC    NEAR
  795.     push    ax
  796.     push    bx
  797.     xor    ax,ax            ; from screen loc 0,0
  798.     mov    bx,low_rgt    ; to end of text screen (lower right corner)
  799.     inc    bh            ; include status line
  800.     call    atsclr             ; do Topview compatible clear, in msyibm
  801.     pop    bx
  802.     pop    ax
  803.     ret
  804. CMBLNK  ENDP
  805.  
  806. ; Locate: homes the cursor.  Returns normally.
  807.  
  808. LOCATE  PROC    NEAR
  809.     xor    dx,dx            ; Go to top left corner of screen
  810.     jmp poscur
  811. LOCATE  ENDP
  812.  
  813. ; Position the cursor according to contents of DX:
  814. ; DH contains row, DL contains column.  Returns normally.
  815. POSCUR    PROC    NEAR
  816.     push    ax
  817.     push    bx
  818.     mov    ah,2            ; Position cursor
  819.     xor    bh,bh            ; page 0
  820.     int    video
  821.     pop    bx
  822.     pop    ax
  823.     ret
  824. POSCUR    ENDP
  825.  
  826. ; Delete a character from the terminal.  This works by printing
  827. ; backspaces and spaces.  Returns normally.
  828.  
  829. DODEL    PROC    NEAR
  830.     mov    ah,prstr
  831.     mov    dx,offset delstr    ; Erase weird character
  832.     int    dos            
  833.     ret
  834. DODEL    ENDP
  835.  
  836. ; Move the cursor to the left margin, then clear to end of line.
  837. ; Returns normally.
  838.  
  839. CTLU    PROC    NEAR
  840.     mov    ah,prstr
  841.     mov    dx,offset clrlin
  842.     int    dos
  843.     jmp    clearl
  844. CTLU    ENDP
  845.  
  846.  
  847. BEEP    PROC    NEAR
  848.     push    ax
  849.     push    cx
  850.     mov    al,10110110B    ; Gen a short beep (long one losses data.)
  851.     out    timercmd,al    ; set Timer to to mode 3
  852.     mov    ax,1512        ; divisor, for frequency
  853.     out    timer2data,al    ; send low byte first
  854.     mov    al,ah
  855.     out    timer2data,al
  856.     in    al,ppi_port    ; get 8255 Port B setting
  857.     or    al,3        ; turn on speaker and timer
  858.     out    ppi_port,al    ; start speaker and timer
  859.     push    ax
  860.     mov    ax,40        ; 40 millisecond beep, calibrated time
  861.     call    pcwait
  862.     pop    ax
  863.     in    al,ppi_port
  864.     and    al,0fch        ; turn off speaker and timer
  865.     out    ppi_port,al
  866.     pop    cx
  867.     pop    ax
  868.     clc
  869.     ret
  870. BEEP    ENDP 
  871.  
  872. ; write a line in inverse video at the bottom of the screen...
  873. ; the line is passed in dx, terminated by a $.  Returns normally.
  874. putmod    proc    near
  875.     push    ax        ; save regs
  876.     push    bx
  877.     push    cx
  878.     push    si
  879.     push    dx        ; preserve message
  880.     mov    bl,scbattr    ; screen attributes at Kermit init time
  881.     and    bl,77h        ; get colors, omit bright and blink
  882.     rol    bl,1        ; interchange fore and background
  883.     rol    bl,1
  884.     rol    bl,1
  885.     rol    bl,1
  886.     xor    bh,bh        ; preset page 0
  887.     mov    temp,bx        ; temp = page 0, reverse video 
  888.     mov    dx,low_rgt    ; ending location is lower right corner
  889.     inc    dh        ;  of status line
  890.     mov    cx,dx        ; start is status left side
  891.     xor    cl,cl        ; left side
  892.     mov    ax,600h        ; scroll to clear the line
  893.     mov    bh,byte ptr temp ; set inverse video attributes
  894.     int    video
  895.     mov    dx,low_rgt    ; last text line
  896.     inc    dh        ; status line
  897.     xor    dl,dl        ; left side
  898.     call    poscur
  899.     pop    si        ; get message back
  900.     mov    cx,1        ; only one char at a time
  901.     xor    bh,bh        ; page 0
  902.     cld
  903. putmo1:    lodsb            ; get a byte
  904.     cmp    al,'$'        ; end of string?
  905.     je    putmo2
  906.     push    si        ; save si
  907.     push    ax        ; and the char
  908.     call    poscur
  909.     inc    dl        ; increment for next write
  910.     pop    ax        ; recover char
  911.     mov    ah,9        ; try this
  912.     mov    bx,temp        ; page 0, inverse video
  913.     int    video
  914.     pop    si        ; recover pointer
  915.     cmp    dl,crt_cols    ; beyond physical right border?
  916.     jb    putmo1        ; b = no
  917. putmo2:    pop    si
  918.     pop    cx
  919.     pop    bx
  920.     pop    ax
  921.     ret
  922. putmod    endp
  923.  
  924. ; clear the mode line written by putmod.  Returns normally.
  925. clrmod    proc    near
  926.     push    ax        ; save regs
  927.     push    bx
  928.     push    cx
  929.     push    dx
  930.     mov    ax,600h        ; do a scroll up
  931.     mov    dx,low_rgt    ; ending location is lower right corner
  932.     inc    dh        ;  of status line
  933.     mov    cx,dx        ; start is status left side
  934.     xor    cl,cl        ; left side
  935.     mov    bh,scbattr    ; use screen attributes at Kermit init time
  936.     int    video
  937.     pop    dx
  938.     pop    cx
  939.     pop    bx
  940.     pop    ax
  941.     ret
  942. clrmod    endp
  943.  
  944. ; put a help message on the screen.  This one uses reverse video...
  945. ; pass the message in ax, terminated by a null.  Returns normally.
  946. puthlp    proc    near
  947.     push    bx        ; save regs
  948.     push    cx
  949.     push    dx
  950.     push    si
  951.     push    ax        ; preserve this
  952.     cld
  953.     mov    bl,scbattr    ; screen attributes at Kermit init time
  954.     and    bl,77h        ; get colors, omit bright and blink
  955.     rol    bl,1        ; interchange fore and background
  956.     rol    bl,1
  957.     rol    bl,1
  958.     rol    bl,1
  959.     xor    bh,bh        ; preset page 0
  960.     mov    temp,bx        ; temp = page 0, reverse video 
  961.  
  962.     mov    si,ax        ; point to it
  963.     mov    dh,1        ; init counter
  964. puthl1:    lodsb            ; get a byte
  965.     cmp    al,lf        ; linefeed?
  966.     jne    puthl2        ; no, keep going
  967.     inc    dh        ; count it
  968.     jmp    puthl1        ; and keep looping
  969. puthl2:    or    al,al        ; end of string?
  970.     jnz    puthl1        ; nz = no, keep going
  971.     mov    ax,600h        ; scroll to clear window
  972.     xor    cx,cx        ; from top left
  973.     mov    dl,4fh        ; to bottom right of needed piece
  974.     mov    bh,70h        ; inverse video
  975.     mov    bh,bl        ; inverse video
  976.     int    video
  977.     call    locate        ; home cursor
  978.     mov    bx,0070h    ; bh = page 0, bl = inverse video
  979.     mov    bx,temp
  980.     mov    cx,1        ; one char at a time
  981.     cld            ; scan direction is forward
  982.     pop    si        ; point to string again
  983. puthl3:    lodsb            ; get a byte
  984.     or    al,al        ; end of string?
  985.     jz    puthl4        ; z = yes, stop
  986.     push    si        ; save around bios call
  987.     cmp    al,' '        ; printable?
  988.     jb    puth21        ; b = no
  989.     mov    ah,9        ; write char at current cursor position
  990.     int    video        ; do the Bios int 10h call
  991.     inc    dl        ; point to next column
  992.     jmp    puth23        ; move cursor there
  993. puth21:    cmp    al,cr        ; carriage return?
  994.     jne    puth22        ; ne = no
  995.     xor    dl,dl        ; set to column zero
  996.     jmp    puth23
  997. puth22:    cmp    al,lf        ; line feed?
  998.     jne    puth23
  999.     inc    dh        ; go to next line
  1000. puth23:    mov    ah,2        ; set cursor position to dx
  1001.     int    video
  1002.     pop    si        ; restore pointer
  1003.     jmp    puthl3        ; and keep going
  1004. puthl4:    mov    dh,byte ptr low_rgt+1    ; go to last line
  1005.     inc    dh
  1006.     xor    dl,dl
  1007.     call    poscur        ; position cursor
  1008.     pop    si
  1009.     pop    dx
  1010.     pop    cx
  1011.     pop    bx
  1012.     ret
  1013. puthlp    endp
  1014. ; Compute number of iterations needed in procedure pcwait inner loop
  1015. ; to do one millisecond delay increments. Uses Intel 8253/8254 timer chip
  1016. ; (timer #2) to measure elapsed time assuming 1.193182 MHz clock.
  1017. ; Called by serini below. For IBM PC compatible machines.
  1018. ; Regs preserved. 16 April 87 [jrd]
  1019. pcwtst    proc    near
  1020.     push    ax
  1021.     push    cx
  1022.     push    dx
  1023.     mov    pcwcnt,256    ; software loop, initial value
  1024.     in    al,ppi_port    ; 8255 chip port B, 61h
  1025.     and    al,0fch        ; speaker off (bit 1), stop timer (bit 0)
  1026.     out    ppi_port,al    ; do it
  1027.   ; 10 = timer 2, 11 = load low byte then high byte, 010 = mode 2, 0 = binary
  1028.     mov    al,10110100B    ; command byte
  1029.     out    timercmd,al    ; timer command port, 43h
  1030.     xor    al,al        ; clear initial count for count-down
  1031.     out    timer2data,al    ; low order byte of count preset, to port 42h
  1032.     out    timer2data,al    ; high order byte, to the same place
  1033.     in    al,ppi_port    ; get 8255 setting
  1034.     mov    dl,al        ; remember it in dl
  1035.     and    al,0fch        ; clear our control bits
  1036.     or    al,1           ; start counter now (Gate = 1, speaker is off)
  1037.     out    ppi_port,al    ; do it, OUT goes low
  1038.                 ; this is the test loop
  1039.     mov    ax,8        ; wait 8 millisec
  1040.     call    pcwait        ; call the software timer
  1041.                 ; end test loop
  1042.     mov    al,dl        ; restore ppi port, stop timer
  1043.     out    ppi_port,al
  1044.     in    al,timer2data    ; read count down value
  1045.     xchg    al,ah        ; save low order byte
  1046.     in    al,timer2data    ; get high order byte
  1047.     xchg    ah,al        ; put in correct sequence
  1048.     neg    ax        ; subtract from zero to get elapsed tics
  1049.     xor    dx,dx        ; clear high order divisor
  1050.     add    ax,1193/2    ; round up
  1051.     adc    dx,0        ; for very very slow machines
  1052.     mov    cx,1193        ; tics per millisec
  1053.     div    cx        ; count / 1193 yields millisecs, quo=ax
  1054.     mov    cx,ax        ; retain whole number of milliseconds
  1055.     mov    ax,pcwcnt    ; get current pcwait inner loop count
  1056.     xor    dx,dx        ; clear high order field for division
  1057.     shl    ax,1
  1058.     rcl    dx,1
  1059.     shl    ax,1
  1060.     rcl    dx,1
  1061.     shl    ax,1
  1062.     rcl    dx,1        ; dx:ax = current counter times 8 loops
  1063.     jcxz    pcwtst1        ; z = no millisec (super speed machines) use 1
  1064.     div    cx        ; divide by observed milliseconds
  1065. pcwtst1:mov    pcwcnt,ax    ; store quotient as new inner loop counter
  1066.     pop    dx
  1067.     pop    cx
  1068.     pop    ax
  1069.     ret
  1070. pcwtst    endp
  1071.     
  1072. ;; Wait for the # of milliseconds in ax, for non-IBM compatibles.
  1073. ;; Thanks to Bernie Eiben for this one. Modified to use adjustable 
  1074. ; inner loop counter (pcwcnt, adjusted by proc pcwtst) by [jrd].
  1075. pcwait    proc    near
  1076.     push    cx
  1077. pcwai0:    mov    cx,pcwcnt    ; inner loop counter for 1 ms (240 @ 4.77 MHz)
  1078. pcwai1:    sub    cx,1        ; inner loop takes 20 clock cycles
  1079.     jnz    pcwai1
  1080.     dec    ax        ; outer loop counter
  1081.     jnz    pcwai0        ; wait another millisecond
  1082.     pop    cx
  1083.     ret
  1084. pcwait    endp
  1085.  
  1086. ; set the current port.  
  1087. ; Note: serial port addresses are found by looking in memory at 40:00h and
  1088. ; following three words for COM1..4, resp. All UARTS are assumed to follow
  1089. ; std IBM addresses relative to 03f8h for COM1, and actual address are offset
  1090. ; from value found in segment 40h. Global byte flags.comflg is 1,2,3,4 for
  1091. ; COM1..4, and is 'N' for NetBios.
  1092. ; 'O' is for Intel Opennet Network (FGR)
  1093. ; If address 02f8h is found in 40:00h then name COM1 is retained but COM2
  1094. ;  addressing is used to access the UART and a notice is displayed. IRQ 3
  1095. ; or IRQ 4 is sensed automatically for any COMx port.
  1096. COMS    PROC    NEAR
  1097.     mov    dx,offset comptab    ; table of legal comms ports
  1098.     xor    bx,bx            ; no extra help text
  1099.     mov    ah,cmkey        ; parse key word
  1100.     call    comnd
  1101.     jnc    coms0a            ; nc = success
  1102.     ret                ; failure
  1103. coms0a:    mov    temp,bx
  1104.     cmp    bl,'D'            ; DECnet?
  1105.     je    comstrt            ; e = yes
  1106.     cmp    bl,'N'            ; NetBios network?
  1107.     je    comstrt            ; yes, get another item for networks
  1108.      cmp    bl,'O'            ; Opennet network?
  1109.      je    comstrt            ; yes, get another item for networks
  1110.     cmp    bl,'U'            ; Ungermann Bass net?
  1111.     je    comstrt            ; e = yes
  1112.     cmp    bl,'W'            ; Novell NASI net?
  1113.     je    comstrt            ; e = yes
  1114.     mov    ah,cmeol        ; non-network
  1115.     call    comnd            ; Get a confirm
  1116.     jnc    coms0b            ; nc = success
  1117.     ret                ; failure
  1118. coms0b:    mov    bx,temp
  1119.  
  1120. COMSTRT:mov    temp,bx            ; port ident is in BL
  1121.     cmp    bl,'N'            ; NetBios network?
  1122.     jne    comst2a            ; ne = no
  1123.       jmp    comsn            ; yes, get another item for networks
  1124. comst2a:cmp    bl,'O'            ; Opennet network?
  1125.       jne    comst2                  ; ne = no
  1126.     jmp    comso            ; yes, get another item for networks
  1127. comst2:    cmp    bl,'U'            ; Ungermann Bass net?
  1128.     jne    comst3            ; ne = no
  1129.     jmp    comsub
  1130. comst3:    cmp    bl,'D'            ; DECnet?
  1131.     jne    comst4            ; ne = no
  1132.     jmp    comsd            ; do DECnet startup
  1133. comst4:    cmp    bl,'W'            ; Novell NASI?
  1134.     jne    comst5            ; ne = no
  1135.     jmp    comsub
  1136. comst5:    cmp    bl,'C'            ; 3Com BAPI?
  1137.     jne    comst5a            ; ne = no
  1138.     jmp    comsbapi
  1139. comst5a:cmp    flags.comflg,'N'    ; have been running on NetBios?
  1140.      je    coms1c            ; eq = yes
  1141.      cmp    flags.comflg,'O'    ; have been running on Opennet?
  1142.      jne    coms2            ; ne = no
  1143.                       ; turn off sources of net interrupts
  1144. coms1c:    mov    bx,offset can        ; cancel outstanding requests
  1145.     mov    can.scb_cmd,ncancel    ; set cancel op code
  1146.     cmp    lposted,1        ; listen outstanding?
  1147.     jne    coms1a            ; ne = no
  1148.     mov    can.scb_baddr,offset lsn ; cancel listen
  1149.     call    session
  1150.     mov    lposted,0
  1151. coms1a:    cmp    rposted,1        ; receive outstanding?
  1152.     mov    rposted,0        ; clear interlock flag no matter what
  1153.     jne    coms2            ; ne = no
  1154.     mov    can.scb_baddr,offset rcv ; cancel receive
  1155.     call    session
  1156.     
  1157. coms2:    call    serrst            ; close current comms port
  1158.     mov    al,byte ptr temp    ; get COMx (1-4)
  1159.     mov    flags.comflg,al        ; remember port ident
  1160.     cmp    al,'1'            ; Bios?
  1161.     jb    coms2a            ; b = no, hardware
  1162.     sub    al,'0'            ; remove ascii bias for portinfo
  1163. coms2a:    dec    al
  1164.     xor    ah,ah            ; count ports from 0
  1165.     push    bx            ; set UART port addresses
  1166.     mov    bx,type prtinfo        ; size of each portinfo structure
  1167.     mul    bx            ; times port number
  1168.     add    ax,offset port1        ; plus start of COM1
  1169.     mov    portval,ax        ; points to our current port struct
  1170.     pop    bx            ; restore registers
  1171.     cmp    flags.comflg,'1'    ; Bios path?
  1172.     jb    coms4            ; b = no, check hardware
  1173.     clc
  1174.     ret
  1175.  
  1176. coms4:     cmp    portin,-1        ; serial port touched yet?
  1177.     jne    coms4a            ; ne = yes, else avoid init looping
  1178.     mov    portin,0        ; say serial port is being touched
  1179. coms4a:    push    bx            ; save register
  1180.     push    es
  1181.     mov    ax,40h        ; look at RS232_base [bx] in Bios area 40:00h
  1182.     mov    es,ax
  1183.     mov    bx,temp            ; get desired port
  1184.     xor    bh,bh
  1185.     dec    bl            ; count com1 as bl = 0, etc
  1186.     shl    bx,1            ; make bx a word index
  1187.     mov    ax,es:[bx]        ; get modem base address into ax
  1188.     pop    es
  1189.     pop    bx
  1190.     or    ax,ax            ; is address zero?
  1191.     je    comsnh            ; e = yes, no serial port hardware
  1192. comsc:                    ; hardware tests
  1193.     mov    modem.mddat,ax    ; set base address (also data address) 03f8h
  1194.     add    ax,2
  1195.     mov    modem.mdiir,ax        ; interrupt identification reg 03fah
  1196.     inc    ax            ; increment to command port 03fbh
  1197.     mov    modem.mdcom,ax        ; set line control register address
  1198.     mov    brkadr,ax        ; where to send break command
  1199.     add    ax,2            ; increment to status port 03fdh
  1200.     mov    modem.mdstat,ax        ; set line-status port address
  1201.     call    chkport            ; get type of UART support
  1202.     jc    comsnu            ; c = not a real 8250 class UART
  1203.     call    chkint            ; find IRQ for the port
  1204.     jc    comsnu            ; c = not found, an error condition
  1205.     ret                ; success
  1206.  
  1207. comsnh:    mov    ah,prstr        ; no port address for hardware
  1208.     mov    dx,offset badprt
  1209.     int    dos
  1210.                     ; no port address or no UART or no IRQ
  1211. comsnu:    mov     ah,prstr        ; tell user about Bios pathway
  1212.     mov    dx,offset biosmsg
  1213.     int    dos
  1214.     mov    dl,byte ptr temp    ; selected hardware port
  1215.     add    dl,'0'            ; map to Bios
  1216.     mov    flags.comflg,dl
  1217.     mov    ah,conout        ; say port number
  1218.     int    dos
  1219.     stc                ; say error
  1220.     ret
  1221.                                         ; Opennet Network support (FGR)
  1222. comso:    mov    inettyp,'O'        ; remember OpenNet type network
  1223.     jmp    comso2            ; do generic network code
  1224.                       ; NetBios Network support
  1225. comsn:    mov    inettyp,'N'        ; remember Netbios type network
  1226. comso2:    mov    ah,cmword        ; get a word (remote node name)
  1227.     mov    dx,offset rdbuf        ; work buffer
  1228.     mov    word ptr rdbuf,0    ; insert terminator
  1229.     mov    bx,offset nethlp    ; help message
  1230.     call    comnd            ; get the name, ignore errors
  1231.     xchg    ah,al            ; put byte count in al
  1232.     xor    ah,ah            ; clear junk
  1233.     mov    temp,ax            ; save number of chars entered
  1234.     mov    ah,cmeol
  1235.     call    comnd            ; get a confirm
  1236.     jc    comsn2            ; c = failure
  1237.     call    serrst            ; reset serial port
  1238.     cmp    temp,0            ; any name given?
  1239.     je    comsn1            ; e = no, use current name
  1240.     mov    si,offset rdbuf
  1241.     mov    di,offset nambuf    ; copy to here
  1242.     call    strcpy
  1243. comsn1:    call    chknet            ; start network usage
  1244.     cmp    pcnet,0            ; is network alive (non-zero)?
  1245.     jne    comsn4            ; ne = yes
  1246. comsn2:    stc
  1247.     ret                ; failure
  1248.  
  1249. comsn4:    mov    portval,offset portn     ; set Network port structure address
  1250.     mov    portn.portrdy,1        ; say the comms port is ready
  1251.     mov    al,inettyp        ; FGR - get saved network type
  1252.     mov    flags.comflg,al        ; Set the Netbios port flag
  1253.     call    chkport            ; set type of port support
  1254.     clc                ; return success
  1255.     ret                ; End NetBios
  1256.  
  1257.                     ; Ungermann-Bass terminal port [ohl +]
  1258. comsub:    push    bx            ; save net type U or W
  1259.     mov     ah,cmeol
  1260.         call    comnd                   ; get a confirm
  1261.     jc    comsub0            ; c = failure
  1262.     call    serrst            ; reset serial port
  1263.         call    chkub                   ; check UB network presence
  1264.     pop    bx            ; recover net type U or W
  1265.     jnc    comsub1            ; nc = present
  1266. comsub0:ret                ; return failure
  1267.  
  1268. comsub1:push    bx
  1269.     call    netclose        ; better close NetBios parts NOW!
  1270.     pop    bx
  1271.     mov     portval,offset portn ; set Network port data structure address
  1272.     mov    portn.portrdy,1        ; say the comms port is ready
  1273.         mov     flags.comflg,bl        ; set the comm port flag
  1274.     mov     pcnet,2                 ; network is present and active
  1275.         clc                ; return success
  1276.         ret                ; End Ungermann Bass/ Novell
  1277.  
  1278. comsd:                    ; DECnet
  1279.     mov    ah,cmword        ; get a word (remote node name)
  1280.     mov    dx,offset rdbuf        ; work buffer
  1281.     mov    word ptr rdbuf,0    ; insert terminator
  1282.     mov    bx,offset dnethlp    ; help message
  1283.     call    comnd            ; get the name
  1284.     xchg    ah,al            ; put byte count in al
  1285.     xor    ah,ah            ; clear junk
  1286.     mov    temp,ax            ; save number of chars entered
  1287.     mov    ah,cmword        ; get optional LAT service name
  1288.     mov    dx,offset rdbuf+80    ; work near end of this buffer
  1289.     mov    word ptr rdbuf+80,0    ; insert terminator
  1290.     mov    bx,offset nethlp2    ; help message
  1291.     mov    comand.cmblen,17    ; length of buffer (password = 16 chr)
  1292.     call    comnd            ; get the name, ignore if absent
  1293.     mov    ah,cmeol
  1294.     call    comnd            ; get a confirm
  1295.     jnc    comsd3
  1296.     ret                ; did not get a confirm
  1297. comsd3:    cmp    temp,0            ; any node name?
  1298.     je    comsd8a            ; e = no
  1299.     mov    si,offset rdbuf        ; the node name, make upper case
  1300.     add    si,temp            ; and add '::' if absent
  1301.     cmp    byte ptr [si],':'    ; ended on colon?
  1302.     jne    comsd4            ; ne = no, append them
  1303.     cmp    byte ptr [si-1],':'    ; first colon present?
  1304.     je    comsd5            ; e = yes
  1305.     dec    si            ; one colon, back up to it
  1306.     dec    temp
  1307. comsd4:    mov    word ptr [si+1],'::'
  1308.     mov    byte ptr [si+3],0    ; terminator
  1309.     add    temp,2            ; include new bytes
  1310. comsd5:    mov    si,offset rdbuf        ; match spelling of old and new nodes
  1311.     mov    di,offset lat.service
  1312.     mov    cx,temp
  1313.     sub    cx,2            ; ignore trailing '::' here
  1314.     cld
  1315. comsd6:    lodsb                ; si = new node name
  1316.     mov    ah,[di]            ; di = old node name
  1317.     inc    di
  1318.     and    ax,not 2020h        ; move both to upper case
  1319.     xor    ah,al            ; compare bytes
  1320.     loope    comsd6            ; repeat while same spelling
  1321.     je    comsd8            ; e = same throughout
  1322.     mov    al,flags.comflg        ; save kind of port
  1323.     call    nethangup        ; different, clear current connection
  1324.     mov    si,offset rdbuf
  1325.     mov    di,offset lat.service    ; copy new name for use by chkdec
  1326.     call    strcpy
  1327. comsd8:    cmp    pcnet,2            ; session active?
  1328.     jb    comsd8a            ; b = no
  1329.     test    nettype,decnet+declat    ; and of DEC kind?
  1330.     jz    comsd8a
  1331.     call    chknew            ; session exists, Resume or start new?
  1332.     jc    comsd8a            ; c = resume
  1333.     cmp    rdbuf,0            ; New session?
  1334.     jne    comsd8a            ; ne = no, resume current
  1335.     call    nethangup        ; hangup current session
  1336. comsd8a:call    serrst            ; reset serial port (not used here)
  1337.     jmp    chkdec            ; make DECnet session with host
  1338.  
  1339. comsbapi:mov    ah,bapihere        ; 3Com BAPI presence check
  1340.     xor    al,al
  1341.     mov    bx,0aaaah        ; undocumented magic
  1342.     int    bapiint
  1343.     cmp    ax,0af01h        ; signature
  1344.     jne    comsbap1        ; ne = not present
  1345.     call    serrst            ; close current port
  1346.     mov    ah,bapieecm        ; disable Enter Command Mode char
  1347.     xor    al,al
  1348.     int    bapiint
  1349.     mov     portval,offset portn ; set Network port data structure address
  1350.     mov    portn.portrdy,1        ; say the comms port is ready
  1351.     mov    nettype,bapi        ; indentify network type
  1352.         mov     flags.comflg,'C'    ; set the comm port flag
  1353.     mov     pcnet,2                 ; network is present and active
  1354.     clc                ; success
  1355.     ret
  1356. comsbap1:mov    ah,prstr
  1357.     mov    dx,offset nonetmsg    ; say no network
  1358.     int    dos
  1359. comsbap3:stc                ; say failure
  1360.     ret                ; end 3Com BAPI
  1361. COMS    ENDP
  1362.  
  1363. ; SETUP DECNET port. Host name is in lat.service. Try LAT then try CTERM.
  1364. ; Return carry clear if success, or carry set if failure.
  1365. chkdec    proc    near
  1366.     cmp    pcnet,2            ; net active now?
  1367.     jb    chkde4            ; b = no
  1368.     test    nettype,declat        ; LAT support active?
  1369.     jz    chkde9            ; z = not LAT
  1370.     cmp    decneth,0        ; valid LAT handle?
  1371.     je    chkde4            ; e = invalid handle
  1372.     mov     portval,offset portn ; set Network port data structure address
  1373.         mov     flags.comflg,'D'    ; set the comm port flag
  1374.     mov    portn.portrdy,1        ; say the comms port is ready
  1375.     clc
  1376.     ret                ; return to active session
  1377.  
  1378. chkde9:    cmp    decneth,0        ; valid CTERM handle?
  1379.     jle    chkde4            ; le = none, start new session
  1380.     jmp    chkde6            ; resume old session
  1381.  
  1382. chkde4:    cmp    lat.service,0        ; node name present?
  1383.     jne    chkde4a            ; ne = yes
  1384.     mov    ah,prstr
  1385.     mov    dx,offset noname    ; say host name is required
  1386.     int    dos
  1387.     stc
  1388.     ret
  1389. chkde4a:xor    ax,ax            ; status of service not available
  1390.     mov    es,ax            ; refer to segment 0
  1391.     mov    si,latint*4        ; LAT 6Ah interrupt location
  1392.     les    si,es:[si]        ; get LAT driver entry point
  1393.     mov    ax,es
  1394.     cmp    ax,0            ; undefined interrupt?
  1395.     je    chkde4h            ; e = yes
  1396.     cmp    ax,0f000h        ; points at ROM Bios?
  1397.     je    chkde4h            ; e = yes
  1398.     cmp    word ptr es:[si-3],'AL'    ; preceeding 3 bytes spell 'LAT'?
  1399.     jne    chkde4h            ; ne = no, so no LAT, try CTERM
  1400.     cmp    byte ptr es:[si-1],'T'
  1401.     je    chkde4i            ; e = a match for LAT
  1402. chkde4h:jmp    chkde4e            ; no LAT, try CTERM
  1403. chkde4i:push    ds
  1404.     pop    es
  1405.     mov    bx,offset lat        ; LAT session control block
  1406.     mov    ax,offset xmtbufx    ; initialize receive slot pointers
  1407.     mov    [bx].slotptr+2,ax
  1408.     add    ax,4
  1409.     mov    [bx].slotptr,ax
  1410.     mov    ax,offset rcvbuf    ; use this as second buffer
  1411.     mov    [bx].slotptr+4,ax
  1412.     cmp    lat.service,'*'        ; just show known LAT names?
  1413.     jne    chkde4j            ; ne = no
  1414.     call    latlst            ; show LAT names
  1415.     stc                ; do not make a connection
  1416.     ret
  1417. chkde4j:mov    ax,latopen        ; open a LAT session
  1418.     mov    di,offset rdbuf+80    ; optional asciiz LAT password ptr
  1419.     cmp    byte ptr [di],0        ; any name entered?
  1420.     je    chkde4d            ; e = no
  1421.     mov    cx,16            ; 16 chars required, blank padded
  1422. chkde4b:cmp    byte ptr [di],0        ; found terminator?
  1423.     je    chkde4c            ; yes, proceed to pad with spaces
  1424.     inc    di            ; no, point to next character
  1425.     loop    chkde4b            ;  and loop
  1426.     jmp    short chkde4g        ; in case 16 byte password
  1427. chkde4c:mov    byte ptr [di],' '    ; insert padding
  1428.     inc    di            ; point to next
  1429.     loop    chkde4c            ;  and loop
  1430. chkde4g:mov    byte ptr [di],0        ; null terminator
  1431.     mov    di,offset rdbuf+80    ; point es:di to password field
  1432.     push    ds
  1433.     pop    es
  1434.     and    al,0fh            ; open as AX = 0d0fh if with password
  1435. chkde4d:mov    dh,0ffh
  1436.     int    latint
  1437.     or    ah,ah            ; status byte
  1438.     jnz    chkde4e            ; nz = failure, try CTERM
  1439.     mov    dh,0ffh            ; success
  1440.     mov    decneth,dx        ; store handle returned in dl
  1441.     or    nettype,declat        ; say LAT session is active
  1442.     mov    pcnet,2
  1443.     mov     portval,offset portn ; set Network port data structure address
  1444.         mov     flags.comflg,'D'    ; set the comm port flag
  1445.     mov    portn.portrdy,1        ; say the comms port is ready
  1446.     mov    ah,prstr
  1447.     mov    dx,offset decmsg5    ; show status
  1448.     int    dos
  1449.     clc                ; carry clear means status = success
  1450.     ret
  1451.  
  1452. chkde4e:xor    ax,ax            ; CTERM check
  1453.     mov    es,ax            ; refer to segment 0
  1454.     mov    si,decint*4        ; CTERM 69h interrupt location
  1455.     les    si,es:[si]        ; get CTERM driver entry point
  1456.     mov    ax,es
  1457.     cmp    ax,0            ; undefined interrupt?
  1458.     je    chkde4f            ; e = yes
  1459.     cmp    ax,0f000h        ; points at ROM Bios?
  1460.     je    chkde4f            ; e = yes
  1461.     mov    ax,dpresent        ; CTERM installation call
  1462.     int    decint
  1463.     cmp    al,0ffh            ; CTERM installed?
  1464.     je    chkde5            ; e = yes
  1465. chkde4f:mov    ah,prstr
  1466.     mov    dx,offset decmsg1    ; no CTERM yet
  1467.     int    dos
  1468.     jmp    chkde8            ; exit with no net
  1469. chkde5:    mov    ax,decseg        ; scb memory segment, if non-zero
  1470.     or    ax,ax            ; allocated already?
  1471.     jnz    chkde5a            ; nz = yes, segment is in ax
  1472.     mov    ax,dgetscb        ; get CTERM SCB size
  1473.     int    decint
  1474.     add    ax,15            ; round up byte count
  1475.     shr    ax,1            ; bytes to paragraphs
  1476.     shr    ax,1
  1477.     shr    ax,1
  1478.     shr    ax,1
  1479.     mov    bx,ax
  1480.     mov    temp,ax            ; save requested paragraphs
  1481.     mov    ah,alloc
  1482.     int    dos            ; bx gets # paragraphs allocated
  1483.     jc    chkde8            ; c = failure
  1484.     mov    decseg,ax        ; store address of memory block
  1485.     cmp    temp,bx            ; wanted vs allocated paragraphs
  1486.     jb    chkde7            ; b = not enough
  1487. chkde5a:mov    bx,offset lat.service    ; ds:bx = node name
  1488.     mov    es,ax
  1489.     xor    dx,dx            ; es:dx = SCB address
  1490.     mov    ax,dopen        ; open session
  1491.     int    decint
  1492.     cmp    ax,0            ; > 0 means session handle, else error
  1493.     jle    chkde7            ; le = error
  1494.     mov    decneth,ax        ; store handle
  1495.     mov    ah,prstr
  1496.     mov    dx,offset decmsg4    ; say CTERM connection is ready
  1497.     int    dos
  1498. chkde6:    or    nettype,decnet        ; network type is DECnet
  1499.     mov    pcnet,2            ; say net is present and active
  1500.     mov     portval,offset portn    ; set Network port structure address
  1501.         mov     flags.comflg,'D'    ; set the comm port flag
  1502.     mov    portn.portrdy,1        ; say the comms port is ready
  1503.     clc
  1504.     ret
  1505.                     ; CTERM startup failure
  1506. chkde7:    push    ax            ; save error number in ax
  1507.     mov    ax,decseg        ; allocated memory segment
  1508.     mov    es,ax
  1509.     mov    ah,freemem        ; free allocated memory at es:
  1510.     int    dos            ; free the block
  1511.     mov    decseg,0        ; clear remembered segment address
  1512.     mov    ah,prstr
  1513.     mov    dx,offset decmsg1    ; cannot create session
  1514.     int    dos
  1515.     mov    dx,offset decmsg3    ; DEC Error #
  1516.     int    dos
  1517.     pop    ax            ; recover error number (negative)
  1518.     neg    ax
  1519.     call    decout            ; error number
  1520. chkde8:    mov    pcnet,0            ; no net
  1521.     stc                ; status is error
  1522.     ret
  1523. chkdec    endp
  1524.  
  1525. ; Display list of LAT service names. Presumes LAT presence checks have passed
  1526. latlst    proc    near
  1527.     push    es
  1528.     push    bx
  1529.     mov    ah,prstr
  1530.     mov    dx,offset dnetsrv    ; header
  1531.     int    dos
  1532.     push    ds
  1533.     pop    es
  1534.     mov    si,2            ; chars in line counter
  1535. latlst1:mov    bx,offset rdbuf+2     ; es:bx = temp buffer for a name
  1536.     mov    word ptr [bx-2],'  '    ; indent
  1537.     mov    byte ptr [bx],0        ; and a null terminator
  1538.     mov    ax,latsrv        ; get next LAT service name
  1539.     mov    dh,0ffh
  1540.     int    latint
  1541.     or    ah,ah            ; check status
  1542.     jnz    latlst2            ; nz = done (no more names)
  1543.     mov    dx,offset rdbuf        ; name ptr is in es:bx (our buffer)
  1544.     call    prtasz            ; show asciiz name
  1545.     call    strlen            ; get current length
  1546.     add    si,cx            ; count chars on this line
  1547.     cmp    si,60            ; enough on line already?
  1548.     jbe    latlst1            ; be = no
  1549.     mov    ah,prstr        ; break the screen line
  1550.     mov    dx,offset crlf
  1551.     int    dos
  1552.     mov    si,2            ; reset line count
  1553.     jmp    short latlst1        ; do it again
  1554. latlst2:pop    bx
  1555.     pop    es
  1556.     ret
  1557. latlst    endp
  1558.  
  1559. ; Check which Interrupt ReQuest line the port uses. Technique: allow interrupt
  1560. ; on transmitter holding register empty, test for that condition first with
  1561. ; IRQ 4 and then IRQ 3. Returns with IRQ values set and carry clear if success
  1562. ; or carry set if failure. [jrd]
  1563. chkint    proc    near
  1564.     cmp    flags.comflg,2        ; COM1 or COM2?
  1565.     ja    chkin1            ; a = no
  1566.     jmp    chkin2            ; be = yes, use standard IRQ's
  1567. chkin1:    mov    modem.mddis,MDMINTC    ; IRQ 4 test. mask to disable IRQ 4
  1568.     mov    modem.mden,MDMINTO    ; mask to enable IRQ 4
  1569.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  1570.     mov    modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch) 
  1571.     mov    intkind,0        ; clear interrupt cause
  1572.     call    serini            ; setup port for IRQ 4
  1573.     jc    chkint2            ; c = failure
  1574.     mov    dx,modem.mddat
  1575.     inc    dx            ; interrupt enable reg (3f9h)
  1576.     cli
  1577.     mov    al,2            ; set xmtr holding reg empty interrupt
  1578.     out    dx,al
  1579.     jmp    $+2
  1580.     out    dx,al            ; again, because first may be missed
  1581.     sti
  1582.     mov    ax,1            ; wait one millisec for interrupt
  1583.     call    pcwait            ;  to occur
  1584.     test    intkind,2        ; check cause of interrupt, ours?
  1585.     jz    chkint2            ; z = no, try other IRQ
  1586.     call    serrst            ; reset port
  1587.     mov    modem.mdmeoi,EOICOM    ; use specific EOI for IRQ4 level
  1588.     clc                ; this setup worked
  1589.     ret
  1590.                     ; IRQ 3 test
  1591. chkint2:call    serrst            ; reset port
  1592.     mov    modem.mddis,MDINTC2    ; mask to disable IRQ 3
  1593.     mov    modem.mden,MDINTO2    ; mask to enable IRQ 3
  1594.     mov    modem.mdmeoi,20h    ; use general in case we guess wrong
  1595.     mov    modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1596.     mov    intkind,0        ; clear interrupt cause
  1597.     call    serini            ; setup port for IRQ 3
  1598.     jc    chkin2            ; c = failure
  1599.     mov    dx,modem.mddat
  1600.     inc    dx            ; interrupt enable reg (3f9h)
  1601.     cli
  1602.     mov    al,2            ; set xmtr holding reg empty interrupt
  1603.     out    dx,al
  1604.     jmp    $+2
  1605.     out    dx,al            ; again, because first may be missed
  1606.     sti
  1607.     mov    ax,1            ; wait one millisec for interrupt
  1608.     call    pcwait            ;  to occur
  1609.     test    intkind,2        ; check cause of interrupt, ours?
  1610.     jz    chkin2            ; z = no, so no interrupts for port
  1611.     call    serrst            ; reset port
  1612.     mov    modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1613.     clc                ; this setup worked
  1614.     ret
  1615.  
  1616. chkin2:    call    serrst            ; reset port, auto test did not work
  1617.     cmp    flags.comflg,1        ; COM1?
  1618.     je    chkin4            ; e = yes, use IRQ 4
  1619.     cmp    isps2,0            ; IBM PS/2 Model 50 or above?
  1620.     jne    chkin3            ; ne = yes, other COMs use IRQ 3
  1621.     cmp    flags.comflg,3        ; COM2, COM3, or COM4?
  1622.     je    chkin4            ; e = COM3, use IRQ 4
  1623.     jmp    short chkin3        ; else COM2 or COM4, use IRQ 3
  1624. chkin4:    cmp    modem.mddat,02f8h    ; really COM2 material for PCjr?
  1625.     je    chkin3            ; e = yes, use COM2 addresses
  1626.     mov    modem.mdmeoi,EOICOM    ; use specific EOI for IRQ4 level
  1627.     mov    modem.mddis,MDMINTC    ; IRQ 4 test. mask to disable IRQ 4
  1628.     mov    modem.mden,MDMINTO    ; mask to enable IRQ 4
  1629.     mov    modem.mdintv,MDMINTV    ; IRQ 4 interrupt vector (0ch)
  1630.     jmp    short chkin5
  1631. chkin3:    mov    modem.mdmeoi,EOICOM2    ; use specific EOI for IRQ 3 level
  1632.     mov    modem.mddis,MDINTC2    ; mask to disable IRQ 3
  1633.     mov    modem.mden,MDINTO2    ; mask to enable IRQ 3
  1634.     mov    modem.mdintv,MDINTV2    ; IRQ 3 interrupt vector
  1635. chkin5:    clc
  1636.     ret
  1637. chkint    endp
  1638.  
  1639. ; Test presently selected serial port for having a real 8250 UART.
  1640. ; Return carry clear if 8250 present,
  1641. ;  else carry set and flags.comflg in ascii digits for system Bios or
  1642. ;  carry set for network.
  1643. ; Method is to check UART's Interrupt Identification Register for high
  1644. ; five bits being zero; IBM does it this way. Assumes port structure
  1645. ; has been initialized with addresses of UART.    21 Feb 1987 [jrd]
  1646. ; 29 May 1987 Add double check by reading Line Status Register. [jrd]
  1647.  
  1648. chkport    proc    near
  1649.     cmp    flags.comflg,4        ; non-UART port?
  1650.     ja    chkporx            ; a = yes
  1651.     cmp    flags.comflg,0        ; undefined port?
  1652.     je    chkporx            ; e = yes
  1653.     push    ax
  1654.     push    dx
  1655.     mov    dx,modem.mdiir        ; UART Interrupt Ident reg (3FAh/2FAh)
  1656.     in    al,dx            ; read UART's IIR
  1657.     test    al,30h            ; are these bits set?
  1658.     jnz    chkpor1            ; nz = yes, not an 8250/16450/16550A
  1659.     mov    dx,modem.mdstat        ; line status register
  1660.     in    al,dx             ; read to clear UART BI, FE, PE, OE bits
  1661.     jmp    $+2            ; pause, for chip access timing
  1662.     in    al,dx            ; these bits should be cleared
  1663.     test    al,8eh            ; are they cleared?
  1664.     jnz    chkpor1            ; nz = no, not an 8250/16450/16550A
  1665.     pop    dx
  1666.     pop    ax
  1667.     clc                ; clear carry (say 8250/etc)
  1668.     ret
  1669. chkpor1:pop    dx
  1670.     pop    ax
  1671.     add    flags.comflg,'0'    ; set Bios usage flag (ascii digit)
  1672. chkporx:stc                ; set carry (say no 8250/etc)
  1673.     ret
  1674. chkport    endp
  1675.  
  1676. ; Check for presence of IBM EBIOS and set dl to Bios port value
  1677. ; Returns carry clear if EBIOS present, else carry set
  1678. chkbios    proc    near
  1679.     xor    dx,dx            ; assume port 1, find current port
  1680.     mov    dl,flags.comflg        ; get port number (1..4)
  1681.     or    dl,dl            ; zero (no such port)?
  1682.     jz    chkbios1        ; z = yes, don't access it
  1683.     and    dl,7            ; use low three bits
  1684.     dec    dl            ; address ports as 0..3 for Bios
  1685.     mov    ax,0f4ffh        ; IBM EBIOS presence check
  1686.     int    rs232
  1687.     jc    chkbios1        ; c = failure
  1688.     or    ax,ax            ; returns ax = 0 if present
  1689.     jnz    chkbios1        ; nz = not present
  1690.     clc
  1691.     ret
  1692. chkbios1:stc                ; IBM EBIOS not present, dl = port
  1693.     ret
  1694. chkbios    endp
  1695.  
  1696. ;;;;;;;;;;;;;;;;;;;;;; end of part one of msxibm.asm
  1697. ;;;;;;;;;;;;;;;;;;;;;; start part two of msxibm.asm
  1698.  
  1699. ; Set the baud rate for the current port, based on the value
  1700. ; in the portinfo structure.  Returns carry clear.
  1701.  
  1702. BAUDST    PROC    NEAR
  1703.     mov    dx,offset bdtab        ; baud rate table, ascii
  1704.     xor    bx,bx            ; help is the table itself
  1705.     mov    ah,cmkey        ; get keyword
  1706.     call    comnd
  1707.     jc    baudst1            ; c = failure
  1708.     push    bx            ; save result
  1709.     mov    ah,cmeol        ; get confirmation
  1710.     call    comnd
  1711.     pop    bx
  1712.     jc    baudst1            ; c = failure
  1713.     mov    si,portval
  1714.     mov    ax,[si].baud        ; remember original value
  1715.     mov    [si].baud,bx        ; set the baud rate
  1716.     call    dobaud            ; use common code
  1717.     clc
  1718. baudst1:ret
  1719. BAUDST    ENDP
  1720.  
  1721. DOBAUD    PROC    NEAR
  1722.     cmp    portin,-1        ; port used yet?
  1723.     jne    dobd3            ; ne = yes, go get rate
  1724.     mov    bl,flags.comflg        ; pass current port ident
  1725.     cmp    bl,4            ; upper limit on UARTs
  1726.     ja    dobd4            ; a = not a UART, no baud rate
  1727.     call    comstrt            ; do SET PORT command now
  1728.     jnc    dobd3            ; nc = success
  1729. dobd4:    stc
  1730.     ret                ; failure
  1731. dobd3:    push    ax            ; save some regs
  1732.     push    bx
  1733.     push    cx
  1734.     push    dx
  1735.     cmp    flags.comflg,'4'    ; UART or Bios?
  1736.     ja    dobd1            ; a = no, networks
  1737.     call    chkport            ; check port for real 8250 UART
  1738.     mov    bx,portval        ; pointer to port data structure
  1739.     mov    temp,ax            ; don't overwrite previous rate
  1740.     mov    ax,[bx].baud        ; check if new rate is valid
  1741.     shl    ax,1            ; make a word index
  1742.     mov    bx,offset bddat        ; start of table
  1743.     cmp    flags.comflg,'0'    ; Bios?
  1744.     jb    dobd0a            ; b = no, UART
  1745.     mov    bx,offset clbddat    ; use Bios speed parameters
  1746. dobd0a:    add    bx,ax
  1747.     mov    ax,[bx]            ; data to output to port
  1748.     cmp    ax,0FFH            ; Unimplemented baud rate
  1749.     jne    dobd0
  1750.     mov    ah,prstr
  1751.     mov    dx,offset badbd        ; give an error message
  1752.     int    dos
  1753.     jmp    dobd1
  1754.  
  1755. dobd0:    cmp    flags.comflg,'0'    ; running on a real uart?
  1756.     jb    dobd2            ; b = the real thing
  1757.     xor    dx,dx            ; assume port 1, find current port
  1758.     mov    dl,flags.comflg        ; get coms port (1..4)
  1759.     or    dl,dl            ; zero (undefined port)?
  1760.     jz    dobd1            ; z = yes, just exit
  1761.     and    dl,7            ; use lower three bits
  1762.     dec    dl            ; count ports as 0..3 for Bios
  1763.     xor    ah,ah            ; set serial port
  1764.     int    rs232            ; Bios: set the parameters
  1765.          jmp    dobd1            ; and exit
  1766.  
  1767. dobd2:    mov    temp,ax            ; UART, remember value to output
  1768.     mov    dx,modem.mdcom        ; LCR -- Initialize baud rate
  1769.     in    al,dx            ; get it
  1770.     mov    bl,al            ; make a copy
  1771.     or    ax,80H        ; turn on DLAB bit to access divisor part
  1772.     out    dx,al
  1773.     mov    dx,modem.mddat
  1774.     mov    ax,temp            ; set the baud rate divisor, low byte
  1775.     out    dx,al
  1776.     inc    dx            ; next address for high part
  1777.     mov    al,ah            ; set high part of divisor
  1778.     out    dx,al
  1779.     mov    dx,modem.mdcom        ; LCR again
  1780.     mov    al,bl            ; get original setting from bl
  1781.     out    dx,al            ; restore it
  1782. dobd1:    pop    dx            ; restore regs
  1783.     pop    cx
  1784.     pop    bx
  1785.     pop    ax
  1786.     clc
  1787.     ret
  1788. DOBAUD    ENDP
  1789.  
  1790. ; Get the current baud rate from the serial card and set it
  1791. ; in the portinfo structure for the current port.  Returns normally.
  1792. ; This is used during initialization.
  1793.  
  1794. GETBAUD    PROC    NEAR
  1795.     push    bx
  1796.     mov    bx,portval
  1797.     mov    [bx].baud,0ffh        ; set baud rate to unknown
  1798.     cmp    flags.comflg,4        ; UART?
  1799.     ja    getb3            ; a = no, Bios or Networks
  1800.     cmp    portin,-1        ; port unused?
  1801.     jne    getbud            ; ne = no, used, go get rate
  1802.     mov    bl,flags.comflg        ; pass current port ident
  1803.     call    comstrt            ; do SET PORT command now
  1804.     jnc    getbud            ; nc = success
  1805. getb3:    pop    bx
  1806.     ret                ; failure
  1807. getbud:    push    ax            ; save some regs
  1808.     push    cx
  1809.     push    dx
  1810.     mov    dx,modem.mdcom         ; get current Line Control Register value
  1811.     in    al,dx
  1812.     mov    bl,al            ; save it
  1813.     or    ax,80H              ; turn on to access baud rate generator
  1814.     out    dx,al
  1815.     mov    dx,modem.mddat        ; Divisor latch
  1816.     inc    dx
  1817.     in    al,dx            ; get high order byte
  1818.     mov    ah,al            ; save here
  1819.     dec    dx
  1820.     in    al,dx            ; get low order byte
  1821.     push    ax    
  1822.     mov    dx,modem.mdcom        ; Line Control Register
  1823.     mov    al,bl            ; restore old value
  1824.     out    dx,al
  1825.     pop    ax
  1826.     cmp    ax,0FFFFH        ; Who knows what this is
  1827.     je    getb2
  1828.     mov    bx,offset bddat        ; find rate's offset into table
  1829.     xor    cl,cl            ; keep track of index
  1830. getb0:    cmp    ax,[bx]
  1831.     je    getb1
  1832.     inc    cl
  1833.     cmp    cl,baudlen        ; at the end of the list?
  1834.     jge    getb2            ; ge = yes
  1835.     add    bx,2
  1836.     jmp    getb0
  1837. getb1:    xor    ch,ch
  1838.     mov    bx,portval
  1839.     mov    [bx].baud,cx        ; set baud rate
  1840. getb2:    pop    dx            ; restore regs
  1841.     pop    cx
  1842.     pop    ax
  1843.     pop    bx
  1844.     clc
  1845.     ret
  1846. GETBAUD    ENDP
  1847.  
  1848. ; Get Char from    serial port buffer.
  1849. ; returns carry set if no character available at port, otherwise
  1850. ; returns carry clear with char in al, # of chars in buffer in dx.
  1851. PRTCHR  PROC    NEAR
  1852.     cmp    holdscr,0        ; Holdscreen in effect?
  1853.     jne    prtch0a            ; ne = yes, do not read
  1854.     call    chkxon            ; see if we need to xon
  1855.     cmp    repflg,0        ; REPLAY?
  1856.     je    prtchn1            ; e = no
  1857.     jmp    prtch30            ; yes, do replay file reading
  1858. prtchn1:mov    al,flags.comflg        ; get kind of port
  1859.     cmp    al,'0'            ; Bios or network?
  1860.     jb    prtch0            ; b = no, UART
  1861.     cmp    al,'4'            ; Bios?
  1862.     jbe    prtch6            ; be = yes, else networks
  1863. prtchn:    cmp    count,bufsiz-nbuflen    ; room left for more network data?
  1864.     ja    prtch1            ; a = no, read current buffer
  1865.     cmp    al,'U'            ; UB network?
  1866.     je    prtchn2
  1867.     cmp    al,'C'            ; 3Com BAPI interface?
  1868.     je    prtchn2            ; e = yes
  1869.     cmp    al,'W'            ; Novell network?
  1870.     jne    prtchn3            ; ne = no
  1871. prtchn2:call    ubrecv                  ; do a UB receive
  1872.     jmp    short prtch0
  1873. prtchn3:cmp    al,'D'            ; DECnet?
  1874.     jne    prtchn4            ; ne = no
  1875.     jmp    decrcv            ; DECnet receive char
  1876. prtchn4:call    receive                 ; start next NetBios receive (async)
  1877. prtch0:    cmp    count,0            ; any characters available?
  1878.     jnz    prtch1            ; nz = yes, get one
  1879. prtch0a:xor    dx,dx            ; return count of zero
  1880.     stc                ; say no data
  1881.     ret
  1882. prtch1:    push    si            ; save si
  1883.     cli        ; interrupts off, to keep srcpnt & count consistent
  1884.     mov    si,srcpnt        ; address of next available slot in buffer
  1885.     sub    si,count        ; minus number of unread chars in buffer
  1886.     cmp    si,offset source    ; located before start of buf?
  1887.     jae    prtch2            ; ae = no
  1888.     add    si,bufsiz        ; else do arithmetic modulo bufsiz
  1889. prtch2:    mov    al,byte ptr [si]    ; get a character into al
  1890.     dec    count            ; one less unread char now
  1891.     sti                ; interrupts back on now
  1892.     pop    si
  1893.     mov    dx,count        ; return # of chars in buffer
  1894.     jmp    prtch12            ; screen delivered characters
  1895.  
  1896. prtch6:                    ; Bios calls
  1897.     call    chkbios            ; set dl to port check IBM EBIOS
  1898.     jc    prtch7            ; c = EBIOS not present
  1899.     mov    ah,0fch            ; IBM EBIOS receive /no wait
  1900.     int    rs232            ; does line check then char ready chk
  1901.     test    ah,8ch            ; timeout, framing error, parity error?
  1902.     jnz    prtch8            ; nz = error, no char
  1903.     jz    prtch9a            ; z = success, process char
  1904. prtch7:    mov    ah,3            ; check port status, std Bios calls
  1905.     int    rs232            ; Bios call
  1906.     test    ah,mdminp        ; data ready?
  1907.     jnz    prtch9            ; nz = yes, get one
  1908. prtch8:    xor    dx,dx            ; return count of zero
  1909.     stc                ; say no data
  1910.     ret
  1911. prtch9:    mov    ah,2            ; receive a char into al
  1912.     int    rs232            ; Bios call
  1913.     test    ah,8ch            ; timeout, framing error, parity error?
  1914.     jnz    prtch8            ; nz = error, no char
  1915.                     
  1916. prtch9a:                ; single char read final filter
  1917.     cmp    al,flowoff        ; acting on Xoff?
  1918.     jne    prtch10            ; ne = no, go on
  1919.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  1920.     jne    prtch8            ; ne = yes, ignore (possible echo)
  1921.     mov    xofrcv,bufon        ; set the flag saying XOFF received
  1922.     jmp    prtch8            ;  and exit
  1923. prtch10:cmp    al,flowon        ; acting on Xon?
  1924.     jne    prtch12            ; ne = no, go on
  1925.     mov    xofrcv,off        ; Clear the XOFF received flag
  1926.     jmp    short prtch8        ; no data to return
  1927. prtch12:test    flags.debug,logses    ; debug mode?
  1928.     jnz    prtch14            ; nz = yes, pass all chars
  1929.     cmp    rxtable+256,0        ; translation turned off?
  1930.     jne    prtch14            ; ne = table is on, pass all chars
  1931.     cmp    al,0            ; NUL?
  1932.     je    prtch13            ; e = yes, ignore it
  1933.     cmp    tekflg,0        ; Tek emulation active?
  1934.     jne    prtch14            ; ne = yes, pass DEL
  1935.     cmp    al,DEL            ; DEL char
  1936.     jne    prtch14            ; ne = no, pass char
  1937. prtch13:xor    dx,dx
  1938.     stc                ; no data
  1939.     ret
  1940. prtch14:clc                ; return char in al
  1941.     ret
  1942.  
  1943. prtch30:push    bx            ; REPLAY, read char from a file
  1944.     push    cx
  1945.     xor    dx,dx
  1946.     test    xofsnt,usron        ; user level xoff sent?
  1947.     jz    prtch32            ; z = no
  1948.     pop    cx            ; suppress reading here
  1949.     pop    bx
  1950.     clc                ; return with no char
  1951.     ret
  1952. prtch32:cmp    tekflg,0        ; doing Tek plots?
  1953.     jne    prtch32a        ; ne = yes, do not insert pauses
  1954.     mov    ax,100
  1955.     mov    bx,1
  1956.     jmp    $+2            ; flush lookahead buffer
  1957.     div    bx            ; burn some cpu cycles
  1958.     jmp    $+2            ; because a 1 ms wait is too long
  1959.     div    bx
  1960.     jmp    $+2
  1961.     div    bx
  1962. prtch32a:mov    ah,readf2
  1963.     mov    bx,diskio.handle    ; file handle
  1964.     mov    cx,1            ; read one char
  1965.     mov    dx,offset rdbuf        ; to this buffer
  1966.     int    dos
  1967.     jc    prtch31            ; c = read failure
  1968.     cmp    ax,cx            ; read the byte?
  1969.     jne    prtch31            ; ne = no
  1970.     pop    cx
  1971.     pop    bx
  1972.     mov    al,rdbuf        ; get the char into al
  1973.     mov    dx,1            ; external char count
  1974.     clc
  1975.     ret                ; return it
  1976. prtch31:call    beep
  1977.     mov    ax,40            ; wait 40 millisec
  1978.     call    pcwait
  1979.     call    beep
  1980.     mov    ah,coninq        ; wait for a keystroke
  1981.     int    dos
  1982.     or    al,al            ; null?
  1983.     jnz    prtch33            ; nz = no
  1984.     mov    ah,coninq
  1985.     int    dos
  1986. prtch33:pop    cx
  1987.     mov    bx,portval
  1988.     mov    [bx].portrdy,0        ; say port is not ready
  1989.     pop    bx
  1990.     xor    dx,dx
  1991.     stc                ; say no char
  1992.     ret
  1993. PRTCHR  ENDP
  1994.  
  1995. ; DECnet receive routine
  1996. DECRCV    PROC    NEAR
  1997.     mov    dx,decneth        ; DEC handle
  1998.     test    nettype,declat        ; LAT interface?
  1999.     jz    decrcv1            ; z = not LAT
  2000.     test    lat.sstatus,08h        ; status: stop slot received?
  2001.     jnz    decrcv4            ; nz = yes, no valid session
  2002.     mov    ah,latread        ; read char via LAT
  2003.     int    latint
  2004.     test    ah,80h            ; char available?
  2005.     jz    decrcv2            ; z = yes
  2006.     test    lat.sstatus,0ch        ; status: stop slot or circuit failure
  2007.     jnz    decrcv4            ; nz = yes, no valid session
  2008.     stc                ; return no char
  2009.     mov    count,0
  2010.     ret
  2011.  
  2012. decrcv1:mov    ax,dcstat        ; CTERM status
  2013.     int    decint
  2014.     test    ah,0c0h            ; no session, DECnet error?
  2015.     jnz    decrcv4            ; nz = yes, stop here
  2016. ;    test    ah,1            ; data available?
  2017. ;    jz    decrcv3            ; z = no
  2018. ; data available test fails under flow control, maybe a Cterm bug.  jrd
  2019.     mov    ax,dread        ; read char via CTERM
  2020.     int    decint
  2021.     test    ah,80h            ; char received?
  2022.     jnz    decrcv3            ; nz = no
  2023. decrcv2:jmp    prtch9a            ; use common completion code
  2024.  
  2025. decrcv3:stc                ; return no char
  2026.     mov    count,0
  2027.     ret
  2028.  
  2029. decrcv4:call    nethangup
  2030.     test    flags.remflg,dserver    ; server mode?
  2031.     jz    decrcv5            ; z = no
  2032.     call    serini            ; reinitialize it for new session
  2033. decrcv5:stc                ; say failure to receive
  2034.     ret
  2035. DECRCV    ENDP
  2036.  
  2037. ; NetBios Receive packet routine. If a new packet has been received unpack
  2038. ; the data and request a new one with no-wait option. If a receive request is
  2039. ; still outstanding just return with no new data.
  2040. ; Return carry clear if success. If failure, reset serial port (Server mode
  2041. ; reinits serial port) and return carry set. No entry setup needed.
  2042. RECEIVE PROC    NEAR            ; receive network session pkt
  2043.     cmp    pcnet,1            ; net ready yet?
  2044.     jbe    receiv3            ; be = no, declare a broken session
  2045.     cmp    rposted,1        ; is a request outstanding now?
  2046.     je    receiv4            ; e = yes (1), don't do another
  2047.     jb    receiv1            ; b = no (0), do one now
  2048.     call    receiv2            ; have new pkt, unpack, do new recv
  2049.     jnc    receiv1            ; nc = success
  2050.     ret                ; else return carry set
  2051.  
  2052. receiv1:mov    rposted,1        ; say posting a receive now
  2053.     mov    rcv.scb_length,nbuflen    ; length of input buffer  
  2054.     mov    rcv.scb_cmd,nreceive+nowait   ; receive, no wait
  2055.     push    bx
  2056.     mov    bx,offset rcv        ; setup pointer to scb
  2057.     call    session
  2058.     pop    bx
  2059.     ret                
  2060.  
  2061. receiv2:mov    al,rcv.scb_err        ; returned status
  2062.     or    al,al            ; success?
  2063.     jz    receiv5            ; z = yes, get the data
  2064.     cmp    al,npending        ; pending receive?
  2065.     je    receiv4            ; e = yes
  2066.     cmp    al,6            ; message incomplete?
  2067.     je    receiv5            ; e = yes, get what we have anyway
  2068.     cmp    al,0bh            ; receive cancelled?
  2069.     je    receiv4            ; e = yes
  2070.     cmp    al,18h            ; session ended abnormally?
  2071.     jbe    receiv3            ; e = yes, b = other normal errors
  2072.     mov    ah,prstr
  2073.     mov    dx,offset recmsg    ; give error message
  2074.     int    dos
  2075.     mov    al,rcv.scb_err        ; get error code
  2076.     call    hexout            ; show error code
  2077.  
  2078.                     ; Error return
  2079. receiv3:mov    pcnet,1            ; say session is broken
  2080.     mov    rposted,0
  2081.     call    serrst            ; reset serial port
  2082.     test    flags.remflg,dserver    ; server mode?
  2083.     jz    receiv3a        ; z = no
  2084.     call    serini            ; reinitialize it for new session
  2085. receiv3a:stc                ; say failure to receive
  2086.     ret
  2087. receiv4:clc                ; carry clear = success
  2088.     ret
  2089.         ; shared by NetBios, Novell, Opennet, Ungerman Bass, 3ComBAPI
  2090. receiv5:push    bx            ; new packet has been received
  2091.     push    cx            ; copy contents to circ buf source
  2092.     push    dx
  2093.     push    si
  2094.     mov    dh,flowon
  2095.     mov    dl,flowoff
  2096.     mov    si,rcv.scb_baddr    ; source of text (es:bx is scb ptr)
  2097.     mov    bx,srcpnt        ; address of destination buffer slot
  2098. receiv6:mov    cx,rcv.scb_length    ; get remaining returned byte count
  2099.     jcxz    receiv13        ; z = nothing there
  2100.     mov    ax,offset source+bufsiz ; end of destination buffer+1
  2101.     sub    ax,bx            ; space remaining at end of buffer
  2102.     jns    receiv7            ; should never be negative
  2103.     neg    ax            ; but if so invert
  2104. receiv7:cmp    ax,cx            ; buffer ending vs incoming byte count
  2105.     jge    receiv8            ; ge = enough for this pass
  2106.     mov    cx,ax            ; limit this pass to end of the buffer
  2107. receiv8:sub    rcv.scb_length,cx    ; deduct chars done in this pass
  2108.     add    count,cx        ; add them to the count
  2109.     cld                ; inner loop "block" transfer
  2110. receiv9:lodsb                ; get byte from rcvbuf to al
  2111.     or    dx,dx            ; doing flow control?
  2112.     jz    receiv11        ; z = no
  2113.     mov    ah,al            ; get copy of character
  2114.     and    ah,parmsk        ; strip parity, if any, before testing
  2115.     cmp    ah,dl            ; acting on Xoff?
  2116.     jne    receiv10        ; ne = no
  2117.     cmp    xofsnt,0        ; have we sent an XOFF?
  2118.     jne    receiv12        ; ne = yes, ignore this XOFF char
  2119.     mov    xofrcv,bufon        ; set flag saying buffer XOFF received
  2120.     jmp    short receiv12        ;  and skip this character
  2121. receiv10:cmp    ah,dh            ; acting on Xon?
  2122.     jne    receiv11        ; ne = no, go on
  2123.     mov    xofrcv,off        ; clear the XOFF received flag
  2124.     jmp    short receiv12        ;  and skip this character
  2125. receiv11:mov    [bx],al            ; store new char in buffer "source"
  2126.     inc    bx
  2127. receiv12:loop    receiv9            ; bottom of inner loop
  2128.                     ; update buffer pointer for wrapping
  2129.     cmp    bx,offset source+bufsiz    ; pointing beyond end of buffer?
  2130.     jb    receiv6            ; b = no, do next pass
  2131.     mov    bx,offset source    ; wrap pointer, modulo bufsiz
  2132.     jmp    short receiv6        ; do next pass
  2133.  
  2134. receiv13:mov    srcpnt,bx        ; update pointer to next free slot
  2135.     cmp    count,bufsiz        ; count more that buffer size?
  2136.     jbe    receiv14        ; be = no
  2137.     mov    count,bufsiz        ; limit to bufsiz (tells the truth)
  2138. receiv14:mov    rposted,0        ; clear interlock flag
  2139.     pop    si
  2140.     pop    dx
  2141.     pop    cx
  2142.     pop    bx
  2143.     clc
  2144.     ret
  2145. RECEIVE    ENDP
  2146.  
  2147. ; NetBios Receive post processing interrupt routine.
  2148. ; Sets rposted interlock flag
  2149. RPOST    PROC    NEAR        ; NetBios receive post interrupt routine
  2150.     push    ds
  2151.     push    ax
  2152.     mov    ax,data            ; reestablish data segment
  2153.     mov    ds,ax
  2154.     mov    rposted,2        ; set interlock flag to completed
  2155.     pop    ax
  2156.     pop    ds
  2157.     iret                ; return from interrupt
  2158. RPOST    endp    
  2159.  
  2160. ; Ungermann-Bass NETCI port receive characters routine.  Receive one or more
  2161. ; characters.  Calls the receiv5 routine to transfer character to main source
  2162. ; circular buffer.  Return carry clear if success. 
  2163. UBRECV    PROC    near
  2164.     push    bx
  2165.     push    cx
  2166.     push    es
  2167.     mov    ax, data
  2168.     mov    es, ax            ; es:bx will point to rcvbuf
  2169.     mov    bx, offset rcvbuf
  2170.     mov    cx, nbuflen        ; buffer length
  2171. ubrecv2:test    nettype,bapi        ; 3Com BAPI interface?
  2172.     jz    ubrecv2a        ; z = no, Int 6bh kind
  2173.     mov    ah,bapiread
  2174.     xor    dh,dh            ; session 0
  2175.     int    bapiint
  2176.     jmp    short ubrecv2b
  2177. ubrecv2a:mov    ax, nciread        ; function 1 (receive) port 0     [ohl]
  2178.     int    netci            ; get characters         [ohl]
  2179. ubrecv2b:stc
  2180.     jcxz    ubrec1            ; cx = z = nothing to do
  2181.     mov    rcv.scb_length, cx    ; prepare for rpost call     [ohl]
  2182.     call    receiv5            ; process buffer
  2183.     clc
  2184. ubrec1:    pop    es
  2185.     pop    cx
  2186.     pop    bx
  2187.     ret
  2188. UBRECV    ENDP
  2189.  
  2190. ; Put the char in AH to the serial port, assumimg the port is active.
  2191. ; Returns carry clear if success, else carry set.
  2192. ; 16 May 1987 Add entry point OUTCH2 for non-flow controlled sending to
  2193. ; prevent confusion of flow control logic at top of outchr; used by receiver
  2194. ; buffer high/low water mark flow control code. [jrd]
  2195. OUTCHR    PROC    NEAR
  2196.     cmp    flowoff,0        ; Are we doing flow control
  2197.     je    outch2            ; No, just continue
  2198.     cmp    ah,flowoff        ; sending xoff?
  2199.     jne    outch1            ; ne = no
  2200.     mov    xofsnt,usron        ; indicate user level xoff being sent
  2201.     jmp    outch1b
  2202. outch1:and    xofsnt,not usron    ; cancel user level xoff
  2203.     cmp    ah,flowon        ; user sending xon?
  2204.     jne    outch1b            ; ne = no
  2205.     mov    xofsnt,off         ; say an xon has been sent (cancels xoff)
  2206. outch1b:cmp    xofrcv,off        ; Are we being held (xoff received)?
  2207.     je    outch2            ; e = no - it's OK to go on
  2208.     push    cx            ; save reg
  2209.     mov    ch,15            ; 15 sec timeout interval
  2210.     xor    cl,cl            ;  convert to 4 millsec increments
  2211.  
  2212. outch1a:cmp    xofrcv,off        ; are we being held (xoff received)?
  2213.     je    outch1c            ; e = no - it's OK to go on
  2214.     push    ax
  2215.     mov    ax,4            ; 4 millisec wait loop
  2216.     call    pcwait
  2217.     pop    ax
  2218.     loop    outch1a            ; and try it again
  2219.     mov    xofrcv,off        ; timed out, force it off
  2220.     cmp    ttyact,0        ; in Connect mode?
  2221.     je    outch1c            ; e = no
  2222.     push    ax            ; save char around the call
  2223.     call    beep            ; let user know we are xoff-ed
  2224.     pop    ax            ;  but are sending anyway
  2225. outch1c:pop    cx            ; end of flow control section
  2226.              ; OUTCH2 is entry point for sending without flow control
  2227. OUTCH2:    mov    al,ah            ; Parity routine works on AL
  2228.     call    dopar            ; Set parity appropriately
  2229.     mov    ah,al            ; Don't overwrite character with status
  2230.     cmp    repflg,0        ; doing REPLAY from a file?
  2231.     je    outch3            ; e = no
  2232.     and    al,7fh            ; strip parity
  2233.     cmp    al,'C'-40h        ; Control-C? (to exit playback mode)
  2234.     je    outch2a            ; e = yes, return failure
  2235.     clc                ; return success, send nothing
  2236.     ret
  2237. outch2a:stc                ; return failure to exit playback mode
  2238.     ret
  2239. outch3:    cmp    flags.comflg,'0'    ; Bios?
  2240.     jb    outch3a            ; b = no, UART
  2241.     cmp    flags.comflg,'4'    ; Bios?
  2242.     jbe    outch3e            ; be = yes
  2243.     jmp    outch8            ; else try networks
  2244. outch3e:jmp    outch6            ; do Bios routine
  2245.  
  2246. outch3a:push    cx            ; save registers
  2247.     push    dx
  2248. outch3b:cmp    dupflg,0        ; full duplex?
  2249.     je    outch3d            ; e = yes
  2250.     mov    dx,modem.mddat
  2251.     add    dx,4            ; modem control reg 3fch
  2252.     in    al,dx
  2253.     or    al,2            ; set RTS
  2254.     jmp    $+2
  2255.     out    dx,al
  2256.     add    dx,2            ; modem status register 3feh
  2257.     jmp    $+2
  2258.     in    al,dx
  2259.     test    al,20h            ; ignore CTS if DSR is not asserted
  2260.     jz    outch3d            ; z = DSR not asserted
  2261.     mov    cx,8000            ; ~10 seconds worth of waiting on CTS
  2262. outch3c:test    al,10h            ; is CTS asserted?
  2263.     jnz    outch3d            ; nz = yes
  2264.     push    cx
  2265.     push    dx
  2266.     mov    ax,1            ; wait one millisec
  2267.     call    pcwait
  2268.     pop    dx
  2269.     pop    cx
  2270.     loop    outch3c            ; test again
  2271.     call    beep            ; half duplex timeout, make non-fatal
  2272.     pop    dx
  2273.     pop    cx
  2274.     clc
  2275.     ret
  2276.  
  2277. outch3d:xor    cx,cx
  2278.     mov    dx,modem.mdstat        ; get port status
  2279.     in    al,dx
  2280.     test    al,20H            ; Transmitter (THRE) ready?
  2281.     jnz    outch4            ; nz = yes
  2282.     jmp    $+2            ; use time, prevent overdriving UART
  2283.     jmp    $+2
  2284.     loop    outch3b
  2285.     jmp    outch5            ; Timeout
  2286. outch4:    mov    al,ah            ; Now send it out
  2287.     mov    dx,modem.mddat        ; use a little time
  2288.     jmp    $+2
  2289.     out    dx,al
  2290.     cmp    dupflg,0        ; full duplex?
  2291.     je    outch4a            ; e = yes
  2292.     cmp    al,trans.seol        ; End of Line char?
  2293.     jne    outch4a            ; ne = no
  2294.     xor    cx,cx            ; loop counter
  2295. outch4b:mov    dx,modem.mdstat        ; modem line status reg
  2296.     in    al,dx            ; read transmitter shift reg empty bit
  2297.     jmp    $+2
  2298.     jmp    $+2
  2299.     jmp    $+2            ; wait for char to be sent
  2300.     test    al,40h            ; is it empty?
  2301.     loopz    outch4b            ; z = no, not yet
  2302.     mov    dx,modem.mddat
  2303.     add    dx,4            ; modem control reg 3fch
  2304.     in    al,dx
  2305.     and    al,not 2        ; unassert RTS
  2306.     jmp    $+2
  2307.     out    dx,al
  2308. outch4a:pop    dx            ; exit success
  2309.     pop    cx
  2310.     clc
  2311.     ret
  2312. outch5:    call    beep
  2313.     pop    dx            ; exit failure
  2314.     pop    cx
  2315.     stc
  2316.     ret
  2317.                     ; finish up for Bios calls
  2318. outch6:    push    cx            ; find current port
  2319.     push    dx
  2320.     xor    dx,dx            ; assume port 1
  2321.     mov    dl,flags.comflg        ; get port number (1..4)
  2322.     or    dl,dl            ; zero (no such port)?
  2323.     jz    outch5            ; z = yes, don't access it
  2324.     and    dl,7            ; use lower three bits
  2325.     dec    dl            ; address ports as 0..3 for Bios
  2326.     mov    al,ah            ; now send it out
  2327.     mov    ah,1            ; send char
  2328.     int    rs232            ; bios send
  2329.     pop    dx             ; exit success
  2330.     pop    cx
  2331.     shl    ah,1            ; put status high bit into carry
  2332.     ret                ; c set = failure, else success
  2333.  
  2334. outch8:                ; Network sending, buffered and single char
  2335.     cmp    flags.comflg,'D'    ; DECnet?
  2336.     je    outch14            ; e = yes
  2337.     push    bx
  2338.     mov    bx,xmtcnt        ; count of chars in buffer
  2339.     mov    xmtbufx[bx],ah        ; put char in buffer
  2340.     pop    bx
  2341.     inc    xmtcnt            ; count of items in this buffer
  2342.     cmp    xmtcnt,length xmtbuf    ; is buffer full now?
  2343.     jae    outch9            ; ae = buffer is full, send it now
  2344.     cmp    ah,trans.seol        ; end of packet?
  2345.     je    outch9            ; e = yes, send buffer
  2346.     cmp    ah,flowon        ; flow control?
  2347.     je    outch9            ; e = yes, always expedite
  2348.     cmp    ah,flowoff        ; ditto for flow off
  2349.     je    outch9
  2350.     cmp    ttyact,0        ; are we in Connect mode?
  2351.     je    outch10            ; e = no, wait for more before sending
  2352. outch9: cmp    flags.comflg,'U'    ; check for UB port     [ohl]
  2353.     je    outch12            ; e = yes         [ohl]
  2354.     cmp    flags.comflg,'W'    ; Novell network?
  2355.     je    outch12            ; e = yes
  2356.     cmp    flags.comflg,'C'    ; 3Com BAPI
  2357.     je    outch12            ; e = yes
  2358.     call    send            ; NetBios network send routine
  2359.     jc    outch11            ; c = error
  2360. outch10:clc                ; good exit
  2361.     ret
  2362. outch11:stc                ; bad exit
  2363.     ret
  2364.  
  2365. outch12:jmp    ubsend            ; UB/Novell network send
  2366.     
  2367. outch14:mov    dx,decneth        ; DECnet, handle
  2368.     or    dl,dl            ; legal handle?
  2369.     jle    outch14c        ; le = invalid handle
  2370.     test    nettype,declat        ; LAT?
  2371.     jz    outch14a        ; z = no, use CTERM
  2372.     mov    al,ah
  2373.     mov    ah,latsend        ; LAT send byte
  2374.     int    latint
  2375.     jmp    short outch14b        ; common completion
  2376. outch14a:push    bx            ; CTERM
  2377.     mov    bl,ah            ; char to be sent
  2378.     mov    ax,dsend        ; send byte in bl
  2379.     int    decint
  2380.     pop    bx
  2381. outch14b:rcl    ah,1            ; status 80h bit, did char get sent?
  2382.     jnc    outch15            ; nc = success
  2383. outch14c:call    nethangup        ; failure
  2384.     stc
  2385. outch15:ret
  2386. OUTCHR    ENDP
  2387.  
  2388. ; NetBios Send packet routine. Send xmt scb with no-wait option. Waits
  2389. ; up to 6 seconds for current Send to complete before emitting new Send.
  2390. ; Failure to Send resets serial port (Server mode allows reiniting of serial
  2391. ; port). Returns carry clear for success, carry set for failure.
  2392. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  2393. SEND    PROC    NEAR            ; Network. Send session packet
  2394.     cmp    pcnet,1            ; network ready yet?
  2395.     ja    send0b            ; a = net is operational
  2396.     je    send0c            ; e = net but no session, fail
  2397.     jmp    send3a            ; no net, fail
  2398. send0c:    jmp    send3            ; net but no session
  2399. send0b:    cmp    sposted,0        ; is a send outstanding now?
  2400.     je    send1            ; e = no, go ahead
  2401.     push    cx            ; Timed test for old send being done
  2402.     mov    ch,trans.rtime        ; receive timeout other side wants
  2403.     mov    cl,80h            ; plus half a second
  2404.     shl    cx,1            ; sending timeout * 512
  2405. send0:    cmp    sposted,0        ; is a send outstanding now?
  2406.     je    send0a            ; e = no, clean up and do send
  2407.     push    cx            ; save cx
  2408.     push    ax            ; and ax
  2409.     mov    ax,2            ; wait 2 milliseconds
  2410.     call    pcwait            ;  between retests
  2411.     pop    ax
  2412.     pop    cx            ; loop counter
  2413.     loop    send0            ; repeat test
  2414.     pop    cx            ; recover cx
  2415.     jmp    send3a            ; get here on timeout, can't send
  2416. send0a:    pop    cx            ; recover cx and proceed to send
  2417.  
  2418. send1:    cmp    xmtcnt,0        ; number of items to send
  2419.     jne    send1a            ; ne = some
  2420.     clc                ; else don't send null packets
  2421.     ret
  2422. send1a:    push    bx            ; save these regs
  2423.     push    cx
  2424.     push    si
  2425.     push    di
  2426.     push    es
  2427.     push    ds
  2428.     pop    es            ; set es to data segment
  2429.     mov    si,offset xmtbufx    ; external buffer
  2430.     mov    di,offset xmtbuf    ; copy for network packets
  2431.     mov    cx,xmtcnt        ; buffer length
  2432.     mov    xmt.scb_length,cx    ; tell buffer length
  2433.     shr    cx,1            ; divide by two (words), set carry
  2434.     jnc    send2            ; nc = even number of bytes
  2435.     movsb                ; do single move
  2436. send2:    jcxz    send2a            ; z = nothing left to do
  2437.     rep    movsw            ; copy the data
  2438. send2a:    pop    es
  2439.     pop    di
  2440.     pop    si
  2441.     pop    cx
  2442.     mov    xmtcnt,0        ; say xmtbufx is available again
  2443.     mov    xmt.scb_cmd,nsend+nowait ; send, don't wait for completion
  2444.     mov    sposted,1        ; say send posted
  2445.     mov    bx,offset xmt        ; set pointer to scb
  2446.     call    session
  2447.     pop    bx            ; recover pointer to scb
  2448.                     ; success or failure?
  2449.     cmp    xmt.scb_err,0        ; good return?
  2450.     je    send4            ; e = yes
  2451.     cmp    xmt.scb_err,npending    ; pending?
  2452.     je    send4            ; e = yes
  2453.     cmp    xmt.scb_err,18h        ; session ended abnormally?
  2454.     jbe    send3            ; e = yes, b = other normal errors
  2455.     push    ax
  2456.     push    dx            ; another kind of error, show message
  2457.     mov    ah,prstr
  2458.     mov    dx,offset sndmsg    ; say send failed
  2459.     int    dos
  2460.     mov    al,xmt.scb_err        ; show error code (hex)
  2461.     call    hexout
  2462.     pop    dx
  2463.     pop    ax
  2464.                     ; Error return
  2465. send3:    mov    pcnet,1            ; say session is broken
  2466.     call    serrst            ; reset serial port
  2467.     test    flags.remflg,dserver    ; server mode?
  2468.     jz    send3a            ; z = no
  2469.     call    nethangup        ; Server: purge old NAKs etc
  2470. send3a:    call    serini            ; reinitialize it for new session
  2471.     stc                ; set carry for failure to send
  2472.     ret
  2473. send4:    clc
  2474.     ret
  2475. SEND    ENDP
  2476.  
  2477. ; NetBios Send packet completion interrupt routine. At entry CS is our
  2478. ; code segment, es:bx points to scb, netbios stack, interrupts are off.
  2479. SPOST    PROC    NEAR            ; post routine for Send packets
  2480.     push    ds
  2481.     push    ax
  2482.     mov    ax,data
  2483.     mov    ds,ax
  2484.     mov    sposted,0        ; clear send interlock
  2485.     pop    ax
  2486.     pop    ds
  2487.     iret
  2488. SPOST    ENDP    
  2489.  
  2490. ; Ungermann-Bass NETCI/Novell NASI port send packet routine.
  2491. ; Enter with xmtcnt holding length of data in xmtbuf to be sent.
  2492. ubsend    proc    near
  2493.     push    ax
  2494.     push    bx
  2495.     push    cx
  2496.     push    es
  2497.     mov    cx, xmtcnt        ; number of chars         [ohl]
  2498.     jcxz    ubsend1            ; dont send zero chars         [ohl]
  2499.     mov    bx, offset xmtbufx    ; buffer address in es:bx     [ohl]
  2500.     mov    ax, data
  2501.     mov    es, ax
  2502. ubsend2:test    nettype,bapi        ; 3Com BAPI?
  2503.     jz    ubsend2a        ; z = no, Int 6bh kind
  2504.     mov    ah,bapiwrit        ; 3Com block write
  2505.     xor    dh,dh            ; session 0
  2506.     int    bapiint
  2507.     jmp    short ubsend2b
  2508. ubsend2a:mov    ax, nciwrit        ; write function, port 0     [ohl]
  2509.     int    netci
  2510. ubsend2b:cmp    cx,xmtcnt        ; check that all characters sent [ohl]
  2511.     je    ubsend1            ; e = yes             [ohl]
  2512.     add    bx, cx            ; point to remaining chars     [ohl]
  2513.     sub    xmtcnt,cx        ; count of remaining characters     [ohl]
  2514.     mov    cx,xmtcnt        ; need count in cx too
  2515.     jmp    short    ubsend2        ; try again to send         [ohl]
  2516. ubsend1:mov    xmtcnt,0
  2517.     pop    es
  2518.     pop    cx
  2519.     pop    bx
  2520.     pop    ax
  2521.     clc                ; success, need failure case too
  2522.     ret
  2523. ubsend    endp                ;  [ohl] ---
  2524.  
  2525.  
  2526. ; Dispatch prebuilt NetBios session scb, enter with bx pointing to scb.
  2527. ; Returns status in al (and ah too). Allows STARLAN Int 2ah for netint.
  2528. SESSION    PROC    NEAR    
  2529.     push    es            ; save es around call
  2530.     push    ds
  2531.     pop    es            ; make es:bx point to scb in data seg
  2532.     mov    ax,exnbios        ; funct 4 execute netbios, for Int 2ah
  2533.     int    netint            ; use NetBios interrupt
  2534.     pop    es            ; saved registers
  2535.     ret                ; exit with status in ax
  2536. SESSION    ENDP
  2537.  
  2538. ; Make a NetBios virtual circuit Session, given preset scb's from proc chknet.
  2539. ; For Server mode, does a Listen to '*', otherwise does a Call to indicated
  2540. ; remote node. Updates vcid number in scb's. Shows success or fail msg.
  2541. ; Updates network status byte pcnet to 2 if session is established.
  2542. ; Does nothing if a session is active upon entry; otherwise, does a network
  2543. ; hangup first to clear old session material from adapter board. This is
  2544. ; the second procedure to call in initializing the network for usage.
  2545. SETNET    PROC    NEAR            ; NetBios, make a connection
  2546.     cmp    lposted,1        ; Listen pending?
  2547.     je    setne0            ; e = yes, exit now
  2548.     cmp    pcnet,1            ; session active?
  2549.     jbe    setne1            ; be = no
  2550. setne0:    ret
  2551.                     ; No Session
  2552. setne1:    call    nethangup        ; clear old session material
  2553.     test    flags.remflg,dserver    ; Server mode?
  2554.     jz    setne2            ; z = no, file xfer or Connect
  2555.                     ; Server mode, post a Listen (async)
  2556.     mov    lsn.scb_rname,'*'    ; accept anyone
  2557.     mov    ax,500
  2558.     call    pcwait            ; 0.5 sec wait
  2559.     mov    lposted,1        ; set listen interlock flag
  2560.     mov    lsn.scb_cmd,nlisten+nowait ; do LISTEN command, no wait
  2561.     push    bx            ; save reg
  2562.     mov    bx,offset lsn
  2563.     call    session
  2564.     pop    bx
  2565.     ret
  2566. setne2:                    ; Non-server (Client) mode
  2567.     test    nettype,starlan        ; STARLAN?
  2568.     jz    setne2a            ; z = no
  2569.     cmp    xmt.scb_vrlen,0        ; yes, using long name support?
  2570.     je    setne2a            ; e = no
  2571.     push    es            ; save reg
  2572.     push    ds
  2573.     pop    es            ; make es:bx point to xmt scb
  2574.     push    bx            ; save reg
  2575.     mov    bx,offset xmt        ; use xmt scb for the call
  2576.     mov    xmt.scb_cmd,ncall    ; CALL_ISN, vrname + vrlen are ready
  2577.     int    5bh            ; STARLAN CALL Int 5bh, wait
  2578.     pop    bx
  2579.     pop    es            ; restore regs
  2580.     jmp    short setne3        ; finish up
  2581.  
  2582.                     ; Regular Netbios Call
  2583. setne2a:cmp    flags.comflg,'O'    ; Opennet network? (FGR)
  2584.     jne    setne2b            ; ne = no
  2585.     mov    xmt.scb_rname+15,'v' ; fix name to use VT port under nameserver
  2586.     mov    rcv.scb_rname+15,'v'
  2587. setne2b:mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  2588.     push    bx            ; save reg
  2589.      mov    bx,offset xmt        ; setup scb pointer
  2590.     call    session
  2591.     pop    bx            ; restore register
  2592.  
  2593. setne3:                    ; common Call completion, show status
  2594.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  2595.     jnz    setne3a            ; nz = yes, do bad return
  2596.     or    al,al            ; check error return
  2597.     jnz    setne3b            ; nz = bad connection
  2598.     jmp    short setne4        ; good connection so far
  2599.  
  2600.                     ; We try twice, to allow for R1, and R3
  2601.                     ; versions of the nameservers
  2602. setne3b:cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  2603.     jne    setne3a            ; ne = no
  2604.     mov    xmt.scb_rname+15,' '    ; try generic port under nameserver
  2605.     mov    rcv.scb_rname+15,' '
  2606.                     ; Regular Netbios Call
  2607.     mov    xmt.scb_cmd,ncall    ; CALL, wait for answer
  2608.     push    bx            ; save reg
  2609.     mov    bx,offset xmt        ; setup scb pointer
  2610.     call    session
  2611.     pop    bx            ; restore register
  2612.  
  2613.                     ; common Call completion, show status
  2614.     test    xmt.scb_err,0ffh    ; is there a non-zero return code?
  2615.     jnz    setne3a            ; nz = yes, do bad return
  2616.     or    al,al            ; check error return
  2617.     jz    setne4            ; z = good connection so far
  2618. setne3a:mov    dx,offset nbadset    ; say can't reach remote node
  2619.     mov    ah,prstr
  2620.     int    dos
  2621.     call    saynode            ; show remote host node name
  2622.     jmp    setne4c
  2623.                     ; keep results of Call (vcid)
  2624. setne4:    mov    al,xmt.scb_vcid        ; local session number
  2625.     mov    rcv.scb_vcid,al        ; for receiver too
  2626.     mov    can.scb_vcid,al        ; for sending Breaks
  2627.     mov    pcnet,2            ; say session has started
  2628.  
  2629. ; Here is the real difference between Opennet and generic Netbios.
  2630. ; The Opennet Virtual Terminal Services exchange a small handshake at connect
  2631. ; time. After that it is just normal Netbios data transfer between the host
  2632. ; and Kermit.
  2633.     cmp    flags.comflg,'O'    ; Opennet netnork? (FGR)
  2634.     jne    setne4o            ; ne = no
  2635.     push    si
  2636.     push    di
  2637.     mov    si,offset ivt1str    ; protocol string "iVT1\0"
  2638.     mov    di,offset xmtbufx    ; buffer
  2639.     call    strcpy            ; copy asciiz string
  2640.     mov    xmtcnt,5        ; length of asciiz string, for send
  2641.     pop    di
  2642.     pop    si
  2643.     call    send            ; send signon packet
  2644. ; Note to Opennet purists: this just sends the handshake string to the host
  2645. ; system without checking for an appropriate response. Basically, I am just
  2646. ; very willing to talk to ANY VT server, and do the host response checking
  2647. ; (if desired) in a Kermit script file (so its optional).
  2648. setne4o:
  2649.     test    flags.remflg,dregular+dquiet ; regular or quiet display?
  2650.     jnz    setne4c            ; nz = yes, show only no-connect msg
  2651.     mov    dx,offset ngodset    ; say good connection
  2652.     mov    ah,prstr
  2653.     int    dos
  2654.     call    saynode            ; show remote host name
  2655. setne4c:cmp    pcnet,1            ; check connection again
  2656.     ja    setne5            ; a = good so far
  2657.     stc                ; set carry for failure
  2658.     ret
  2659. setne5:    clc                ; carry clear for success
  2660.     ret
  2661. SETNET    ENDP
  2662.  
  2663. saynode    proc    near        ; display node name on screen, si=name ptr
  2664.     push    ax
  2665.     push    cx
  2666.     push    dx
  2667.     push    si
  2668.     mov    ah,conout
  2669.     mov    si,offset nambuf    ; remote node string
  2670.     mov    cx,64            ; up to 64 bytes long
  2671. saynod1:cld
  2672.     lodsb                ; get remote node name char into al
  2673.     mov    dl,al
  2674.     int    dos            ; display it
  2675.     cmp    al,' '            ; was it a space?
  2676.     jbe    saynod2            ; be = yes, quit here
  2677.     loop    saynod1            ; do all chars
  2678. saynod2:mov    ah,prstr
  2679.     mov    dx,offset crlf
  2680.     int    dos
  2681.     pop    si
  2682.     pop    dx
  2683.     pop    cx
  2684.     pop    ax
  2685.     ret
  2686. saynode    endp
  2687.  
  2688. LPOST    PROC    FAR        ; Interrupt Post routine for Listen call
  2689.     push    ds        ; update vcid and calling node name in scb's
  2690.     push    cx    
  2691.     push    es
  2692.     push    si
  2693.     push    di
  2694.     mov    cx,data        ; reestablish data segment
  2695.     mov    ds,cx
  2696.     mov    es,cx
  2697.     mov    si,offset lsn.scb_rname    ; copy remote name to rcv and xmt scbs
  2698.     push    si
  2699.     mov    di,offset rcv.scb_rname
  2700.     mov    cx,8            ; 16 byte field
  2701.     cld
  2702.     rep    movsw
  2703.     mov    cx,8
  2704.     pop    si
  2705.     push    si
  2706.     mov    di,offset xmt.scb_rname
  2707.     rep    movsw
  2708.     mov    cx,8
  2709.     pop    si
  2710.     mov    di,offset nambuf    ; and to nambuf for display
  2711.     rep    movsw
  2712.     mov    cl,lsn.scb_vcid        ; local session number
  2713.     mov    rcv.scb_vcid,cl
  2714.     mov    xmt.scb_vcid,cl
  2715.     mov    can.scb_vcid,cl
  2716.     mov    lposted,0        ; clear interlock flag
  2717.     mov    pcnet,2            ; say net ready due to a Listen
  2718.     pop    di
  2719.     pop    si
  2720.     pop    es
  2721.     pop    cx
  2722.     pop    ds
  2723.     iret                ; return from interrupt
  2724. LPOST    ENDP
  2725.  
  2726.  
  2727. NETHANGUP PROC    NEAR             ; disconnect network session, keep names
  2728.     cmp    pcnet,0            ; network started?
  2729.     je    nethang1        ; e = no
  2730.     mov    al,flags.comflg        ; get type of port
  2731.     cmp    al, 'U'            ; Ungermann-Bass port? [ohl]
  2732.     je    nethang2        ; e = yes [ohl]
  2733.     cmp    al,'W'            ; Novell?
  2734.     je    nethang2        ; e = yes
  2735.     cmp    al,'D'            ; DECnet?
  2736.     je    nethang3        ; e = yes
  2737.     push    bx            ; NetBios network
  2738.     mov    bx,offset can 
  2739.     mov    can.scb_cmd,ncancel    ; set cancel op code
  2740.     mov    can.scb_baddr,offset lsn ; cancel listens
  2741.     mov    lposted,0        ; say no listen
  2742.     call    session
  2743.     mov    can.scb_baddr,offset rcv ; cancel receives
  2744.     call    session
  2745.     mov    rposted,0        ; say no receives posted
  2746.     mov    can.scb_baddr,offset xmt ; cancel sends
  2747.     call    session
  2748.     mov    sposted,0        ; say no sends posted
  2749.     mov    xmtcnt,0        ; reset output buffer counter
  2750.     mov    xmt.scb_cmd,nhangup    ; hangup, and wait for completion
  2751.     mov    bx,offset xmt
  2752.     call    session
  2753.     pop    bx
  2754.     mov    portn.portrdy,0        ; say the comms port is not ready
  2755.     mov    pcnet,1            ; say network but no session
  2756.     call    serrst            ; reset the serial port for reiniting
  2757. nethang1:clc
  2758.     ret
  2759.                     ; UB network [ohl] +++
  2760. nethang2:call    ubclose            ; close connection if any [ohl]
  2761.     mov    xmtcnt,0
  2762.     clc
  2763.     ret                ;  [ohl] ---
  2764. nethang3:mov    dx,decneth        ; DECnet handle
  2765.     test    nettype,declat        ; DECnet LAT active?
  2766.     jz    nethang4        ; z = no
  2767.     mov    ax,latclose
  2768.     int    latint
  2769.     and    nettype,not declat    ; remove net type bit
  2770.     jmp    short nethang5
  2771. nethang4:test    nettype,decnet        ; DEC CTERM active?
  2772.     jz    nethang5        ; z = no
  2773.     mov    ax,dclose        ; CTERM close
  2774.     int    decint
  2775.     and    nettype,not decnet    ; remove net type bit
  2776. nethang5:xor    dx,dx            ; clear handle
  2777.     mov    decneth,dx
  2778.     mov    portn.portrdy,0        ; say the comms port is not ready
  2779.     mov    pcnet,1            ; say network but no session
  2780.     call    serrst            ; reset the serial port for reiniting
  2781.     clc
  2782.     ret
  2783. NETHANGUP ENDP
  2784.  
  2785. ; Ungermann Bass. Do a disconnect from the current connection.
  2786. ubclose proc    near
  2787.     push    ax
  2788.     push    cx
  2789.     test    nettype,netone        ; UB network has been activated?
  2790.     jz    ubclos3            ; z = no
  2791.     mov    ax, ncistat        ; get status             [ohl]
  2792.     int    netci
  2793.      or    ch,ch            ; check if we have a connection     [ohl]
  2794.     jz    ubclos2            ; z = no             [ohl]
  2795.     mov    ax, ncicont        ; control function         [ohl]
  2796.     mov    cx, ncidis        ; say disconnect         [ohl]
  2797.     int    netci
  2798. ubclos1:call    ubrecv            ; read response from net cmdintpr[ohl]
  2799.     jnc    ubclos1            ; continue till no chars     [ohl]
  2800.     mov    ax, ncistat        ; get status again
  2801.     int    netci
  2802.     or    ch,ch            ; check if we have a connection
  2803.     jnz    ubclos3            ; nz = yes, had more than one
  2804. ubclos2:and    nettype,not netone    ; remove network type
  2805.     mov    pcnet,1            ; net but no connection
  2806.     mov    portn.portrdy,0        ; say the comms port is not ready
  2807. ubclos3:pop    cx
  2808.     pop    dx
  2809.     ret
  2810. ubclos4:test    nettype,bapi        ; 3Com BAPI in use?
  2811.     jz    ubclos3            ; z = no
  2812.     mov    ah,bapieecm        ; control Enter Command Mode char
  2813.     mov    al,1            ; enable it
  2814.     int    bapiint
  2815.     jmp    short ubclos3
  2816. ubclose endp
  2817.  
  2818. ; Ungermann Bass/Novell. Put current connection on Hold. Requires keyboard
  2819. ; verb \kubhold to activate. Should return to Connect mode to see NASI. [jrd]
  2820. ubhold    proc    near
  2821.     push    ax
  2822.     push    cx
  2823.     test    nettype,netone        ; UB/Novell network active?
  2824.     jz    ubhold1            ; z = no
  2825.     mov    ax,ncistat        ; get link status
  2826.     int    netci
  2827.     or    ch,ch            ; connection active?
  2828.     jz    ubhold1            ; z = no
  2829.     mov    ax,ncicont        ; control command
  2830.     mov    cl,ncihld        ; place circuit on HOLD
  2831.     int    netci
  2832.     jmp    short ubhold2
  2833. ubhold1:test    nettype,bapi        ; 3Com BAPI?
  2834.     jz    ubhold2            ; z = no
  2835.     mov    ah,bapiecm        ; do Enter Command Mode char
  2836.     int    bapiint
  2837. ubhold2:pop    cx
  2838.     pop    dx
  2839.     clc
  2840.     ret
  2841. ubhold    endp
  2842.  
  2843. ; Called when Kermit exits. Name passed to mssker by initialization lclini
  2844. ; in word lclexit.
  2845. NETCLOSE PROC    NEAR            ; close entire network connection
  2846.     cmp    pcnet,0            ; network ever used?
  2847.     je    netclo1            ; e = no, so don't touch it
  2848.     call    nethangup        ; close connections
  2849.     test    nettype,netbios        ; NetBios activated?
  2850.     jz    netclo1            ; z = no
  2851.     push    bx
  2852.     mov    bx,offset xmt
  2853.     mov    xmt.scb_cmd,ndelete    ; delete our local Kermit name
  2854.     call    session            ;  from net adapter board
  2855.     pop    bx
  2856.     mov    pcnet,0            ; say no network
  2857.     mov    portn.portrdy,0        ; say comms port is not ready
  2858.     and    nettype,not netbios    ; remove network kind
  2859. netclo1:clc
  2860.     ret
  2861. NETCLOSE ENDP    
  2862.  
  2863. ; Start connection process to network. Obtains Network board local name
  2864. ; and appends '.K' to form Kermit's local name (removed when Kermit exits).
  2865. ; If no local name is present then use name 'mskermit.K'.
  2866. ; Sets local name in scb's for xmt, rcv, lsn. (Does not need DOS 3.x)
  2867. ; Sets NETDONE pointer to procedure netclose for Kermit exit.
  2868. ; Verifies existance of interrupt 5ch support, verifies vendor specific
  2869. ; support for BREAK and other features, sets network type bit in nettype,
  2870. ; sets BREAK support in nsbrk, hangsup old session if new node name given,
  2871. ; fills in local and remote node names and name number in scbs (including ISN
  2872. ; names for STARLAN), and sets network status byte pcnet to 0 (no net) or
  2873. ; to 1 (net ready). This is the first procedure called to init network usage.
  2874. ; Byte count of new host name is in temp from COMS.
  2875. chknet    proc    near
  2876.     cmp    flags.comflg,'U'    ; Ungermann Bass network?
  2877.     jb    chknea            ; b = no, (ae includes U and W)
  2878.     mov    pcnet,0            ; force reactivation of UB net
  2879. chknea:    cmp    pcnet,2            ; session active now?
  2880.     jb    chknec            ; b = no
  2881.     cmp    temp,0            ; byte count of new name, if any
  2882.     je    chkneb            ; e = none, resume old session
  2883.     call    chknew            ; Resume current session?
  2884.     jc    chknex            ; c = yes
  2885.     cmp    rdbuf,0            ; New session?
  2886.     je    chkneb            ; e = yes
  2887.     clc
  2888. chknex:    ret                ; resume old one
  2889. chkneb:    jmp    chknet1            ; skip presence tests
  2890.  
  2891. chknec:                ; setup addresses and clear junk in scb's
  2892.     cmp    pcnet,0            ; have we been here already?
  2893.     je    chkned            ; e = no
  2894.     jmp    chknet1            ; yes, skip init part
  2895. chkned:    mov    xmtcnt,0        ; say buffer is empty
  2896.     mov    nsbrk,0            ; assume no BREAK across network
  2897.     and    nettype,not netbios    ; say no NetBios network yet
  2898.  
  2899.     push    bx
  2900.     push    es            ; Test for Netbios presence, IBM way
  2901.     mov    ah,35h            ; DOS get interrupt vector
  2902.     mov    al,netint        ; the netbios vector
  2903.     int    dos            ; returns vector in es:bx
  2904.     mov    ax,es
  2905.     cmp    ax,0f000h        ; rom bios segment??
  2906.     jb    chknee            ; b = not likely, else Bios has
  2907.     xor    ax,ax            ;  trapped this vector to dummy iret
  2908.     xor    bx,bx            ; fake null vector
  2909. chknee:    or    bx,ax            ; is vector present?
  2910.     pop    es
  2911.     pop    bx
  2912.     jz    chknet0            ; z = no
  2913.     mov    xmt.scb_cmd,7fh ; presence test, 7fh is illegal command code
  2914.     mov    xmt.scb_err,0        ; clear response field
  2915.     push    bx
  2916.     mov    bx,offset xmt        ; address of the session control block
  2917.     call    session            ; execute operation
  2918.     pop    bx
  2919.     mov    al,xmt.scb_err        ; get response
  2920.     cmp    xmt.scb_err,3        ; 'illegal function', so adapter is ready
  2921.     jne    chknet0            ; ne = failure
  2922.     push    bx
  2923.     push    es            ; Test for Netbios presence, IBM way
  2924.     mov    ah,35h            ; DOS get interrupt vector
  2925.     mov    al,2ah            ; the netbios vector 2ah
  2926.     int    dos            ; returns vector in es:bx
  2927.     mov    ax,es
  2928.     cmp    ax,0f000h        ; rom bios segment??
  2929.     jb    chknef            ; b = not likely
  2930.     xor    ax,ax
  2931.     xor    bx,bx            ; fake null vector
  2932. chknef:    or    bx,ax            ; is vector present?
  2933.     pop    es
  2934.     pop    bx
  2935.     jz    chknet0            ; z = no, no NetBios network
  2936.     or    nettype,netbios        ; say have NetBios network
  2937.                 ; AT&T STARLAN board check (0ddh=magic #)
  2938.     xor    ah,ah            ; vendor installation check on int 2ah
  2939.     xor    al,al            ; do error retry
  2940.     int    2ah            ; session level interrupt
  2941.     cmp    ah,0ddh            ; 0ddh = magic number, success?
  2942.     jne    chknet1            ; ne = no
  2943.     or    nettype,starlan        ; say using STARLAN, have int 2ah
  2944.     push    bx
  2945.     push    es            ; Test for vector
  2946.     mov    ah,35h            ; DOS get interrupt vector
  2947.     mov    al,5bh            ; 5bh = STARLAN netbios ext'd vector
  2948.     int    dos            ; returns vector in es:bx
  2949.     mov    ax,es
  2950.     or    bx,ax            ; is vector present?
  2951.     pop    es
  2952.     pop    bx
  2953.     jz    chknet1            ; z = no
  2954.     mov    nsbrk,1            ; network BREAK supported
  2955.     jmp    chknet1
  2956.  
  2957. chknet0:mov    pcnet,0            ; no network yet
  2958.     push    dx
  2959.     mov    ah,prstr
  2960.     mov    dx,offset nonetmsg    ; say network is not available
  2961.     int    dos
  2962.     pop    dx
  2963.     stc                ; set carry for failure
  2964.     ret                ; and exit now
  2965.  
  2966.                     ; net ready to operate
  2967. chknet1:mov    portn.portrdy,1        ; say the comms port is ready
  2968.     cmp    temp,0            ; byte count of new name, from COMS
  2969.     jne    chkne1e            ; ne = new name given
  2970.     jmp    chknet2            ; nothing, so leave names intact
  2971. chkne1e:cmp    pcnet,2            ; is session active now?
  2972.     jb    chkne1d            ; b = no
  2973.     call    nethangup        ; hangup net to clear old connection
  2974. chkne1d:                ; start fresh connection
  2975.     push    si
  2976.     push    di
  2977.     push    es
  2978.     push    ds
  2979.     pop    es            ; make es:di point to data segment
  2980.     cld
  2981.     mov    cx,8            ; 16 bytes for a node name
  2982.     mov    ax,'  '            ; first, fill with spaces
  2983.     mov    di,offset xmt.scb_rname ; remote name field, clear it
  2984.     rep    stosw
  2985.     test    nettype,starlan        ; STARLAN?
  2986.     jz    chkne1b            ; z = no
  2987.                     ; begin STARLAN section    
  2988.     mov    xmt.scb_vrname,0    ; STARLAN var length name ptr
  2989.     mov    xmt.scb_vrname+2,0    ; segement of name    
  2990.     mov    xmt.scb_vrlen,0        ; and its length
  2991.     mov    cx,temp            ; count of characters in new name
  2992.     cmp    cx,16            ; > 16 chars in remote node name?
  2993.     ja    chkne1a            ; a = yes, too long for Netbios
  2994.     mov    al,'/'            ; scan for slashes in name
  2995.     mov    di,offset nambuf    ; source of text
  2996.     cld
  2997.     repne    scasb            ; look for the slash
  2998.     jne    chkne1b        ; ne = none, do regular Netbios name storage
  2999. chkne1a:                ; STARLAN ISN long remote name support
  3000.     mov    xmt.scb_vrname,offset nambuf    ; STARLAN var length name ptr
  3001.     mov    xmt.scb_vrname+2,data        ; segment of remote name    
  3002.     mov    cx,temp            ; get name length again (in cl)
  3003.     mov    xmt.scb_vrlen,cl    ; indicate its length
  3004.     jmp    chkne1c            ; copy blanks in remote name field
  3005.                     ; end STARLAN section
  3006.  
  3007. chkne1b:mov    cx,temp            ; Regular Netbios form, name length
  3008.     mov    si,offset nambuf    ; source of text
  3009.     mov    di,offset xmt.scb_rname ; destination is remote name
  3010.     rep    movsb            ; copy text to transmitter's scb
  3011. chkne1c:mov    cx,8            ; 8 words
  3012.     mov    si,offset xmt.scb_rname ; from here
  3013.     mov    di,offset rcv.scb_rname ; to receiver's scb also
  3014.     rep    movsw
  3015.     pop    es
  3016.     pop    di
  3017.     pop    si
  3018.  
  3019. chknet2:cmp    pcnet,0            ; started net?
  3020.     je    chknet2c        ; e = no
  3021.     ret                ; else quit here
  3022. chknet2c:
  3023.     mov    ah,prstr
  3024.     mov    dx,offset netmsg1    ; say checking node name
  3025.     int    dos
  3026.     push    word ptr xmt.scb_rname    ; save first two bytes (user spec)
  3027.     mov    byte ptr xmt.scb_rname,'*'    ; call to local name
  3028.     push    bx
  3029.     mov    xmt.scb_cmd,naustat    ; get Network Adapter Unit status
  3030.     mov    bx,offset xmt
  3031.     call    session
  3032.     pop    bx
  3033.     pop    word ptr xmt.scb_rname    ; restore remote name first two bytes
  3034. chknet2a:
  3035.     push    es            ; save registers
  3036.     push    di
  3037.     push    si
  3038.     push    cx
  3039.     push    ds
  3040.     pop    es            ; set es:di to data segment
  3041.     mov    si,offset xmtbuf+60 ; where local name is returned (1st entry)
  3042.     cmp    word ptr xmtbuf+58,0    ; is local name empty?
  3043.     jne    chknet2b        ; ne = no, use name from table
  3044.     mov    si,offset deflname    ; else use default local name
  3045. chknet2b:
  3046.     mov    di,offset xmt.scb_lname ; where to put it in scb
  3047.     mov    cx,14            ; 16 bytes minus extension of '.K'
  3048.     cld                ; append extension of '.K' to loc name
  3049. chknet3:cmp    byte ptr[si],' ' ; find first space (end of regular node name)
  3050.     jbe    chknet4            ; be = found one (or control code)
  3051.     movsb                ; copy local name to scb
  3052.     loop    chknet3            ; continue though local name
  3053. chknet4:cmp    word ptr [di-2],'K.'    ; is extension '.K' present already?
  3054.     je    chknet4a        ; e = yes, nothing to add
  3055.     cmp    word ptr [di-2],'k.'    ; check lower case too
  3056.     je    chknet4a        ; e = yes, nothing to add
  3057.     mov    word ptr [di],'K.'    ; append our extension of '.K'
  3058.     add    di,2            ; step over our new extension
  3059.     sub    cx,2
  3060.                     ; complete field with spaces
  3061.     add    cx,2            ; 15th and 16th chars
  3062. chknet4a:jcxz    chknet5            ; z = nothing to add
  3063.     mov    al,' '            ; space as padding
  3064.     rep    stosb    
  3065. chknet5:mov    si,offset xmt.scb_lname
  3066.     mov    di,offset rcv.scb_lname ; put in receiver scb too
  3067.     mov    cx,8
  3068.     rep    movsw
  3069.     mov    cx,8
  3070.     mov    si,offset xmt.scb_lname
  3071.     mov    di,offset lsn.scb_lname    ; in Listen scb also
  3072.     rep    movsw
  3073.     pop    cx
  3074.     pop    si
  3075.     pop    di
  3076.     pop    es
  3077.  
  3078.     push    bx            ; Put our new local name in NAU
  3079.     mov    xmt.scb_cmd,nadd    ; ADD NAME, wait
  3080.     mov    bx,offset xmt
  3081.     call    session
  3082.     pop    bx
  3083.     mov    al,xmt.scb_err        ; get error code
  3084.     or    al,al            ; success?
  3085.     jz    chknet7            ; z = yes
  3086.     cmp    al,0dh            ; duplicate name in local table?
  3087.     je    chknet6a        ; e = yes
  3088.     cmp    al,16h            ; name used elsewhere?
  3089.     je    chknet6a        ; e = yes
  3090.     cmp    al,19h            ; name conflict?
  3091.     je    chknet6a        ; e = yes
  3092.     push    ax
  3093.     mov    ah,prstr        ; another kind of error
  3094.     mov    dx,offset chkmsg1    ; say can't construct local name
  3095.     int    dos
  3096.     pop    ax
  3097.     call    hexout            ; display it (in al)
  3098.     mov    ah,prstr
  3099.     mov    dx,offset crlf
  3100.     int    dos
  3101.     mov    pcnet,0            ; say no connection today
  3102.     stc                ; set carry for failure
  3103.     ret
  3104. chknet6a:
  3105.     mov    ah,prstr        ; ask for another name
  3106.     mov    dx,offset chkmsg2    ; prompt message
  3107.     int    dos
  3108.     mov    ah,conout        ; show name itself
  3109.     push    cx
  3110.     mov    cx,16            ; 16 bytes in name field
  3111.     mov    si,offset xmt.scb_lname
  3112. chknet6c:lodsb                ; get name char into al
  3113.     mov    dl,al
  3114.     int    dos
  3115.     mov    byte ptr[si-1],' '    ; clear old name as we go
  3116.     loop    chknet6c
  3117.     pop    cx
  3118.     mov    ah,prstr
  3119.     mov    dx,offset chkmsg3    ; rest of prompt
  3120.     int    dos
  3121.  
  3122.     mov    ah,0ah            ; read buffered line from stdin
  3123.     mov    dx,offset xmtbuf+58    ; where to put text (xmtbuf+60=text)
  3124.     mov    xmtbuf+58,15        ; buf capacity, including cr at end
  3125.     mov    xmtbuf+59,0        ; say text in buffer = none
  3126.     int    dos
  3127.     jc    chknet6b        ; c = error
  3128.     cmp    xmtbuf+59,0        ; any bytes read?
  3129.     je    chknet6b        ; e = no, exit failure
  3130.     mov    ah,prstr        ; say rechecking name
  3131.     mov    dx,offset netmsg1
  3132.     int    dos
  3133.     jmp    chknet2a        ; go reinterpret name
  3134. chknet6b:
  3135.     stc                ; set carry for failure
  3136.     ret
  3137.  
  3138. chknet7:mov    pcnet,1            ; network is present (but not active)
  3139.     mov    al,xmt.scb_num        ; name number
  3140.     mov    rcv.scb_num,al
  3141.     mov    lsn.scb_num,al
  3142.     push    ax
  3143.     push    cx
  3144.     mov    dx,offset netmsg2     ; say net going
  3145.     mov    ah,prstr
  3146.     int    dos
  3147.     mov    si,offset rcv.scb_lname ; display our local name
  3148.     mov    ah,conout
  3149.     mov    cx,16
  3150.     cld
  3151. chknet9:lodsb                ; byte from si to al
  3152.     mov    dl,al
  3153.     int    dos            ; display it
  3154.     loop    chknet9
  3155.     mov    ah,prstr
  3156.     mov    dx,offset crlf        ; add cr/lf
  3157.     int    dos
  3158.     pop    cx
  3159.     pop    ax
  3160.     clc                ; carry clear for success
  3161.     ret
  3162. chknet    endp
  3163.  
  3164. ; Network session exists. Tell user and ask for new node or Resume.
  3165. ; Returns rdbuf 0 if Resume response.
  3166. chknew    proc    near
  3167.     mov    dx,offset naskpmt    ; prompt for New or Resume
  3168.     call    prompt
  3169.     mov    dx,offset nettab    ; table of answers
  3170.     xor    bx,bx            ; help for the question
  3171.     mov    ah,cmkey        ; get answer keyword
  3172.     mov    comand.cmcr,1        ; allow bare CR's
  3173.     call    comnd
  3174.     mov    comand.cmcr,0        ; dis-allow bare CR's
  3175.     jc    chknew1            ; c = failure, means Resume
  3176.     mov    rdbuf,bl        ; save keyword action value here
  3177.     mov    ah,cmeol        ; get a confirm
  3178.     call    comnd
  3179. chknew1:ret                ; carry may be set
  3180. chknew    endp
  3181.  
  3182. ;                    ; [ohl] ++++
  3183. ; Verifies existance of interrupt 6Bh support, verifies vendor specific
  3184. ; support for BREAK and other features, sets network type bit in nettype,
  3185. ; sets BREAK support in nsbrk and sets network status byte pcnet to 0
  3186. ; (no net) or to 1 (net ready). This is the first procedure called to
  3187. ; init Ungermann-Bass NETCI terminal port network usage.
  3188. chkub  proc    near
  3189.     push    bx
  3190.         push    es                      ; Test for vector
  3191.         mov     ah,35h                  ; DOS get interrupt vector
  3192.         mov     al,6bh                  ; 6bh = Net/One command interpreter
  3193.                     ;  interface, with break support
  3194.         int     dos                     ; returns vector in es:bx
  3195.     mov    ax,es            ; is vector in rom bios??? [jrd]
  3196.     cmp    ax,0f000h        ; rom bios starts here
  3197.     jb    chkub2            ; b = not likely
  3198.     xor    ax,ax            ; yes, say no network
  3199.     mov    es,ax            ; fake a null vector
  3200.     mov    bx,ax
  3201. chkub2:    mov     ax,es
  3202.         or      bx,ax                   ; is vector present?
  3203.         jz      chkub0                  ; z = no
  3204.     mov    al,0ffh            ; test value (anything non-zero)
  3205.     mov    ah,2            ; function code for testing net board
  3206.     int    netci
  3207.     or    al,al            ; al = 0 means board is ok
  3208.     jnz    chkub0            ; nz = not ok
  3209.     pop    es
  3210.     pop    bx
  3211.         mov     nsbrk,1                 ; network BREAK supported
  3212.         or      nettype,netone        ; say have Net/One
  3213.     clc                ; return success
  3214.     ret
  3215.  
  3216. chkub0:    pop    es            ; clean stack from above
  3217.     pop    bx
  3218.     push    ax
  3219.         push    dx
  3220.         mov     ah,prstr
  3221.         mov     dx,offset nonetmsg      ; say network is not available
  3222.         int     dos
  3223.         pop     dx
  3224.         pop     ax
  3225.         stc                             ; set carry for failure
  3226.         ret                             ; and exit now
  3227. chkub  endp                ; [ohl] ----
  3228.  
  3229. hexout    proc    near            ; display byte in al as hex value
  3230.     push    ax            ; all regs preserved
  3231.     push    cx
  3232.     push    dx
  3233.     mov    cx,2            ; two nibbles
  3234. hexout1:push    cx            ; save counter
  3235.     mov    cl,4            ; high nibble
  3236.     ror    al,cl            ; put in low order field
  3237.     mov    dl,al
  3238.     xchg    ch,al            ; save al byte in ch
  3239.     and    dl,0fh            ; four bits
  3240.     cmp    dl,9            ; too big?
  3241.     jbe    hexout2            ; be = no
  3242.     add    dl,'A'-'9'-1        ; bump up to A-F
  3243. hexout2:add    dl,'0'
  3244.     mov    ah,conout
  3245.     int    dos
  3246.     xchg    ch,al            ; recover data byte
  3247.     pop    cx
  3248.     loop    hexout1            ; do second nibble
  3249.     mov    dl,'H'            ; add a final hex ident
  3250.     int    dos
  3251.     pop    ax
  3252.     pop    cx
  3253.     pop    dx
  3254.     ret
  3255. hexout    endp
  3256.  
  3257. ; local routine to see if we have to transmit an xon
  3258. chkxon    proc    near
  3259.     cmp    flowon,0        ; doing flow control?
  3260.     je    chkxo1            ; no, skip all this
  3261.     test    xofsnt,usron        ; did user send an xoff?
  3262.     jnz    chkxo1            ; nz = yes, don't contradict it here
  3263.     test    xofsnt,bufon        ; have we sent a buffer level xoff?
  3264.     jz    chkxo1            ; z = no, forget it
  3265.     cmp    count,mntrgl        ; below (low water mark) trigger?
  3266.     jae    chkxo1            ; no, forget it
  3267.     mov    ah,flowon        ; ah gets xon
  3268.     and    xofsnt,off        ; remember we've sent the xon
  3269.     call    outch2            ; send via non-flow controlled entry point
  3270. chkxo1:    ret
  3271. chkxon    endp
  3272.  
  3273. ; IHOSTS - Initialize the host by sending XOFF, or equivalent.
  3274. ; Requires that the port be initialized before hand.
  3275. ; Do not send flow control if doing half duplex.
  3276.  
  3277. IHOSTS    PROC    NEAR
  3278.     push    ax        ; save the registers
  3279.     push    cx
  3280.     push    dx
  3281.     mov    xofrcv,off    ; clear old xoff received flag
  3282.     mov    xofsnt,off    ; and old xoff sent flag
  3283.     mov    ah,flowoff    ; put wait flow control char in ah
  3284.     or    ah,ah        ; check for null char
  3285.     jz    ihosts1        ; z = null, don't send it
  3286.     cmp    dupflg,0    ; full duplex?
  3287.     jne    ihosts1        ; ne = no, half
  3288.     call    outchr        ; send it
  3289. ihosts1:call    clrbuf        ; clear out interrupt buffer
  3290.     pop    dx            ; empty buffer. we are done here
  3291.     pop    cx
  3292.     pop    ax
  3293.     ret
  3294. IHOSTS    ENDP
  3295.  
  3296. ; IHOSTR - initialize the remote host for our reception of a file by
  3297. ; sending the flow-on character (XON typically) to release any held
  3298. ; data. Do not send flow control if doing half duplex.
  3299. IHOSTR    PROC    NEAR
  3300.     push    ax        ; save regs
  3301.     push    cx
  3302.     mov    xofrcv,off    ; clear old xoff received flag
  3303.     mov    xofsnt,off    ; and old xoff sent flag
  3304.     mov    ah,flowon    ; put Go-ahead flow control char in ah
  3305.     or    ah,ah        ; check for null char
  3306.     jz    ihostr1        ; z = null, don't send it
  3307.     cmp    dupflg,0    ; full duplex?
  3308.     jne    ihostr1        ; ne = no, half
  3309.     call    outchr        ; send it (release Host's output queue)
  3310. ihostr1:pop    cx
  3311.     pop    ax
  3312.     ret
  3313. IHOSTR    ENDP
  3314.  
  3315. ; Send a break out the current serial port.  Returns normally.
  3316. ; Do both regular and long Break. 6 March 1987 [jrd]
  3317.  
  3318. SENDBR    PROC    NEAR
  3319.     push    cx        ; Regular Break entry point
  3320.     mov    cx,275        ; 275 milliseconds in regular Break
  3321.     call    sendbw        ; call worker routine to do it
  3322.     pop    cx
  3323.     clc            ; don't exit Connect mode
  3324.     ret
  3325. SENDBL:    push    cx        ; Long Break entry point
  3326.     mov    cx,1800        ; 1.8 second long break
  3327.     call    sendbw        ; call worker routine to do it
  3328.     pop    cx
  3329.     clc            ; don't exit Connect mode
  3330.     ret
  3331.                 ; worker - send Break for cx millisec
  3332. sendbw:    mov    al,flags.comflg    ; get type of port
  3333.     cmp    al,4        ; running on a UART?
  3334.     ja    sendbw2        ; a = yes
  3335.     push    dx        ; UART BREAK
  3336.     mov    dx,brkadr    ; port address
  3337.     in    al,dx        ; get current setting
  3338.     push    ax        ; save setting on the stack
  3339.     or    al,brkval    ; set send-break bit(s)
  3340.     out    dx,al        ; start the break
  3341.     mov    ax,cx        ; # of ms to wait
  3342.     call    pcwait        ; hold break for desired interval
  3343.     pop    ax        ; restore Line Control Register
  3344.     out    dx,al        ; stop the break
  3345.     pop    ax
  3346.     ret
  3347. sendbw2:cmp    al,'N'        ; is this a NetBios network port?
  3348.     jne    sendbw5        ; ne = no
  3349.     cmp    nsbrk,0        ; is network able to send a break?
  3350.     je    sendbw4        ; e = no
  3351.     test    nettype,starlan    ; STARLAN: network break supported?
  3352.     jz    sendbw4        ; z = no
  3353.     push    bx
  3354.     push    es        ; save es around call
  3355.     push    ds
  3356.     pop    es        ; make es:bx point to scb in data segment
  3357.     mov    bx,offset can    ; use Cancel control block
  3358.     mov    can.scb_cmd,netbrk ; send net Break command
  3359.     int    5bh        ; use network Break interrupt
  3360.     pop    es        ; saved registers
  3361.     pop    bx
  3362. sendbw4:ret
  3363. sendbw5:cmp    al,'4'            ; Bios?
  3364.     ja    sendbw6            ; a = no
  3365.     push    ax
  3366.     push    dx
  3367.     call    chkbios            ; set dl to port, check IBM EBIOS
  3368.     jc    sendbw5a        ; c = not present
  3369.     mov    ah,0fbh            ; send BREAK, IBM EBIOS code
  3370.     int    rs232            ; bios send
  3371. sendbw5a:pop    dx
  3372.     pop    ax
  3373.     ret
  3374. sendbw6:cmp    al,'U'            ; is it an UB NETCI port?     [ohl]
  3375.     je    sendbw6            ; e = yes             [ohl]
  3376.     cmp    al,'W'            ; Novell network?
  3377.     jne    sendbw7            ; ne = no
  3378.     push    cx            ; UB port send break         [ohl] +++
  3379.     mov    ax,ncicont + 0    ; call control, use 0 for network port num [ohl]
  3380.     mov    cl,ncibrk    ; request break                 [ohl]
  3381.     int    netci        ; Net/One command interface int. (6Bh)     [ohl]
  3382.     pop    cx
  3383.     ret                ;  [ohl] ---
  3384. sendbw7:cmp    al,'D'            ; DECnet?
  3385.     jne    sendbw9            ; ne = no
  3386.     test    nettype,declat        ; LAT?
  3387.     jz    sendbw8            ; z = no, CTERM cannot send a BREAK
  3388.     mov    ax,latbreak        ; LAT BREAK command
  3389.     push    dx
  3390.     mov    dx,decneth        ; DECnet handle
  3391.     int    latint
  3392.     pop    dx
  3393. sendbw8:ret
  3394. sendbw9:test    nettype,bapi        ; 3Com BAPI interface?
  3395.     jne    sendbw8            ; ne = no
  3396.     mov    ah,bapibrk        ; BAPI, send BREAK
  3397.     xor    dh,dh            ; session id of 0 (external sessions)
  3398.     int    bapiint
  3399.     ret
  3400. SENDBR    ENDP
  3401.  
  3402. ; Initialization for using serial port.  This routine performs
  3403. ; any initialization necessary for using the serial port, including
  3404. ; setting up interrupt routines, setting buffer pointers, etc.
  3405. ; Doing this twice in a row should be harmless (this version checks
  3406. ; a flag and returns if initialization has already been done).
  3407. ; SERRST below should restore any interrupt vectors that this changes.
  3408. ;
  3409. ; Revised slightly by Joe R. Doupnik 22 Dec 1985 to prevent interrupts
  3410. ; being enabled until we're done, to stop interrupts from occurring when
  3411. ; TX holding buffer becomes empty (a useless interrupt for us), and to
  3412. ; shorten the time between enabling interrupts and our exit.
  3413. ; Returns carry clear if success, else carry set.
  3414. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  3415. SERINI    PROC    NEAR
  3416.     call    pcwtst            ; recalibrate pcwait loop timer
  3417.     cmp    portin,0        ; did we initialize port already?
  3418.     je    serin5            ; e = yes
  3419.     jl    serin0            ; l = no, not yet
  3420.     jmp    serin4            ; yes, update flow and leave
  3421. serin0:    mov    bl,flags.comflg        ; pass current port ident
  3422.     call    comstrt            ; do SET PORT now
  3423.     jnc    serin5            ; nc = success
  3424.     ret                ; failed, exit now
  3425. serin5:    push    bx
  3426.     mov    bx,portval
  3427.     mov    bl,[bx].duplex        ; get full/half duplex flag, local cpy
  3428.     mov    dupflg,bl
  3429.     pop    bx
  3430.     cmp    flags.comflg,4        ; UART?
  3431.     jbe    serin2            ; be = yes, real thing
  3432.     jmp    serin3            ; else try other port kinds
  3433.  
  3434. serin2:    push    bx
  3435.     push    es
  3436.     in    al,21H            ; Interrupt controller
  3437.     mov    savirq,al        ; save state here for restoration
  3438.     or    al,modem.mddis        ; Inhibit IRQ 3 or IRQ 4 
  3439.     out    21H,al
  3440.     mov    al,byte ptr modem.mdintv ; desired interrupt vector
  3441.     mov    ah,35H            ; Int 21H, function 35H = Get Vector
  3442.     int    dos            ; get vector into es:bx
  3443.     mov    word ptr savsci,bx    ; save address offset of original vector
  3444.     mov    word ptr savsci+2,es     ;  and its segment
  3445.     mov    al,byte ptr modem.mdintv ; interrupt number for IRQ 4 or IRQ 3
  3446.     mov    dx,offset serint    ; offset of our interrupt routine
  3447.     push    ds            ; save ds around next DOS call
  3448.     mov    bx,cs            ; compose full address of our routine
  3449.     mov    ds,bx            ; segment is the code segment
  3450.     mov    ah,25H            ; set interrupt address from ds:dx
  3451.     int    dos
  3452.     pop    ds
  3453.     mov    al,rs232        ; interrupt number for Bios serial port
  3454.     mov    ah,35H            ; get vector into es:bx
  3455.     int    dos
  3456.     mov    word ptr sav232,bx    ; save offset
  3457.     mov    word ptr sav232+2,es    ; save segment
  3458.     mov    dx,offset serdum    ; offset of our interrupt routine
  3459.     push    ds            ; save ds around next DOS call
  3460.     mov    bx,cs            ; compose full address of our routine
  3461.     mov    ds,bx            ; segment is the code segment
  3462.     mov    ah,25H            ; set interrupt address from ds:dx
  3463.     int    dos
  3464.     pop    ds
  3465.     pop    es
  3466.     pop    bx
  3467.     mov    portin,1        ; Remember port has been initialized
  3468.     mov    ax,modem.mdstat
  3469.     mov    mst,ax            ; Use this address for status
  3470.     mov    ax,modem.mddat
  3471.     mov    mdat,ax            ; Use this address for data
  3472.     mov    ax,modem.mdiir
  3473.     mov    miir,ax            ; uart interrupt ident register
  3474.     cli                ; Disable interrupts
  3475.     cld                ; Do increments in string operations
  3476.     mov    al,modem.mdmeoi
  3477.     mov    mdeoi,al        ; Use to signify end-of-interrupt
  3478.     in    al,21H            ; Set up 8259 interrupt controller
  3479.     and    al,modem.mden    ; Enable INT3 or INT4. (bit=0 means enable)
  3480.     out    21H,al            ; rewrite interrupt mask byte
  3481.     mov    dx,modem.mdcom        ; set up serial card Line Control Reg
  3482.     in    al,dx            ; get present settings
  3483.     mov    savlcr,al        ; save them for restoration
  3484.     mov    al,3            ; 8 data bits. DLAB = 0
  3485.     out    dx,al
  3486.     mov    dx,modem.mdiir        ; Interrupt Ident reg (03fah)
  3487.     mov    al,087h    ; 8 byte trigger (80), reset fifos (2/4), Rx fifo(1) 
  3488.     out    dx,al
  3489.     jmp    $+2
  3490.     in    al,dx            ; read back iir
  3491.     and    al,0c0h    ; select BOTH fifo bits: 16550A vs 16550 (bad fifo)
  3492.     cmp    al,0c0h            ; are both fifo enabled bits set?
  3493.     je     serin2b            ; e = yes, rcvr fifo is ok (16550/A)
  3494.     xor    al,al            ; else turn off fifo mode (16550/etc)
  3495.     out    dx,al
  3496. serin2b:mov    dx,modem.mddat       ; data and command port, read and flush any    
  3497.     in    al,dx            ; char in UART's receive buffer
  3498.     inc    dx              ; interrupt enable register 3f9h
  3499.     mov    al,1            ; set up interrupt enable register
  3500.     out    dx,al            ;  for Data Available only
  3501.     jmp    $+2
  3502.     add    dx,3               ; modem control register 3fch
  3503.     mov    al,0bh          ; assert DTR, RTS, not OUT1, and OUT2
  3504.     cmp    dupflg,0        ; full duplex?
  3505.     je    serin2c            ; e = yes
  3506.     mov    al,9h            ; assert DTR, not RTS, not OUT1, OUT2
  3507. serin2c:out    dx,al          ; OUT2 high turns on interrupt driver chip
  3508.     sti              ; Allow interrupts (AFTER next instr)
  3509.     jmp    short serin4        ; finish up
  3510.  
  3511. serin3:    cmp    flags.comflg,'N'    ; NetBios?
  3512.     je    serin3o            ; e = yes
  3513.     cmp    flags.comflg,'O'    ; Opennet Network? (FGR)
  3514.     jne    serin3a            ; ne = no
  3515. serin3o:cmp    pcnet,2            ; already going?
  3516.     je    serin4            ; e = yes
  3517.     call    setnet            ; setup network session and pcnet flag
  3518.     jnc    serin4            ; nc = success
  3519.     ret                ; fail, carry set, leave portin at 0
  3520. serin3a:cmp    flags.comflg,'4'    ; using Bios?
  3521.     ja    serin3b            ; a = no
  3522.     call    chkbios            ; set dl to port, check IBM EBIOS
  3523.     jc    serin4            ; c = not present
  3524.     mov    ah,0f9h            ; do a Regain Control operation
  3525.     int    rs232
  3526.     mov    bx,offset biosbuf    ; receive buffer for EBIOS
  3527.     push    ds
  3528.     pop    es            ; set es:bx to the buffer address
  3529.     mov    cx,biosblen        ; set cx to buffer's length
  3530.     mov    ax,0ff02h        ; set buffered mode for receiving
  3531.     int    rs232
  3532.     mov    ax,0fb03h        ; set outgoing DTR and RTS leads
  3533.     int    rs232
  3534. serin3b:cmp    flags.comflg,'D'    ; DECnet?
  3535.     jne    serin4            ; ne = no
  3536.     cmp    pcnet,2            ; going already?
  3537.     je    serin4            ; e = yes
  3538.     call    chkdec            ; reinit
  3539.     jnc    serin4            ; nc = success
  3540.     ret                ; fail, carry set, leave portin at 0
  3541.  
  3542. serin4:    push    bx
  3543.     mov    bx,portval        ; get port data structure
  3544.     mov    [bx].portrdy,1        ; say the comms port is ready
  3545.     mov    parmsk,0ffh        ; parity mask, assume parity is None
  3546.     cmp    [bx].parflg,parnon    ; is it None?
  3547.     je    serin1            ; e = yes
  3548.     mov    parmsk,07fh        ; no, pass lower 7 bits as data
  3549. serin1:    xor    ax,ax
  3550.     cmp    [bx].floflg,0        ; flow control is off?
  3551.     je    serin1a            ; e = yes
  3552.     mov    ax,[bx].flowc        ; get flow control chars
  3553. serin1a:mov    flowoff,al        ; xoff or null
  3554.     mov    flowon,ah        ; xon or null
  3555.     mov    xofrcv,off        ; clear xoff received flag
  3556.     pop    bx
  3557.     mov    portin,1        ; say initialized
  3558.     clc                ; carry clear for success
  3559.     ret                ; We're done
  3560. SERINI    ENDP
  3561.  
  3562. ; Reset the serial port.  This is the opposite of serini.  Calling
  3563. ; this twice without intervening calls to serini should be harmless.
  3564. ; Moved push/pop es code to do quicker exit before interrupts enabled. [jrd] 
  3565. ; Returns normally.
  3566. ; 22 June 1986 Leave OUT1 low to avoid resetting Hayes 1200B's. [jrd]
  3567. ; 21 Feb 1987 Add support for Bios calls [jrd]
  3568. ; 17 May 1987 Redo for COM3/4 support [jrd]
  3569. ; 9 July 1989 Accomodate 16550/A receiver fifo mode. [jrd]
  3570. SERRST    PROC    NEAR
  3571.     cmp    portin,0        ; Reset already? 
  3572.     jg    srst3            ; g = no
  3573.     clc
  3574.     ret                ; e = yes, l=not used yet, just leave
  3575. srst3:    cmp    flags.comflg,'0'    ; Bios or networks?
  3576.     jb    srst4            ; b = no, real UART
  3577.     jmp    srst1            ; nz = yes (Bios or Net)
  3578. srst4:    push    word ptr savsci        ; save original interrupt owner
  3579.     push    word ptr savsci+2    ; offset and segment
  3580.     mov    word ptr savsci,offset nulint ; redirect to our null routine
  3581.     mov    ax,cs            ; segment of null routine is code
  3582.     mov    word ptr savsci+2,ax
  3583.     xor    cx,cx            ; loop counter
  3584. srst2:    mov    dx,modem.mdstat        ; status register
  3585.     in    al,dx
  3586.     jmp    $+2            ; chip access delay
  3587.     test    al,40h            ; both xmtr output registers empty?
  3588.     loopz    srst2            ; z = no, wait for them a while
  3589.     xor    al,al
  3590.     mov    dx,modem.mdiir        ; modem Interrupt Ident reg (03fah)
  3591.     out    dx,al            ; turn off FIFO mode
  3592.     jmp    $+2
  3593.     dec    dx            ; point at int enable reg 3f9h
  3594.     out    dx,al            ; disable interrupts from this source
  3595.     jmp    $+2            ; let stray interrupts occur now
  3596.     jmp    $+2
  3597.     add    dx,2            ; point at Line Control Register 3fbh
  3598.     mov    al,savlcr        ; saved bit pattern
  3599.     and    al,not 80h        ; force DLAB bit to 0
  3600.     out    dx,al            ; restore line control state
  3601.         ; clear modem's delta status bits and reassert DTR etc
  3602.     inc    dx        ; increment to modem control register 3fch
  3603.     mov    al,03h        ; reassert DTR,RTS,but not OUT1 and not OUT2
  3604.     cmp    dupflg,0        ; full duplex?
  3605.     je    srst2a            ; e = yes
  3606.     xor    cx,cx
  3607.     push    dx            ; save dx around test below
  3608. srst2b:    mov    dx,modem.mdstat        ; modem line status reg
  3609.     in    al,dx            ; read transmitter shift reg empty bit
  3610.     jmp    $+2
  3611.     jmp    $+2
  3612.     jmp    $+2            ; wait for char to be sent
  3613.     test    al,40h            ; is it empty?
  3614.     loopz    srst2b            ; z = no, not yet
  3615.     pop    dx
  3616.     mov    al,1            ; reassert DTR but not RTS, OUT1, OUT2
  3617. srst2a:    out    dx,al        ;  OUT2 low to turn off interrupt drivers
  3618.     jmp    $+2        ; pause, in case stray interrupt is generated
  3619.     jmp    $+2        ; which is more than likely, hence nulint.
  3620.     add    dx,2            ; modem status register 3feh
  3621.     in    al,dx            ; clear status register by reading it
  3622.     jmp    $+2
  3623.     mov    mdmhand,al        ; save here for Show Modem
  3624.     cli                ; Disable interrupts
  3625.     in    al,21H            ; Interrupt controller
  3626.     or    al,modem.mddis        ; Inhibit IRQ 3 or IRQ 4
  3627.     pop    word ptr savsci+2    ; recover original int owner's addr
  3628.     pop    word ptr savsci
  3629.     sti                ; replace original IRQ intrpt vector
  3630.     push    bx
  3631.     mov    al,byte ptr modem.mdintv ; vector number to do
  3632.     mov    dx,word ptr savsci     ; offset part
  3633.     push    ds
  3634.     mov    bx,word ptr savsci+2    ; segment part
  3635.     mov    ds,bx            ; ds:dx has interrupt vector
  3636.     mov    ah,25H            ; set interrupt vector
  3637.     int    dos            ; replaced
  3638.     pop    ds
  3639.     mov    al,rs232    ; Bios serial port interrupt vector to restore
  3640.     mov    dx,word ptr sav232    ; offset part
  3641.     push    ds
  3642.     mov    bx,word ptr sav232+2    ; segment part
  3643.     mov    ds,bx
  3644.     mov    ah,25h            ; set interrupt vector
  3645.     int    dos
  3646.     pop    ds
  3647.     pop    bx
  3648.     cli
  3649.     mov    ah,savirq        ; saved Interrupt state
  3650.     and    ah,modem.mddis        ; pick out our IRQ bit
  3651.     in    al,21h            ; get current intrpt controller state
  3652.     jmp    $+2
  3653.     xor    al,modem.mddis        ; remove our IRQ bit
  3654.     or    al,ah            ; set previous state
  3655.     out    21h,al            ; reset IRQ 3 or 4 to original state
  3656.     sti
  3657.                     ; non-UART processes
  3658. srst1:    cmp    flags.comflg,'4'    ; using Bios?
  3659.     ja    srst6            ; a = no
  3660.     call    chkbios            ; set dl to port, check IBM EBIOS
  3661.     jc    srst6            ; c = not present
  3662.     mov    ah,0f9h            ; do a Regain Control operation
  3663.     int    rs232
  3664. srst1a:    mov    ax,0fd02h        ; see if buffer has chars already
  3665.     int    rs232
  3666.     jcxz    srst1b            ; z = no, ok to reset buffering
  3667.     mov    ah,0fch            ; do receive /nowait to clear buff
  3668.     int    rs232
  3669.     jmp    short srst1a        ; repeat til empty
  3670. srst1b:    mov    bx,offset biosbuf    ; receive buffer for EBIOS
  3671.     push    ds
  3672.     pop    es            ; set es:bx to the buffer address
  3673.     xor    cx,cx            ; set cx to zero to terminate buffering
  3674.     mov    ax,0ff02h        ; reset buffered mode for receiving
  3675.     int    rs232
  3676.     jmp    srst9            ; done
  3677.  
  3678. srst6:    cmp    pcnet,0            ; a network active?
  3679.     je    srst9            ; e = no
  3680.     cmp    flags.comflg,'O'    ; Opennet network? (FGR)
  3681.     je      srst7            ; e = yes
  3682.       cmp    flags.comflg,'N'    ; NetBios network?
  3683.       jne    srst9            ; ne = no
  3684. srst7:    cmp    rposted,0        ; receive outstanding?
  3685.     je    srst9            ; e = no
  3686.     mov    can.scb_baddr,offset rcv ; cancel receives
  3687.     push    bx
  3688.     mov    bx,offset can
  3689.     call    session
  3690.     pop    bx
  3691.     mov    rposted,0        ; clear interlock flag no matter what
  3692. srst9:    mov    portin,0        ; reset flag
  3693.     push    bx
  3694.     mov    bx,portval        ; port data structure
  3695.     mov    [bx].portrdy,0        ; say port is not ready
  3696.     pop    bx
  3697.     clc
  3698.     ret
  3699. SERRST    ENDP
  3700.  
  3701. ; Null interrupt routine, to handle strays
  3702. nulint    proc    near
  3703.     push ax
  3704.     push dx
  3705.     mov al,20h            ; general EOI
  3706.     mov dx,intcon1            ; to 8259 interrupt controller
  3707.     out dx,al            ; clear controller chip
  3708.     pop dx
  3709.     pop ax
  3710.     iret
  3711. nulint    endp
  3712.  
  3713. ; Dummy Interrupt 14H to defeat DOS interference with serial port when CTTY
  3714. ; and Kermit use the port simultaneously. If ports differ then chain DOS to
  3715. ; original Int 14H Bios code. Else return dummy status=ok reports and
  3716. ; Backspace for Read, ignore char for Write.
  3717. ; Entered with AH = function request, AL = char to be sent, DX = com port num
  3718. ; CS is our code segment, DS is DOS's, SS is ours or DOS's, interrupts off.
  3719. ; 25 June 1987 [jrd]
  3720. SERDUM    PROC    FAR
  3721.     push    ds            ; preserve all registers
  3722.     push    ax
  3723.     mov    ax,seg data        ; get our data segment
  3724.     mov    ds,ax
  3725.     mov    al,flags.comflg        ; get port id (COM1 = 1, COM2 = 2)
  3726.     and    al,7            ; use lower three bits
  3727.     dec    al            ; DOS counts COM1 as 0, etc
  3728.     cmp    dl,al        ; referencing same port as Kermit is using?
  3729.     pop    ax            ; recover request parameters
  3730.     jne    serdu1            ; ne = no, chain to Bios routine
  3731.     pop    ds
  3732.     cmp    ah,1            ; send char in al?
  3733.     jb    serdu3            ; b = no, init, return dummy status=ok
  3734.     ja    serdu2            ; a = no, other
  3735.     mov    ah,60h            ; yes, set line status=ok in ah
  3736.     iret
  3737. serdu2:    cmp    ah,2            ; receive char (and wait for it)?
  3738.     jne    serdu3            ; ne = no, return dummy report
  3739.     mov    al,BS            ; yes, return ascii BS to DOS
  3740.     xor    ah,ah            ; ah = errors (none here)
  3741.     iret
  3742. serdu3:    mov    ax,60b0h        ; dummy status report:xmtr empty, CD,
  3743.     iret                ;  DSR, and CTS are on
  3744.  
  3745. serdu1:    pop    tempdum            ; save old ds
  3746.     push    word ptr sav232+2    ; push Bios int 14H handler segment
  3747.     push    word ptr sav232        ; push Bios int 14H handler offset
  3748.     push    tempdum            ; recover old ds
  3749.     pop    ds
  3750.     ret                ; do a ret far (chain to Bios)
  3751. SERDUM    ENDP
  3752.  
  3753. ; Serial port interrupt routine.  This is not accessible outside this
  3754. ; module, handles serial port receiver interrupts.
  3755. ; Revised on 22 May 1986, again 2 August 1986 to run at 38.4kb on PC's.
  3756. ; Srcpnt holds offset, within buffer Source, where next rcv'd char goes.
  3757. ; Count is number of chars now in buffer, and oldest char is srcpnt-count
  3758. ; done modulo size of Source. All pointer management is handled here.
  3759. ; Control-G char substituted for char(s) lost in overrun condition.
  3760. ; Upgraded to read cause of interrupt from interrupt ident reg (accepts only
  3761. ;  data ready), chain to old interrupt if source is not our device.
  3762. ; 9 Feb 1988 Add storage of interrupt cause in intkind. [jrd]
  3763. ; 9 July 1989 Add support for 16550/A 14 char receiver fifo.
  3764.  
  3765. SERINT  PROC  FAR
  3766.     push    ax            ; save registers
  3767.     push    dx            ; 
  3768.     push    ds
  3769.     mov    ax,seg data
  3770.     mov    ds,ax            ; address data segment
  3771.     mov    dx,miir            ; modem interrupt ident reg
  3772.     in    al,dx            ; get interrupt cause
  3773.     mov    intkind,al        ; save cause here
  3774.     test    al,1        ; interrupt available if this bit is zero
  3775.     jz    srintc            ; z = interrupt is from our source
  3776.     pop    tempsci            ;  save old ds
  3777.     pop    dx        ;  clean the stack and prepare for ret far
  3778.     pop    ax        ;  to old int handler (same as a jump there)
  3779.     push    word ptr savsci+2    ; old handler segment
  3780.     push    word ptr savsci        ; old handler offset
  3781.     push    tempsci            ; recover old ds
  3782.     pop    ds
  3783.     ret                ; do far return (chain to old handler)
  3784. srintc:    mov    al,mdeoi        ; allow interrupt controller to run
  3785.     out    intcon1,al        ; Send End-of-Interrupt to 8259
  3786.     test    intkind,4        ; data ready?
  3787.     jnz    srint0a            ; nz = yes, else ignore
  3788. srint0:    sti                ; else turn on interrupts
  3789.     jmp    retint            ;  and exit now (common jump point)
  3790.  
  3791. srint0a:mov    dx,mst            ; Asynch status    port
  3792.     in    al,dx
  3793. srint0b:and    al,mdmover        ; select overrun bit
  3794.     mov    ah,al            ; save it for later
  3795.     mov    dx,mdat
  3796.     in    al,dx            ; read the received character into al
  3797.     mov    dh,al           ; dh = working copy. Check null, flow cntl
  3798.     and    dh,parmsk        ; strip parity temporarily, if any
  3799.     cmp    flowoff,0        ; flow control active?
  3800.     je    srint2            ; e = no
  3801.     cmp    dh,flowoff        ; acting on Xoff?
  3802.     jne    srint1            ; ne = Nope, go on
  3803.     cmp    xofsnt,0        ; have we sent an outstanding XOFF?
  3804.     jne    srint0            ; ne = yes, ignore (possible echo)
  3805.     mov    xofrcv,bufon        ; Set the flag saying XOFF received
  3806.     jmp    srint0            ;  and exit
  3807. srint1:    cmp    dh,flowon        ; acting on Xon?
  3808.     jne    srint2            ; ne = no, go on
  3809.     mov    xofrcv,off        ; Clear the XOFF received flag
  3810.     jmp    srint0            ;  and exit
  3811. srint2:    push    bx            ; save register
  3812.     or    ah,ah            ; overrun?
  3813.     jz    srint2a            ; z = no
  3814.     mov    ah,al            ; yes, save present char
  3815.     mov    al,bell            ; insert control-G for missing char 
  3816. srint2a:mov    bx,srcpnt        ; address of buffer storage slot
  3817.     mov    byte ptr [bx],al       ; store the new char in buffer "source"
  3818.     inc    srcpnt            ; point to next slot
  3819.     inc    bx
  3820.     cmp    bx,offset source + bufsiz ; beyond end of buffer?
  3821.     jb    srint3            ; b = not past end
  3822.     mov    srcpnt,offset source     ; wrap buffer around
  3823. srint3:    cmp    count,bufsiz        ; filled already?
  3824.     jae    srint4            ; ae = yes
  3825.     inc    count            ; no, add a char
  3826. srint4:    or    ah,ah            ; anything in overrun storage?
  3827.     jz    srint4a            ; z = no
  3828.     mov    al,ah            ; recover any recent char from overrun
  3829.     xor    ah,ah            ; clear overrun storage
  3830.     jmp    srint2a            ; yes, go store real second char
  3831. srint4a:pop    bx            ; restore reg
  3832.     mov    dx,mst            ; uart line status register
  3833.     in    al,dx            ; get status
  3834.     test    al,1            ; data ready?
  3835.     jnz    srint0b            ; nz = yes, and preserve al
  3836.     sti                 ; ok to allow interrupts now, not before
  3837.     cmp    count,mntrgh        ; past the high trigger point?
  3838.     jbe    retint            ; be = no, we're within our limit
  3839.     test    xofsnt,bufon        ; Has an XOFF been sent by buffer control?
  3840.     jnz    retint            ; nz = Yes
  3841.     mov    al,flowoff        ; get the flow off char (Xoff or null)
  3842.     or    al,al            ; don't send nul chars
  3843.     jz    retint            ; z = null, nothing to send
  3844.     call    dopar            ; Set parity appropriately
  3845.     mov    ah,al               ; Don't overwrite character with status
  3846.     push    cx            ; save reg
  3847.     xor    cx,cx            ; loop counter
  3848. srint5:    mov    dx,mst            ; Get port status
  3849.     in    al,dx
  3850.     test    al,20H            ; Transmitter ready?
  3851.     jnz    srint6            ; nz = yes
  3852.     jmp    $+2            ; use time, prevent overdriving UART
  3853.     loop    srint5            ; else wait loop, cx times
  3854.      jmp    srint7            ; Timeout
  3855. srint6:    mov    al,ah            ; Now send out the flow control char
  3856.     mov    dx,modem.mddat
  3857.     jmp    $+2
  3858.     out    dx,al
  3859.     mov    xofsnt,bufon       ; Remember we sent an XOFF at buffer level
  3860. srint7:    pop    cx            ; restore reg
  3861. retint:    pop    ds
  3862.     pop    dx
  3863.     pop    ax
  3864.     iret
  3865. SERINT    ENDP
  3866.  
  3867. DTRLOW    PROC    NEAR        ; Global proc to Hangup the Phone or Network
  3868.                 ; by making DTR and RTS low (phone). [jrd]
  3869.     mov    ah,cmline    ; allow text, to be able to display help
  3870.     mov    bx,offset rdbuf        ; dummy buffer
  3871.     mov    dx,offset hnghlp    ; help message
  3872.     call    comnd            ; get a confirm
  3873.     jc    dtrlow3            ; c = failure
  3874.     cmp    flags.comflg,'0'    ; Bios?
  3875.     jb    dtrlow1            ; b = no, UART
  3876.     cmp    flags.comflg,'4'    ; Bios?
  3877.     jbe    dtrlow2            ; be = yes, can't access modem lines
  3878. dtrlow1:call    serhng            ; drop DTR and RTS
  3879.     cmp    taklev,0        ; in a Take file or macro?
  3880.     jne    dtrlow2            ; ne = yes, no message
  3881.     mov    ah,prstr        ; give a nice message
  3882.     mov    dx,offset hngmsg
  3883.     int    dos
  3884. dtrlow2:clc                ; success
  3885. dtrlow3:ret
  3886. DTRLOW    ENDP
  3887.  
  3888. ; Hang up the Phone. Similar to SERRST except it just forces DTR and RTS low
  3889. ; to terminate the connection. 29 March 1986 [jrd]
  3890. ; 5 April 1987 Add 500 millisec wait with lines low before returning. [jrd]
  3891. ; Calling this twice without intervening calls to serini should be harmless.
  3892. ; If network then call nethangup procedure to hangup the session without
  3893. ; losing local name information.
  3894. ; Returns normally.
  3895.  
  3896. serhng    proc    near    ; clear modem's delta status bits and lower DTR & RTS
  3897.     call    serini            ; init port, if not done already
  3898.     mov    al,flags.comflg        ; get kind of port
  3899.     cmp    al,4            ; UART?
  3900.     jbe    shng1            ; be = yes
  3901.     cmp    al,'4'            ; Bios?
  3902.     ja    shng2            ; a = no, networks
  3903.     clc                ; else Bios, no hangup
  3904.     ret
  3905. shng2:    cmp    pcnet,0            ; network operational?
  3906.     je    shng1            ; e = no
  3907.     call    nethangup        ; break the session
  3908.     call    serrst            ; reset port so can be opened again
  3909.     clc
  3910.     ret
  3911. shng1:    call    serrst            ; reset port so serini can set DTR
  3912.     cli                ; Disable interrupts
  3913.     push    ax
  3914.     push    dx
  3915.     mov    dx,modem.mddat        ; serial port base address
  3916.     add    dx,4            ; increment to control register
  3917.     mov    al,08h               ; reassert OUT2, un-assert DTR,RTS,OUT1
  3918.     out    dx,al
  3919.     jmp    $+2
  3920.     add    dx,2            ; increment to modem status register
  3921.     in    al,dx            ; Clear Status reg by reading it
  3922.     sti                ; Enable interrupts
  3923.     mov    ax,500            ; 500 millisec, for pcwait
  3924.     call    pcwait            ; keep lines low for at least 500 millisec
  3925.     pop    dx
  3926.     pop    ax
  3927.     clc
  3928.     ret
  3929. serhng    endp
  3930.  
  3931. code    ends 
  3932.     end
  3933.