home *** CD-ROM | disk | FTP | other *** search
/ Phoenix CD 2.0 / Phoenix_CD.cdr / 01e / msk230s2.zip / MSXIBM.ASM < prev    next >
Assembly Source File  |  1988-02-12  |  152KB  |  3,083 lines

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