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

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