home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / ccpm86 / cn8xms.a86 < prev    next >
Text File  |  2020-01-01  |  33KB  |  1,180 lines

  1. ; STARTSYSDEP    ; This is so:
  2. ;               ;     PIP LISTING=86KERMIT.LST[WSSTARTSYSDEP^ZQENDSYSDEP^Z]
  3. ;               ; will work.
  4. ;
  5. ; **************************************************************************
  6. ;
  7. ; This is the i/o support module for the Honeywell MicroSystem Executive
  8. ; Running Concurrent CP/M (COS-86, FTOS)
  9. ;
  10. ;  Mark J. Hewitt  University of Birmingham, UK   August 1985
  11. ;
  12. ;  Port selection is provided between the V24 and TELEX ports.  It is
  13. ;  impractical to extend this to the PRINTER port because both the PRINTER
  14. ;  and KEYBOARD are routed through the same interrupt vector, and the XIOS
  15. ;  code explicitly enables interrupts.  This means that if I hijack the
  16. ;  OS interrupt with what I think is non-reentrant but safe code, and pass
  17. ;  all the keyboard characters to the OS, when it returns, interrupts are
  18. ;  enabled, and havoc follows.  There are three solutions to this, for the
  19. ;  brave of heart:
  20. ;
  21. ;    a) Patch the STI instruction out of the OS image at runtime.
  22. ;    b) Write the Kermit interrupt service routine to be fully re-entrant.
  23. ;    c) Do not bother to provide support for the PRINTER port.
  24. ;
  25. ;  I've chosen solution (c).
  26. ;
  27. ;  The V.24 port uses the full V.24 standard, and it is therefore necessary
  28. ;  to loop back the baud rate clock.  This appears on pin 16 of the D-type
  29. ;  connector.  This should be connected to pins 15 and 17 for normal async.
  30. ;  operation.
  31. ;
  32. ;  A further limitation is that only one Kermit can be run at once, even
  33. ;  though it would appear that two Kermits could be run concurrently to
  34. ;  the two ports.  This is because the ports share the same interrupt vector.
  35. ;
  36. ; **************************************************************************
  37. ;
  38.     CSEG $
  39.  
  40. ; Port base definitions
  41.  
  42. comm    equ    08000h        ; Telex and V24 port i/o base    (7201)
  43. bgen    equ    0E000h        ; Baud Rate Generator            (8253-5)
  44. ictrl    equ    0E400h        ; Interrupt Controller           (8259A)
  45.  
  46. ; And the I/O ports themselves
  47.  
  48. bgcmd    equ    bgen+6        ; Baud rate generator command port
  49.  
  50. iccmd    equ    ictrl+0        ; Interrupt controller command port
  51. icmask    equ    ictrl+2        ; Interrupt controller mask register port
  52.  
  53. tlxcmd    equ    comm+4        ; Telex command port
  54. tlxbg    equ    bgen+4        ; Baud rate countdown value for telex port
  55. tlxio    equ    comm+0        ; Telex data io port
  56.  
  57. v24cmd    equ    comm+6        ; V24 command port
  58. v24bg    equ    bgen+2        ; Baud rate countdown value for v24 port
  59. v24io    equ    comm+2        ; V24 data io port
  60. ;
  61. ; Port selection
  62. ;
  63. ptlx    equ    0        ; Telex port selected
  64. pv24    equ    1        ; V.24 port selected
  65.  
  66. ;
  67. ; Interrupt vectors in page 0
  68. ;
  69. ivcomm    equ    0100h        ; 0:x interrupt vector for Telex and V.24
  70. ;
  71. ; Interrupt masks
  72. ;
  73. imcomm    equ    01h        ; mask for Telex/V.24 interrupts
  74. imnet    equ    02h        ; mask for network interrupt
  75. imfdc    equ    04h        ; mask for floppy disc controller interrupt
  76. imbus    equ    08h        ; mask for expansion bus interrupt
  77. imwdc    equ    10h        ; mask for winchester disc controller int.
  78. imxxx    equ    20h        ; not used
  79. imfrl    equ    40h        ; mask for frame reference latch interrupt
  80. imprt    equ    80h        ; mask for printer and keyboard interrupts
  81. ;
  82. ;  Baud rate generator command words
  83. ;
  84. tlxbsel    equ    0B6h        ; select telex baud rate register
  85. v24bsel    equ    76h        ; select V.24 baud rate register
  86. ;
  87. ;  Interrupt controller commands
  88. ;
  89. iceoi    equ    20h        ; end of interrupt
  90. ;
  91. ;  I/O register bits
  92. ;
  93. ;  For communications (Telex and V.24) ports
  94. ;
  95. ccreg0    equ    00h        ; Control instruction - select register 0
  96. ccreg1    equ    01h        ; Control instruction - select register 1
  97. ccreg2    equ    02h        ; Control instruction - select register 2
  98. ccreg3    equ    03h        ; Control instruction - select register 3
  99. ccreg4    equ    04h        ; Control instruction - select register 4
  100. ccreg5    equ    05h        ; Control instruction - select register 5
  101. ccreg6    equ    06h        ; Control instruction - select register 6
  102. ccreg7    equ    07h        ; Control instruction - select register 7
  103.  
  104. c0null    equ    00h        ; Register 0 - null command
  105. c0abort    equ    08h        ; Register 0 - send abort
  106. c0resi    equ    10h        ; Register 0 - reset ext. status ints.
  107. c0chrst    equ    18h        ; Register 0 - channel reset
  108. c0eninc    equ    20h        ; Register 0 - enable int. on next character
  109. c0rpti    equ    28h        ; Register 0 - reset pending tx int./DMA req.
  110. c0errst    equ    30h        ; Register 0 - error reset
  111. c0eoi    equ    38h        ; Register 0 - end of interrupt
  112. c0rxcrc    equ    40h        ; Register 0 - reset rx CRC checker
  113. c0txcrc    equ    80h        ; Register 0 - reset tx CRC generator
  114. c0ricrc    equ    0C0h        ; Register 0 - reset idle/CRC latch
  115.  
  116. c1stien    equ    01h        ; Register 1 - external/status int enable
  117. c1txien    equ    02h        ; Register 1 - transmitter interrupt enable
  118. c1cav    equ    03h        ; Register 1 - condition affects vector
  119. c1noi    equ    00h        ; Register 1 - no rx or DMA interrupts
  120. c1i1st    equ    08h        ; Register 1 - int. on 1st received character
  121. c1iall    equ    10h        ; Register 1 - int. on all received characters
  122. c1ialp    equ    18h        ; Register 1 - int on all rx'd chars, no parity
  123. c1wrxtx    equ    20h        ; Register 1 - WAIT on rx/tx
  124. c1txbcm    equ    40h        ; Register 1 - TX byte count mode enbable
  125. c1wten    equ    80h        ; Register 1 - WAIT function enable
  126. ;
  127. ;  and some useful abbreviations
  128. ;
  129. c1norm    equ    c1ialp
  130. ;
  131. c2dma0    equ    00h        ; Register 2 - No DMA
  132. c2dma1    equ    01h        ; Register 2 - DMA mode 1
  133. c2dma2    equ    02h        ; Register 2 - DMA mode 2
  134. c2dma3    equ    03h        ; Register 2 - DMA mode 3
  135. c2pri    equ    04h        ; Register 2 - Set DMA priority
  136. c2ack0    equ    00h        ; Register 2 - Int. Ack. mode 0 (NV,D432)
  137. c2ack1    equ    08h        ; Register 2 - Int. Ack. mode 1 (NV, D432)
  138. c2ack2    equ    10h        ; Register 2 - Int. Ack. mode 2 (NV, D210)
  139. c2ack4    equ    20h        ; Register 2 - Int. Ack. mode 4 (8085 master)
  140. c2ack5    equ    28h        ; Register 2 - Int. Ack. mode 5 (8085 slave)
  141. c2ack6    equ    30h        ; Register 2 - Int. Ack. mode 6 (8086)
  142. c2ack7    equ    38h        ; Register 2 - Int. Ack. mode 7 (8085/8259A slave)
  143. c2rxim    equ    40h        ; Register 2 - rx interrupt mask
  144. c2syncb    equ    80h        ; Register 2 - pin 10 ~RTSB or ~SYNCB
  145.  
  146. c3rxen    equ    01h        ; Register 3 - receive enable
  147. c3scli    equ    02h        ; Register 3 - sync character load inhibit
  148. c3asm    equ    04h        ; Register 3 - address search mode
  149. c3rxcrc    equ    08h        ; Register 3 - receiver CRC enable
  150. c3hunt    equ    10h        ; Register 3 - enter hunt phase
  151. c3aen    equ    20h        ; Register 3 - auto enables on DCD/CTS
  152. c3r5bit equ    00h        ; Register 3 - 5 bit data
  153. c3r6bit equ    40h        ; Register 3 - 6 bit data
  154. c3r7bit equ    80h        ; Register 3 - 7 bit data
  155. c3r8bit equ    0C0h        ; Register 3 - 8 bit data
  156. ;
  157. ;  and some useful abbreviations
  158. ;
  159. c3norm    equ    c3rxen+c3r8bit
  160. ;
  161. c4pen    equ    01h        ; Register 4 - parity enable
  162. c4ep    equ    02h        ; Register 4 - even parity
  163. c41stp    equ    04h        ; Register 4 - 1 stop bit
  164. c415stp    equ    08h        ; Register 4 - 1.5 stop bits
  165. c42stp    equ    0C0h        ; Register 4 - 2 stop bits
  166. c48syn    equ    00h        ; Register 4 - 8 bit internal sync (monosync)
  167. c416syn    equ    10h        ; Register 4 - 16 bit internal sync (bisync)
  168. c4sdlc    equ    20h        ; Register 4 - SDLC
  169. c4exts    equ    30h        ; Register 4 - External sync
  170. c41clk    equ    00h        ; Register 4 - 1x clock rate
  171. c416clk    equ    40h        ; Register 4 - 16x clock rate
  172. c432clk    equ    80h        ; Register 4 - 32x clock rate
  173. c464clk    equ    0C0h        ; Register 4 - 64x clock rate
  174. ;
  175. ;  and some useful abbreviations
  176. ;
  177. c4norm    equ    c41stp+c416clk
  178. ;
  179. c5txcrc    equ    01h        ; Register 5 - transmitter CRC enable
  180. c5rts    equ    02h        ; Register 5 - request to send
  181. c5poly    equ    04h        ; Register 5 - CRC polynomial select
  182. c5txen    equ    08h        ; Register 5 - transmitter enable
  183. c5sbrk    equ    10h        ; Register 5 - send break
  184. c5t5bit    equ    00h        ; Register 5 - transmit 5 bit data
  185. c5t6bit    equ    20h        ; Register 5 - transmit 6 bit data
  186. c5t7bit    equ    40h        ; Register 5 - transmit 7 bit data
  187. c5t8bit    equ    60h        ; Register 5 - transmit 8 bit data
  188. c5dtr    equ    80h        ; Register 5 - data terminal ready
  189. ;
  190. ;  and some useful abbreviations
  191. ;
  192. c5norm    equ    c5rts+c5txen+c5t8bit+c5dtr
  193. ;
  194. cs0rxr    equ    01h        ; Status register 0 - received char ready
  195. cs0ip    equ    02h        ; Status register 0 - interrupt pending
  196. cs0tbe    equ    04h        ; Status register 0 - tx buffer empty
  197. cs0dcd    equ    08h        ; Status register 0 - data carrier detect
  198. cs0sync    equ    10h        ; Status register 0 - sync status
  199. cs0cts    equ    20h        ; Status register 0 - clear to send
  200. cs0idle    equ    40h        ; Status register 0 - idle CRC latch status
  201. cs0brk    equ    80h        ; Status register 0 - break detect
  202.  
  203. cs1sent    equ    01h        ; Status register 1 - all sent
  204. cs1sdlc    equ    0Eh        ; Status register 1 - SDLC residue code
  205. cs1pe    equ    10h        ; Status register 1 - parity error
  206. cs1oe    equ    20h        ; Status register 1 - overrun error
  207. cs1fe    equ    40h        ; Status register 1 - framing error
  208. cs1eosf    equ    80h        ; Status register 1 - end of SDLC frame
  209. ;
  210. ; System Calls
  211. ;
  212. p_dispatch    equ    8Eh    ; Reschedule in Concurrent CP/M
  213. f_errmode    equ    2dh    ; Set BDOS error mode
  214. p_pdadr        equ    9Ch    ; Get current process's descriptor (PD)
  215. s_sysdat    equ    9Ah    ; Get address of system data segment
  216. p_termcpm    equ    0    ; return to Concurrent CP/M
  217. c_wrtstr    equ    9    ; write a string to console
  218. ;
  219. ;  Process management equates
  220. ;
  221. pnoff    equ    8        ; offset of process name into PD
  222. pnlen    equ    8        ; length of process name in PD
  223. pcns    equ    20h        ; offset to process console in PD
  224. thrdrt    equ    72h        ; Offset to thread list root in system data
  225. thread    equ    2        ; Offset to thread list pointer in PD
  226. ;
  227. ; Clock rate *10 for timing loops    ;[19g]
  228. ;
  229. clckrt    equ    80            ;[19g]  8.0 Mhz
  230. ;
  231. ;  Maximum number of examinations of output port to be ready before
  232. ;  rescheduling.
  233. ;
  234. outlmt    equ    1000h
  235.  
  236. ;
  237. ;  The executable code starts here
  238. ;
  239. ;
  240. ; ===========================================================================
  241. ;
  242. ;                        INITIALISATION ROUTINES
  243. ;
  244. ; ===========================================================================
  245. ;
  246. ; INTERFACE ROUTINE SERINI - Initialisation code
  247. ;
  248. serini:    cmp    mninit, true    ; Ensure that we only initialise once
  249.     je    serin2
  250.     mov    mninit, true
  251. ;
  252. ;  Now check that only one invokation of Kermit exists, and abort if we
  253. ;  were not there first - too many frogs spoil the pond!
  254. ;
  255.     call    setname        ; set my own process name
  256.     call    onlychk        ; ensure we are the only Kermit
  257. ;
  258. ;  Initialise the screen
  259. ;
  260.     call    toansi        ; configure the screen in ANSI mode
  261.     call    clrscr        ; clear the screen in ANSI mode.
  262. ;
  263. ;  Disable I/O interrupts, and save the old interrupt mask.
  264. ;
  265.     mov    dx, icmask    ; read the current interrupt mask
  266.     in    al, dx
  267.     mov    oldmsk, al    ; and save it
  268.     or    al, imcomm    ; mask off i/o interrupts
  269.     out    dx, al        ; and reprogram interrupt controller
  270. ;
  271. ;  Save the system i/o interrupt vectors
  272. ;
  273.     mov    ax, ds        ; save the data segment in code segment
  274.     mov    cs:mndseg, ax    ;   for use by interrupt handler
  275.  
  276.     mov    ax, 0        ; point to zero page and save both the
  277.     mov    es, ax        ;   system's i/o interrupt vectors
  278.     mov    ax,es:.ivcomm+0    ;     for the V.24/Telex channel
  279.     mov    vscoff, ax
  280.     mov    ax, es:.ivcomm+2
  281.     mov    vscseg, ax
  282. ;
  283. ;  Configure the default port
  284. ;
  285.     mov    ax, 0        ; point to zero page and set the interrupt
  286.     mov    es, ax        ;   vector for the V.24/Telex channel to my
  287.                 ;     interrupt service routine
  288.     mov    ax, offset isr    ; set offset address
  289.     mov    es:.ivcomm+0, ax
  290.     mov    ax, cs        ; set segment address
  291.     mov    es:.ivcomm+2, ax
  292.  
  293.     call    setmode        ; set UART mode for current port
  294.     call    setbaud        ; set the baud rate for the current port
  295.     call    mnflush        ; flush and enable the current port
  296.     call    inton        ; turn interrupts on for current port
  297. ;
  298. ;  set BDOS error mode
  299. ;
  300.     mov    cl, f_errmode
  301.     mov    dl, 0FEh    ; return and display mode
  302.     int    bdos
  303.  
  304. serin2:    ret            ; initialisation over
  305. ;
  306. ; INTERNAL ROUTINE SETNAME - set the name of my process
  307. ;                            This is to ensure that all invokations of
  308. ;                            Kermit have the same name, and thus we can
  309. ;                            make certain that only one is running.
  310. ;
  311. setname:mov    cl, p_pdadr    ; get the address of my process descriptor
  312.     int    bdos
  313.     mov    pd_seg, es    ; and save it
  314.     mov    pd_off, ax
  315.     add    bx, pnoff    ; offset into PD of process name field
  316.     mov    si, offset myname
  317.     mov    di, bx
  318.     mov    cx, pnlen    ; length of process name
  319.     cld
  320.     rep movsb        ; move the process name
  321.     ret
  322. ;
  323. ;  INTERNAL ROUTINE ONLYCHK - ensure that the current process is the only
  324. ;                             incarnation running.  Only return if we are
  325. ;                             alone (In space, no-one can hear you scream)
  326. ;
  327. onlychk:pushf            ; this must be done with interrupts off
  328.     cli
  329.     mov    cl, s_sysdat    ; get address of system data segment
  330.     int    bdos
  331.     mov    bx, es:word ptr thrdrt[bx]    ; address of root of thread list
  332. ;
  333. ;  Loop through the thread list, looking for processes with the same name
  334. ;  and differently addressed process dcescriptors to the current one
  335. ;
  336.     cld
  337. oc001:    push    bx
  338.     push    es
  339.     mov    si, offset myname    ; compare the names
  340.     add    bx, pnoff        ; point at name on thread list
  341.     mov    di, bx
  342.     mov    cl, pnlen
  343.     repz cmpsb            ; perform the comparison
  344.     pop    es            ; restore regs - does not alter flags
  345.     pop    bx
  346.     jz    oc002            ; may be myself
  347. oc003:    mov    bx, es:word ptr thread[bx]    ; next process on thread list
  348.     cmp    bx, 0            ; null terminated thread list
  349.     jne    oc001
  350.     popf
  351.     ret                ; return through here if we are alone
  352.  
  353. oc002:    cmp    bx, pd_off        ; check if we have found ourselves
  354.     jz    oc003            ; we have - this is OK!
  355.     
  356.     mov    dx, offset frogXn    ; another kermit exists - abort
  357.     mov    cl, c_wrtstr        ; ... prettily
  358.     mov    al, es:byte ptr pcns[bx]    ; the console of other Kermit
  359.     popf                ; restore interrupt status
  360.     add    al, '0'
  361.     mov    okcons, al
  362.     int    bdos
  363. oc004:    mov    cl, p_termcpm        ; and exit
  364.     int    bdos
  365.     jmp    oc004            ; just in case
  366.  
  367.     DSEG    $        ; Data used for process management
  368.  
  369. pd_seg    rw    1        ; segment containing current process descriptor
  370. pd_off    rw    1        ; offset of current process descriptor
  371. myname    db    'Kermit86'    ; Name that current process will be known by
  372. frogXn    db    'Another Kermit is running on console '
  373. okcons    db    1        ; console of other kermit
  374.     db    cr, lf, '$'
  375.  
  376.     CSEG    $
  377.  
  378. ;
  379. ; INTERFACE ROUTINE SERFIN - restore environment (as far as possible)
  380. ;                            to that which existed before we played with it
  381. ;
  382. serfin:    cmp    mninit, true    ; only deinitialise if necessary
  383.     jne    serfn2
  384.     mov    mninit, false
  385. ;
  386. ;  Disable i/o interrupt while we reset the vectors
  387. ;
  388.     mov    dx, icmask    ; get present interrupt mask
  389.     in    al, dx        ; and turn off all i/o interrupts
  390.     or    al, imcomm    ;   from the V.24/Telex channel
  391.     out    dx, al        ; reprogram the interrupt controller
  392. ;
  393. ;  Reset the i/o interrupt vectors
  394. ;
  395.     mov    ax, 0        ; point at page 0 and reset the int. vectors
  396.     mov    es, ax
  397.     mov    ax, vscoff    ;   for the V.24/Telex port
  398.     mov    es:.ivcomm+0, ax
  399.     mov    ax, vscseg
  400.     mov    es:.ivcomm+2, ax
  401. ;
  402. ; turn interrupts back on (or off...)
  403. ;
  404.     mov    al, oldmsk    ; restore original interrupt mask
  405.     out    dx, al
  406. ;
  407. ;  Reset screen modes
  408. ;
  409.     call    clrscr        ; be tidy - clear the screen
  410.     call    toft        ; reset screen to FT mode
  411.  
  412. serfn2:    ret            ; deinitialisation over
  413.  
  414. ;
  415. ; INTERNAL ROUTINE TOANSI - configure screen in ANSI mode
  416. ;
  417. toansi:    mov    dx, offset ansion
  418.     call    tmsg
  419.     ret
  420. ;
  421. ;  INTERNAL ROUTINE TOFT - configure screen in FT mode
  422. ;
  423. toft:    mov    dx, offset fton
  424.     call    tmsg
  425.     ret
  426. ;
  427. ; INTERNAL ROUTINE SETMODE - set the operating mode for current port's UART.
  428. ;                            Port number in cport,
  429. ;                            Current UART command port in ccmdp.
  430. ;
  431. setmode:
  432.     push    ax
  433.     push    dx        ; we'll need this
  434.  
  435.     mov    dx, ccmdp    ; current command port for UART
  436.  
  437.     cmp    cport, ptlx    ; is it the Telex port?
  438.     je    smcomm
  439.     cmp    cport, pv24    ; is it the V.24 port?
  440.     jne    setmo2        ; must be an error - just return for now
  441.  
  442. smcomm:                ; set UART modes for the Telex/V.24 port
  443.     mov    al, c0chrst    ; reset the port
  444.     out    dx, al
  445.     mov    al, c0resi+ccreg4 ; select register 4
  446.     out    dx, al
  447.     mov    al, c4norm    ; 16x Clock, 1 stop bit, no parity
  448.     out    dx, al
  449.     mov    al, c0resi+ccreg3 ; Select register 3
  450.     out    dx, al
  451.     mov    al, c3norm    ; 8 bits/character, RX enable
  452.     out    dx, al
  453.     mov    al, c0resi+ccreg5 ; select register 5
  454.     out    dx, al
  455.     mov    al, c5norm    ; 8 bits/character, TX enable RTS and DTR
  456.     out    dx, al
  457.     mov    al, c0resi+ccreg1 ; select register 1
  458.     out    dx, al
  459.     mov    al, c1norm    ; Interrupt enable
  460.     out    dx, al
  461.     
  462. setmo2:    pop    dx        ; modes now set, restore regs. and return
  463.     pop    ax
  464.     ret
  465.  
  466. ;
  467. ;  INTERNAL ROUTINE SETBAUD - set the baud rate of a current port.
  468. ;                             port number in cport.
  469. ;                             timer countdown table offset in cbaud.
  470. ;
  471. setbaud:
  472.     push    bx        ; we'll be using this
  473.     push    dx        ; and this
  474.     push    ax        ; and this too
  475.  
  476.     mov    al, bdtab    ; check that rate is legal
  477.     dec    al        ; pick up number of valid rates from BDTAB
  478.     cmp    cbaud, al    ;  0 <= cbaud <= [bdtab]-1
  479.     ja    setbd2        ; just return if not legal
  480.  
  481.     mov    bx, offset bdtct    ; get timer value
  482.     mov    al, cbaud        ; from timer countdown table
  483.     mov    ah, 0
  484.     add    al, al        ; word offset
  485.     add    bx, ax        ; bx now points to correct value
  486.  
  487.     mov    dx, bgcmd    ; dx is now baud rate generator command port
  488.  
  489.     cmp    cport, ptlx    ; is it the telex port?
  490.     je    sbtlx
  491.     cmp    cport, pv24    ; is it the v24 port?
  492.     jne    setbd2        ; just return if not
  493.  
  494.     mov    al, v24bsel    ; set baud rate for v24 port
  495.     out    dx, al
  496.     mov    dx, v24bg
  497.     jmp    setbd3
  498.  
  499. sbtlx:    mov    al, tlxbsel    ; set baud rate for telex port
  500.     out    dx, al
  501.     mov    dx, tlxbg
  502.  
  503. setbd3:    mov    ax, [bx]    ; set the countdown value
  504.     out    dx, al
  505.     mov    al, ah
  506.     out    dx, al
  507.  
  508. setbd2:    pop    ax        ; baud rate set, retore regs. and return
  509.     pop    dx
  510.     pop    bx
  511.     ret
  512.  
  513. ;
  514. ;  INTERNAL ROUTINE MNFLUSH - enable and flush current port.
  515. ;                             Port in cport.
  516. ;
  517. mnflush:
  518.     push    ax        ; preserve registers
  519.     push    dx
  520.  
  521.     mov    dx, ciop    ; current io port
  522.     in    al, dx        ; flush the port
  523.     in    al, dx
  524.     in    al, dx
  525.     mov    dx, ccmdp    ; reset any pending interrupts
  526.     mov    al, c0errst
  527.     out    dx, al
  528.     mov    al, c0resi
  529.     out    dx, al
  530.  
  531.     pop    dx        ; port flushed, retore regs. and return
  532.     pop    ax
  533.     ret
  534.  
  535. ;
  536. ; INTERNAL ROUTINE INTON - enable interrupts for the selected port
  537. ;                          Port number in cport.
  538. ;                          Ensure that the port selected is enabled, and
  539. ;                          that all other ports are as the system would
  540. ;                          wish them!
  541. inton:    push    ax
  542.     push    dx
  543.  
  544.     mov    dx, icmask
  545.     mov    al, oldmsk    ; Disable i/o interrupts from the V24/Telex
  546.     or    al, imcomm    ;   channel.
  547.     out    dx, al
  548.  
  549.     cmp    cport, ptlx    ; is it the Telex port?
  550.     je    ietlx
  551.     cmp    cport, pv24    ; is it the V.24 port?
  552.     jne    inton2        ; must be an error - just return for now
  553.  
  554.     mov    dx, tlxcmd    ; disable ints from Telex port
  555.     jmp    iecomm
  556.  
  557. ietlx:    mov    dx, v24cmd    ; disable ints from V.24 port
  558.  
  559. iecomm:    mov    al, c0resi+ccreg1
  560.     out    dx, al
  561.     mov    al, c1norm and not c1ialp
  562.     out    dx, al
  563.  
  564.     mov    dx, icmask
  565.     and    al, not imcomm    ; enable Telex and V.24 interrupts
  566.     out    dx, al
  567.  
  568. inton2:    pop    dx
  569.     pop    ax        ; interrupts now enabled - restore regs.
  570.     ret            ;   and return
  571.  
  572.     DSEG $            ; Data used by initialisation/deinitialisation
  573.  
  574. mninit    db    false        ; flag set when initialised
  575. oldmsk    rb    1        ; Old interrupt mask
  576. ;
  577. ;  Screen mode control strings
  578. ;
  579. ansion    db    esc, '[$'    ; enter ANSI mode
  580. fton    db    esc, 'Q$'    ; re-enter FT mode
  581. ;
  582. ;  Current port status
  583. ;
  584. cport    db    ptlx        ; current port number - default to TELEX
  585. cbaud    db    8        ; current baud rate - default to 4800
  586. ciop    dw    tlxio        ; current i/o port - default to TELEX
  587. ccmdp    dw    tlxcmd        ; current command/status port - default TELEX
  588. ;
  589. ;  Storage for system interrupt vectors
  590. ;
  591. vscoff    rw    1        ; offset for system v.24/telex int. vector
  592. vscseg    rw    1        ; seg. address for system v.24/telex int. vec
  593. ;
  594. ;  Baud rate timer countdown table
  595. ;
  596. bdtct    dw    769        ;    50 baud, code  0, +0.03% error
  597.     dw    513        ;    75             1  -0.04%
  598.     dw    350        ;   110             2  -0.10%
  599.     dw    256        ;   150             3  +0.16%
  600.     dw    128        ;   300             4  +0.16%
  601.     dw     64        ;   600             5  +0.16%
  602.     dw     32        ;  1200             6  +0.16%
  603.     dw     16        ;  2400             7  +0.16%
  604.     dw      8        ;  4800             8  +0.16%
  605.     dw      4        ;  9600             9  +0.16%
  606.     dw      2        ; 19200            10  +0.16%
  607.  
  608.     CSEG $
  609.  
  610. ; ===========================================================================
  611. ;
  612. ;                             SET COMMANDS
  613. ;
  614. ; ===========================================================================
  615. ;
  616. ;  INTERFACE ROUTINE BDSET - set baud rate for current port (cport).
  617. ;                            save current baud rate in cbaud.
  618. ;
  619. bdset:    mov    dx, offset bdtab    ; table of valid baud rates
  620.     mov    bx, offset bdhlp    ; help information for SET BAUD
  621.     mov    ah, cmkey        ; Command parser - KEYWORD lookup
  622.     call    comnd
  623.       jmp    r            ; error return
  624.     mov    settmp, bx        ; Normal return - save value
  625.     mov    ah, cmcfm        ; Command parser - CONFIRM
  626.     call comnd
  627.       jmp    r
  628.     mov    bx, settmp
  629.     mov    cbaud, bl        ; save the baud rate
  630.     call    setbaud            ; and set it for the current port
  631.     jmp    rskp            ; end of parsing SET BAUD command
  632.  
  633.     DSEG $
  634.  
  635. settmp    rw    1            ; temporary storage for baud rate
  636.  
  637.     CSEG $
  638. ;
  639. ;  INTERFACE ROUTINE PRTSET - set the current port.
  640. ;
  641. prtset:    mov    dx, offset potab    ; table of valid port names
  642.     mov    bx, offset pohlp    ; help information for SET PORT
  643.     mov    ah, cmkey        ; Command parser - KEYWORD lookup
  644.     call    comnd
  645.       jmp    r            ; error return
  646.  
  647.     mov    settmp, bx        ; Normal return - save value
  648.  
  649.     mov    ah, cmcfm        ; Command parser - CONFIRM
  650.     call comnd
  651.       jmp    r
  652. ;
  653. ;  Now we can do the work - first preset a few registers
  654. ;
  655.     mov    bx, settmp        ; restore port number
  656.     mov    dx, ccmdp        ; current command port
  657.     mov    al, c0resi+ccreg1    ; and command to select register 1
  658. ;
  659. ;  establish which port we are to use
  660. ;
  661.     cmp    bl, ptlx        ; is it the Telex port?
  662.     je    settlx
  663.     cmp    bl, pv24        ; is it the V.24 port?
  664.     je    setv24
  665.     jmp    r            ; must've been an error
  666. ;
  667. ;  Set the current port to be the V.24 connector
  668. ;
  669. setv24:    out    dx, al            ; disable interrupts from current port
  670.     mov    al, c1norm and not c1ialp
  671.     out    dx, al
  672.     mov    ciop, v24io        ; Set V.24 port
  673.     mov    ccmdp, v24cmd
  674.     jmp    prtdoit
  675. ;
  676. ;  Set the current port to be the Telex port
  677. ;    
  678. settlx:    out    dx, al            ; disable interrupts from current port
  679.     mov    al, c1norm and not c1ialp
  680.     out    dx, al
  681.     mov    ciop, tlxio        ; Set Telex port
  682.     mov    ccmdp, tlxcmd
  683. ;
  684. ; and actually configure it
  685. ;
  686. prtdoit:mov    cport, bl        ; save the current port
  687.     call    setmode            ; configure the selected UART
  688.     call    setbaud            ; set the port's baud rate
  689.     call    mnflush            ; flush it
  690.     call    inton            ; and enable interrupts for it
  691.     jmp    rskp            ; end of parsing SET PORT command
  692. ;
  693. ;  Data required by the SET commands
  694. ;
  695.     DSEG $                ; SET command data
  696. ;
  697. ;  Baud rate table
  698. ;
  699. bdtab    db    11            ; number of entries
  700.     db    3, '110$'        ; size of entry, and the keyword$
  701.     dw    02            ; value returned
  702.     db    3, '150$'
  703.     dw    03
  704.     db    4, '1200$'
  705.     dw    06
  706.     db    5, '19200$'
  707.     dw    10
  708.     db    4, '2400$'
  709.     dw    07
  710.     db    3, '300$'
  711.     dw    04
  712.     db    4, '4800$'
  713.     dw    8
  714.     db    2, '50$'
  715.     dw    00
  716.     db    3, '600$'
  717.     dw    05
  718.     db    2, '75$'
  719.     dw    01
  720.     db    4, '9600$'
  721.     dw    09
  722. ;
  723. ;  Help table for baud rate setting
  724. ;
  725. bdhlp    db    cr, lf, '    50     75    110    150    300    600'
  726.     db    cr, lf, '  1200   2400   4800   9600  19200'
  727.     db    '$'
  728. ;
  729. ;  Port table
  730. ;
  731. potab    db    2
  732.     db    5, 'TELEX$'
  733.     dw    ptlx
  734.     db    3, 'V24$'
  735.     dw    pv24
  736. ;
  737. ;  Help table for port selection
  738. ;
  739. pohlp    db    cr, lf, 'TELEX   V24$'
  740.  
  741.     CSEG $
  742.  
  743. ; ===========================================================================
  744. ;
  745. ;                              SHOW COMMANDS
  746. ;
  747. ; ===========================================================================
  748.  
  749. ;
  750. ;  INTERFACE ROUTINE SHOBD - display the currently set baud rate within
  751. ;                            the SHOW command.
  752. ;
  753. shobd:    mov    dx, offset bdst    ;Baud rate string.
  754.     call    tcrmsg
  755.     mov    al, cbaud    ;Print the keyword corresponding to the
  756.     mov    bx, offset bdtab; current value of mnbaud.
  757.     call    tabprt
  758.     ret
  759.  
  760. ;
  761. ;  INTERFACE ROUTINE SHOPRT - display the currently selected communication
  762. ;                             port within the SHOW command.
  763. ;
  764. shoprt:    mov    dx, offset prtst    ; Port name string
  765.     call    tcrmsg
  766.     mov    al, cport        ; current port code
  767.     mov    bx, offset potab    ; and print the corresponding
  768.     call    tabprt            ;   textual description
  769.     mov    dx, offset prtst2
  770.     call    tmsg
  771.     ret
  772.  
  773.     DSEG $
  774.  
  775. prtst    db    'Communicating via $'
  776. prtst2    db    ' port$'
  777.  
  778.     CSEG $
  779.  
  780. ; ===========================================================================
  781. ;
  782. ;                                I/O ROUTINES
  783. ;
  784. ; ===========================================================================
  785. ;
  786. ;  INTERNAL ROUTINE ISR - Interrupt service routine for Printer, Keyboard,
  787. ;                         Telex and V.24 ports.
  788. ;
  789. isr:    cli                ; disable intrerupts
  790.     mov    cs:mnax, ax        ; save ax - we will need a register
  791.     mov    ax, sp
  792.     mov    cs:mnsp, ax        ; save current stack pointer
  793.     mov    ax, ss
  794.     mov    cs:mnsseg, ax        ; Save current stack segment
  795.     mov    ax, cs:mndseg        ; Switch to my stack
  796.     mov    ss, ax
  797.     mov    sp, offset mnstk
  798.     push    ds            ; Save registers
  799.     push    es
  800.     push    bp
  801.     push    di
  802.     push    si
  803.     push    dx
  804.     push    cx
  805.     push    bx
  806.     mov    ds, ax            ; set our data segment address
  807. ;
  808. ;  That's the housekeeping out of the way - now we can start
  809. ;
  810.     mov    dx, ccmdp        ; see if char. ready at default port
  811.     in    al, dx
  812.     test    al, cs0rxr        ; is there a character for us?
  813.     jz    iprt3            ; no - clear interrupt, and return
  814.  
  815. iprt2:    mov    dx, ciop        ; fetch the character
  816.     in    al, dx
  817.     call    iproc            ; process the character in AL
  818.  
  819. iprt3:    mov    dx, iccmd        ; signal end of interrupt to
  820.     mov    al, iceoi        ;   interrupt controller
  821.     out    dx, al
  822.  
  823.     mov    dx, tlxcmd        ; Clear interrupt status at telex/v.24
  824.     mov    al, c0eoi        ;   channel.
  825.     out    dx, al            ; note we use the Telex (A) channel
  826.  
  827.     pop    bx            ; restore registers
  828.     pop    cx
  829.     pop    dx
  830.     pop    si
  831.     pop    di
  832.     pop    bp
  833.     pop    es
  834.     pop    ds
  835.     mov    ax, cs:mnsp        ; restore interrupt stack
  836.     mov    sp, ax
  837.     mov    ax, cs:mnsseg        ; restore original stack segment
  838.     mov    ss, ax
  839.     mov    ax, cs:mnax        ; restore original AX
  840.     iret                ; all over - return
  841.  
  842. ;
  843. ;  CSEG data required by interrupt service routine
  844. ;
  845. mnax    dw    0        ; temp. copy of AX
  846. mnsp    dw    0        ; interrupt stack pointer
  847. mnsseg    dw    0        ; interrupt stack segment
  848. mndseg    dw    0        ; location of our data segment
  849.  
  850. ;
  851. ; INTERNAL ROUTINE IPROC - process incoming character from Rx interrupt
  852. ;                          Character in AL
  853. ;
  854.  
  855. iproc:    cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  856.     jne    ipr2b        ;no - go on
  857.     cmp    al, xoff    ;is it an XOFF?
  858.     jne    ipr2a        ;no - go on
  859.     mov    xofrcv, true    ;set the flag
  860.     ret
  861.  
  862. ipr2a:    cmp    al, xon        ;an XON?
  863.     jne    ipr2b        ;no
  864.     mov    xofrcv, false    ;clear the flag
  865.     ret            ;                [19a] end
  866.  
  867. ipr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  868.     je    iperr        ;If so, take care of the error.
  869.     inc    mnchrn        ;Increment the character count.
  870.     mov    bx,mnchip    ;Get the buffer input pointer.
  871.     inc    bx        ;Increment it.
  872.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  873.     jb    ipro3
  874.     mov    bx, offset mnchrs ;Yes, point to the start again.
  875. ipro3:    mov    mnchip,bx    ;Save the pointer.
  876.     mov    [bx],al        ;Put the character in the buffer.
  877.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  878.     je    ipro4        ;If yes jump
  879.     ret
  880.  
  881. ipro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  882.     jnz    ipro5
  883.     ret            ;return if we have
  884.  
  885. ipro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  886.     ja    ipro6        ;yes - jump
  887.     ret
  888.  
  889. ipro6:    mov    al, xoff
  890.     call    prtout        ;send an XOFF
  891.     mov    xofsnt, true    ;set the flag
  892.     ret            ;                [19a] End
  893.  
  894. iperr:    ret            ; just return on error for now
  895.  
  896. ;
  897. ;  INTERFACE ROUTINE CFIBF - Clear serial port input buffer
  898. ;
  899. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  900.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  901.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  902.     ret
  903.  
  904. ;
  905. ;  INTERFACE ROUTINE PRTOUT - send character in AL to current port.
  906. ;
  907. prtout:    call    dopar        ; set parity if necessary
  908.     push    dx
  909.     push    cx
  910.  
  911.     mov    cx, outlmt
  912. prtou2:    call    outwait        ; wait for port to be free, or timeout
  913.       loop    prtou2
  914.       nop
  915.     call    outchr        ; output the character
  916.     pop    cx
  917.     pop    dx
  918.     ret
  919.  
  920. ;
  921. ; INTERNAL ROUTINE OUTWAIT - test if port ready for next char to be sent.
  922. ;                            returns RSKP if ready.
  923. ;
  924. outwait:
  925.     cmp    floctl, floxon
  926.     jne    outwt1
  927.     cmp    xofrcv, true
  928.     je    outwt3
  929. outwt1:    push    ax
  930.     mov    dx, ccmdp
  931.     in    al, dx
  932.     test    al, cs0tbe
  933.     jnz    outwt4
  934.     pop    ax
  935. outwt3:    call    dispatch
  936.     ret
  937. outwt4:    pop    ax
  938.     jmp    rskp
  939. ;
  940. ;  INTERNAL ROUTINE OUTCHR - send data to a port
  941. ;
  942. outchr:    mov    dx, ciop
  943.     out    dx, al
  944.     ret
  945.  
  946. ;
  947. ; INTERFACE ROUTINE INSTAT - determine if there is any data to receive.
  948. ;
  949. instat:    cmp    mnchrn, 0        ; any characters in buffer?
  950.     jne    inst2
  951.     call    dispatch
  952.     ret
  953. inst2:    jmp    rskp
  954.  
  955. ;
  956. ;  INTERFACE ROUTINE INCHR - read a character from a port
  957. ;
  958. inchr:    push    bx
  959.     cli            ;Disable interrupts while were are playing.
  960.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  961.     mov    bx,mnchop    ;Get the pointer into the buffer.
  962.     inc    bx        ;Increment to the next char.
  963.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  964.     jb    inchr2
  965.     mov    bx, offset mnchrs ;If so wrap around to the start.
  966. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  967.     mov    al,[bx]        ;Get the character.
  968.     sti            ;All done, we can restore interrupts.
  969.     pop    bx
  970.     cmp    parflg,parnon    ;[par] no parity?
  971.     je    inchr3        ;[par] yup, don't bother stripping
  972.     and    al,7fh        ;[par] checking parity, strip off
  973. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  974.     je    inchr4        ;If yes jump
  975.     ret
  976. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  977.     je    inchr5        ;Jump if yes
  978.     ret
  979. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  980.     jb    inchr6        ;yes - jump
  981.     ret
  982. inchr6:    push    ax        ;save current character
  983.     mov    al, xon
  984.     call    prtout        ;send an XON
  985.     mov    xofsnt, false    ;turn off the flag
  986.     pop    ax        ;get back character
  987.     ret            ;                [19a] end
  988.  
  989. ;
  990. ;  INTERFACE ROUTINE PRTBRK - Send a BREAK sequence to the default port
  991. ;
  992. prtbrk:    mov    dx, ccmdp        ; current command port
  993.     cmp    cport, ptlx        ; is it TELEX port?
  994.     je    brkc
  995.     cmp    cport, pv24        ; is it V.24 port?
  996.     jne    brka            ; must be an error - just return
  997.  
  998. brkc:
  999.     mov    al, c0resi+ccreg5    ; break to telex/v24 ports
  1000.     out    dx, al            ; select register 5
  1001.     mov    al, c5norm+c5sbrk    ; 8 bits, TX enable, Break, RTS & DTR
  1002.     out    dx, al
  1003.     mov    ax, 275            ; for 275 mS
  1004.     call    mswait
  1005.     mov    al, c0resi+ccreg5    ; select register 5
  1006.     out    dx, al
  1007.     mov    al, c5norm        ; 8 bits, TX enable, RTS & DTR
  1008.     out    dx, al
  1009.     ret
  1010.  
  1011. brka:    ret
  1012.  
  1013.     DSEG $
  1014. ;
  1015. ;  Input character queue
  1016. ;
  1017. mnchnd    equ    512        ;Size of circular buffer.
  1018. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  1019. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  1020. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  1021. mnchrn    dw    0        ;Number of chars in the buffer.
  1022.  
  1023. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  1024. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  1025.  
  1026. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  1027. xofsnt    db    0        ;[19a] set if XOFF was sent
  1028. xofrcv    db    0        ;[19a] set if XOFF was recieved
  1029. ;
  1030. ;  a small stack for interrupt handling
  1031. ;
  1032.     rw    64        ;Interrupt stack        ;[28e]
  1033. mnstk    dw    0        ;bottom of stack        ;[28e]
  1034.  
  1035.     CSEG $
  1036.  
  1037. ; ===========================================================================
  1038. ;
  1039. ;                             UTILITY ROUTINES
  1040. ;
  1041. ; ===========================================================================
  1042. ;
  1043. ; INTERNAL ROUTINE MSWAIT - Delay for AL milliseconds
  1044. ;
  1045. mswait:                ;                [34] start
  1046.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  1047. mswai1:
  1048.     sub    cx,1        ;** inner loop takes 20 clock cycles
  1049.     jnz    mswai1        ;**
  1050.     dec    ax        ; outer loop counter
  1051.     jnz    mswait        ; wait another millisecond
  1052.     ret            ;                [34] end
  1053.  
  1054. ;
  1055. ; INTERNAL ROUTINE DISPATCH:    Reschedule current process
  1056. ;
  1057. dispatch:
  1058.     push    ax
  1059.     push    bx
  1060.     push    cx
  1061.     mov    cl, p_dispatch
  1062.     int    bdos
  1063.     pop    cx
  1064.     pop    bx
  1065.     pop    ax
  1066.     ret
  1067.  
  1068.  
  1069.  
  1070. ; ===========================================================================
  1071. ;
  1072. ;                        SCREEN CONTROL ROUTINES
  1073. ;
  1074. ; ===========================================================================
  1075. ;
  1076. ; INTERFACE ROUTINE POSCUR - positions cursor to row and col (each 1 byte)
  1077. ;                            pointed to by dx.
  1078. ;
  1079.  
  1080. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  1081.     mov    cl, 10
  1082.     mov    al, [bx]    ;Get row value
  1083.     sub    ah, ah
  1084.     div    cl        ;units digit in ah, tens digit in al
  1085.     add    ax, '00'    ;Convert both to ASCII
  1086.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  1087.     mov    al, 1[bx]    ;Do same for column value
  1088.     sub    ah, ah
  1089.     div    cl
  1090.     add    ax, '00'
  1091.     mov    word ptr anspos+5, ax
  1092.     mov    dx, offset anspos    ;Print cursor positioning string.
  1093.     call    tmsg
  1094.     ret
  1095.  
  1096. ;
  1097. ; INTERFACE ROUTINE CLRSCR - homes cursor and clears screen.
  1098. ;
  1099.  
  1100. clrscr:    mov    dx, offset anscls
  1101.     call    tmsg
  1102.     ret
  1103. ;
  1104. ; INTERFACE ROUTINE CLRLIN - clears line.
  1105. ;
  1106.  
  1107. clrlin:    mov    dl, cr        ;Go to beginning of line
  1108.     call    bout
  1109. ;
  1110. ;    ...FALL THROUGH
  1111. ;
  1112. ;  INTERFACE ROUTINE CLREOL - clear to end of line
  1113. ;
  1114.  
  1115. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  1116.     call    tmsg
  1117.     ret
  1118.  
  1119. ;
  1120. ; INTERFACE ROUTINE REVON - turns on reverse video display
  1121. ;
  1122.  
  1123. revon:    mov    dx, offset ansron
  1124.     call    tmsg
  1125.     ret
  1126.  
  1127. ;
  1128. ; INTERFACE ROUTINE REVOFF - turns off reverse video display
  1129. ;
  1130.  
  1131. revoff:    mov    dx, offset ansrof
  1132.     call    tmsg
  1133.     ret
  1134. ;
  1135. ; INTERFACE ROUTINE BLDON - turns on bold (highlighted) display
  1136. ;
  1137.  
  1138. bldon:    mov    dx, offset ansbon
  1139.     call    tmsg
  1140.     ret
  1141. ;
  1142. ; INTERFACE ROUTINE BLDOFF - turns off bold (highlighted) display
  1143. ;
  1144.  
  1145. bldoff:    mov    dx, offset ansbof
  1146.     call    tmsg
  1147.     ret
  1148.  
  1149.  
  1150.     DSEG $
  1151.  
  1152. anspos    db    esc,'[00;00H$'    ;Position cursor to row and column
  1153. anscls    db    esc, '[H', esc, '[J$'    ;Home cursor and clear screen
  1154. ansclr    db    esc, '[K$'    ;Clear from cursor to end of line
  1155. ansron    db    esc, '[7m$'    ;Turn on reverse video
  1156. ansrof    db    esc, '[m$'    ;Turn off reverse video
  1157. ansbon    db    esc, '[1m$'    ; Bold on
  1158. ansbof    db    esc, '[m$'    ; Bold off
  1159.  
  1160.     CSEG $
  1161. ;
  1162. ; INTERFACE ROUTINE DOTAB - do tab expansion if necessary
  1163. ;
  1164. dotab:    jmp    rskp        ; assume h/w does it for now
  1165.  
  1166. ;
  1167. ;  Assorted textual constants required as part of the machine interface
  1168. ;
  1169.     DSEG $
  1170.  
  1171. delstr  db    10O,'$'        ;Delete string.
  1172. system    db    '  Honeywell microSystem-eXecutive [mjh] Concurrent$'
  1173.  
  1174.     CSEG $
  1175. ;
  1176. ; ENDSYSDEP
  1177. ;
  1178.  
  1179.  
  1180.