home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / cpm86 / c86xap.a86 < prev    next >
Text File  |  2020-01-01  |  19KB  |  744 lines

  1. ; * * * * * * * * * * * * * * *  version 2.9  * * * * * * * * * * * * * * *
  2. ; [36]    Add calls to support Concurrent CP/M.
  3. ; [34]    Make BREAK be correct length (250 ms).
  4. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  5. ; [30d] Add SET PORT command, currently unimplemented.
  6. ; [30c] Isolate all machine dependencies in KERIO.
  7. ; [30a] Add keyboard DEL key alteration for APC
  8. ;    RonB, 04/18/84
  9. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  10. ; [28e] Switch to local stack on interrupts.
  11. ;    RonB, 03/28/84
  12. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  13. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  14. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  15. ;    RonB,03/02/84
  16. ; [19a] Add XON/XOFF type flow control
  17. ; [19b]    Clear screen and beginning and end of program.
  18. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  19. ; [19g]    Put in EQU for clock rate for timing loops.
  20. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  21. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  22. ;  [par] Added calls to set parity, strip parity on input if
  23. ;        other than none parity is called for.
  24. ;     JD, 2/84
  25. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  26. ;  [2]    Add a de-initialization routine for the serial port, to restore
  27. ;    changed interrupt vectors, etc.
  28. ;    RonB,12/23/83
  29. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  30. ;    RonB,12/23/83
  31. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  32.  
  33. ; This module contains all the low level communications port I/O
  34. ; routines.
  35.  
  36. ; Here are the I/O routines for the NEC APC.
  37.  
  38.     CSEG $
  39.  
  40. ; Clock rate *10 for timing loops    ;[19g]
  41. clckrt    equ    49        ;[19g]  4.9 Mhz            ;[20b]
  42.  
  43. ; Interrupt vector locations, in data segment 0
  44.  
  45. mnioff    equ    84h        ;sio interrupt offset
  46. mniseg    equ    86h        ;sio interrupt segment
  47.  
  48. ; 8259 Interrupt controller (master)
  49.  
  50. iccmd    equ    20h        ;interrupt command register
  51. icmask    equ    22h        ;interrupt mask register
  52.  
  53. ; 8259 commands and masks
  54.  
  55. icEOI    equ    20h        ;end of interrupt (command)
  56. ictmof    equ    08h        ;disable timer (mask)
  57. icmnof    equ    02h        ;disable RS232 (mask)
  58.  
  59. ; 8253-5 Interval Timer
  60.  
  61. tmdata    equ    2bh        ;baud set (chan 1)
  62. tmcmd    equ    2fh        ;baud timer command port
  63.  
  64. ; 8253 Timer commands
  65.  
  66. tmch1    equ    76h        ;select & init timer channel 1
  67.  
  68. ; 8251A USART controller
  69.  
  70. mndata    equ    30h        ;    data port
  71. mnsts1    equ    32h        ;in  status port
  72. mnsts2    equ    34h        ;in  nec special status port
  73. mncmd    equ    32h        ;out command port
  74. mnmsk    equ    34h        ;out interrupt mask port
  75. mntdc    equ    36h        ;out transmit disable port
  76.  
  77. ; 8251 status port 1 bits
  78.  
  79. mninp    equ    02h        ;receive ready value
  80. mnout    equ    01h        ;send ready value
  81. mndsr    equ    80h        ;data set ready
  82.  
  83. ; 8251 status port 2 bits
  84.  
  85. mncts    equ    04h        ;clear to send
  86.  
  87. ; 8251 initialization instructions
  88.  
  89. ;    command instructions
  90.  
  91. ctxe    equ    01h        ;transmit enable
  92. cdtr    equ    02h        ;dtr signal high
  93. crxe    equ    04h        ;receive enable
  94. cbrk    equ    08h        ;send break
  95. cerr    equ    10h        ;error reset
  96. crts    equ    20h        ;rts signal high
  97. cmode    equ    40h        ;reset - go to mode instruction format
  98. chunt    equ    80h        ;hunt for sync characters
  99.  
  100. ;    mode instructions
  101.  
  102. m1x    equ    01h        ;baud rate factor: 1x
  103. m16x    equ    02h        ;                  16x
  104. m64x    equ    03h        ;                  64x
  105. m5d    equ    00h        ;data bits: 5
  106. m6d    equ    04h        ;           6
  107. m7d    equ    08h        ;           7
  108. m8d    equ    0Ch        ;           8
  109. mpn    equ    00h        ;parity: none
  110. mpo    equ    10h        ;        odd
  111. mpe    equ    30h        ;        even
  112. m1s    equ    40h        ;stop bits: 1
  113. m15s    equ    80h        ;           1.5
  114. m2s    equ    0C0h        ;           2
  115.  
  116. ; 8251 interrupt mask port bits
  117.  
  118. txmsk    equ    01h        ;disable transmit complete interrupt
  119. rxmsk    equ    02h        ;disable receive complete interrupt
  120. tbemsk    equ    04h        ;disable transmit buffer empty interrupt
  121.  
  122. outlmt    EQU    1000H        ;Number of times to check output status
  123.                 ; before giving up on send.        ;[20d]
  124.  
  125. ; dispatch:    Under Concurrent CP/M, releases the processor for other
  126. ;        use when waiting for either the receive or the send status
  127. ;        routines to indicate success.
  128.  
  129. dispatch:
  130.     push    ax
  131.     push    bx
  132.     push    cx
  133.     mov    cl,8Eh            ; P-Dispatch
  134.     int    224
  135.     pop    cx
  136.     pop    bx
  137.     pop    ax
  138.     ret
  139.  
  140.  
  141. ; Test if port is ready to send next char.  Returns RSKP if ready.
  142. ; Trashes dx.
  143.  
  144. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  145.     jne    outwt1        ;no - go on
  146.     cmp    xofrcv, true    ;are we being held?
  147.     je    outwt3        ;yes - return status not ready
  148. outwt1:    push    ax
  149.     mov    dx,mnsts1
  150.     in    al,dx
  151.     and    al,mndsr+mnout
  152.     sub    al,mndsr+mnout
  153.     jnz    outwt2
  154.     mov    dx,mnsts2
  155.     in    al,dx
  156.     and    al,mncts
  157.     jnz    outwt4
  158. outwt2:    pop    ax
  159. outwt3:    call    dispatch    ;let other CCPM processes have a chance    ;[36]
  160.      ret
  161. outwt4:    pop    ax
  162.     jmp    rskp
  163.  
  164.  
  165. ; Output data to port. Trashes DX and prints char in AL.
  166.  
  167. outchr:    mov    dx,mndata
  168.     out    dx,al
  169.     ret
  170.  
  171.  
  172. ; Output the character in AL, checking first to make sure the port is clear.
  173.  
  174. prtout:    call    dopar        ;[par] set parity
  175.     push    dx
  176.     push    cx                        ;[20d] begin
  177.     mov    cx,outlmt
  178. prtou2:    call    outwt        ;Wait until the port is ready
  179.      loop    prtou2        ; or too much time has passed.
  180.      nop
  181.     call    outchr        ;Output it.
  182.     pop    cx                        ;[20d] end
  183.     pop    dx
  184.     ret
  185.  
  186.  
  187. ; Test if data is available from port.
  188.  
  189. instat:    cmp    mnchrn,0    ;Any chars in the buffer?
  190.     jne    inst2
  191.     call    dispatch    ;let other CCPM processes have a chance    ;[36]
  192.      ret
  193. inst2:    jmp    rskp
  194.  
  195.  
  196. ; Input data from port.  Preserves all registers and returns char in
  197. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  198. ; already there.
  199.  
  200. inchr:    push    bx
  201.     cli            ;Disable interrupts while were are playing.
  202.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  203.     mov    bx,mnchop    ;Get the pointer into the buffer.
  204.     inc    bx        ;Increment to the next char.
  205.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  206.     jb    inchr2
  207.     mov    bx, offset mnchrs ;If so wrap around to the start.
  208. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  209.     mov    al,[bx]        ;Get the character.
  210.     sti            ;All done, we can restore interrupts.
  211.     pop    bx
  212.     cmp    parflg,parnon    ;[par] no parity?
  213.     je    inchr3        ;[par] yup, don't bother stripping
  214.     and    al,7fh        ;[par] checking parity, strip off
  215. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  216.     je    inchr4        ;If yes jump
  217.     ret
  218. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  219.     je    inchr5        ;Jump if yes
  220.     ret
  221. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  222.     jb    inchr6        ;yes - jump
  223.     ret
  224. inchr6:    push    ax        ;save current character
  225.     mov    al, xon
  226.     call    prtout        ;send an XON
  227.     mov    xofsnt, false    ;turn off the flag
  228.     pop    ax        ;get back character
  229.     ret            ;                [19a] end
  230.  
  231.  
  232.  
  233. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  234. mnsp    dw    0        ;  for use by interrupt handler
  235. mnsseg    dw    0
  236. mndseg    dw    0
  237.  
  238. ; This routine handles the interrupts on input.
  239.  
  240. mnint:    cli
  241.     mov    cs:mnax, ax    ;Save interrupt stack location.
  242.     mov    ax, sp
  243.     mov    cs:mnsp, ax
  244.     mov    ax, ss
  245.     mov    cs:mnsseg, ax
  246.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  247.     mov    ss, ax
  248.     mov    sp, offset mnstk
  249.     push    ds        ;Save all registers.
  250.     push    es
  251.     push    bp
  252.     push    di
  253.     push    si
  254.     push    dx
  255.     push    cx
  256.     push    bx
  257.     mov    ds, ax        ;Get our data segment address.
  258.     call    mnproc        ;Process the character.
  259.     mov    dx, iccmd
  260.     mov    al, icEOI    ;signal end of interrupt to controller
  261.     out    dx, al
  262.     pop    bx        ;Restore all registers.
  263.     pop    cx
  264.     pop    dx
  265.     pop    si
  266.     pop    di
  267.     pop    bp
  268.     pop    es
  269.     pop    ds
  270.     mov    ax, cs:mnsp    ;Restore the original stack.
  271.     mov    sp, ax
  272.     mov    ax, cs:mnsseg
  273.     mov    ss, ax
  274.     mov    ax, cs:mnax
  275.     iret            ;Return from the interrupt.    ;[28e] end
  276.  
  277.  
  278. ; This routine (called by MNINT) gets a char from the serial port
  279. ; and puts it in the ring buffer.
  280.  
  281. mnproc:    mov    dx,mnsts1
  282.     in    al,dx        ;Get the port status.
  283.     and    al,mninp    ;Is a character waiting?
  284.     jnz    mnpro2        ;   Yes, go take care of it.
  285.      ret            ;   No, just a false alarm.
  286.  
  287. mnpro2:    mov    dx,mndata
  288.     in    al,dx        ;Read the char.
  289.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  290.     jne    mnpr2b        ;no - go on
  291.     cmp    al, xoff    ;is it an XOFF?
  292.     jne    mnpr2a        ;no - go on
  293.     mov    xofrcv, true    ;set the flag
  294.     ret
  295. mnpr2a:    cmp    al, xon        ;an XON?
  296.     jne    mnpr2b        ;no
  297.     mov    xofrcv, false    ;clear the flag
  298.     ret            ;                [19a] end
  299. mnpr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  300.     je    mnperr        ;If so, take care of the error.
  301.     inc    mnchrn        ;Increment the character count.
  302.     mov    bx,mnchip    ;Get the buffer input pointer.
  303.     inc    bx        ;Increment it.
  304.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  305.     jb    mnpro3
  306.     mov    bx, offset mnchrs ;Yes, point to the start again.
  307. mnpro3:    mov    mnchip,bx    ;Save the pointer.
  308.     mov    [bx],al        ;Put the character in the buffer.
  309.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  310.     je    mnpro4        ;If yes jump
  311.     ret
  312. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  313.     jnz    mnpro5
  314.     ret            ;return if we have
  315. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  316.     ja    mnpro6        ;yes - jump
  317.     ret
  318. mnpro6:    mov    al, xoff
  319.     call    prtout        ;send an XOFF
  320.     mov    xofsnt, true    ;set the flag
  321.     ret            ;                [19a] End
  322.  
  323. mnperr:    ret            ;Just return on an error for now.
  324.  
  325.  
  326. ; prtbrk - send a break        ;                [20b] start
  327.  
  328. prtbrk:                ;
  329.     mov    dx,mncmd    ;break goes to command port
  330.     mov    al,cbrk+crts+cerr+crxe+cdtr+ctxe ;add break to normal command
  331.     out    dx,al
  332.     mov    ax, 275        ;.. for 275 millisec's        [34]
  333.     call    mswait        ;                [34]
  334.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  335.     out    dx,al        ;return to normal setting
  336.     ret            ;                 [19e] end
  337.  
  338. mswait:                ;                [34] start
  339.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  340. mswai1:
  341.     sub    cx,1        ;** inner loop takes 20 clock cycles
  342.     jnz    mswai1        ;**
  343.     dec    ax        ; outer loop counter
  344.     jnz    mswait        ; wait another millisecond
  345.     ret            ;                [34] end
  346.  
  347.  
  348. ; serini - This routine initializes all devices that need it.
  349. ;       Called at the start of the program.
  350.  
  351. serini:    cmp    mninit,0FFh    ; must only do this initialization once
  352.     je    serin2
  353.     mov    mninit,0FFh
  354.  
  355.     push    es
  356.  
  357. ; Make DEL key return a 7F code rather than the 18 (control-X)    ;[30a] begin
  358. ; that it ordinarily does.  This involves modifying a key
  359. ; conversion table in the BIOS.  Version 1.107 and later
  360. ; contain a pointer to this table at 40:256C, but earlier
  361. ; versions which do not are still in common use, so I will
  362. ; try to find it with a direct search.
  363.  
  364.     cld
  365.     mov    ax, 40h        ;BIOS segment
  366.     mov    es, ax
  367.     mov    di, 2500h    ;Start of BIOS
  368.     mov    al, 0FCh    ;Key gives this value
  369.     mov    ah, 18h        ;Translated to this value
  370.     mov    cx, -1
  371. serina:    repnz    scasb        ;Look for the key value
  372.     or    cx, cx        ;Zero if search failed
  373.     jz    serinb        ; If so, do nothing
  374.     cmp    es:[di], ah    ;Translation value next?
  375.     jne    serina        ; If not, keep looking
  376.     mov    kbpat, di    ;Save the location we're patching.
  377.     mov    al, 7Fh        ;Insert a DEL character
  378.     mov    es:[di], al
  379. serinb:                ;...and continue    ;[30a] end
  380.  
  381.  
  382.     mov    dx,icmask
  383.     in    al,dx        ;get current interrupt mask
  384.     mov    mnxmsk,al    ;save it for restore
  385.  
  386. ;    NEC recommends that the timer be turned off during interrupt-driven
  387. ;    serial I/O, but this disables the clock and keyboard repeat.  I have
  388. ;    not had any bad results from leaving it enabled.  I will leave the
  389. ;    disabling code here in case something develops. -- RonB
  390.  
  391. ;    or    al,ictmof+icmnof;mask off timer and sio interrupts
  392.     or    al,icmnof    ;mask off sio interrupt
  393.     out    dx,al
  394.  
  395.     mov    ax,ds        ;save data segment in cseg
  396.     mov    cs:mndseg,ax    ;   for use by the interrupt handler
  397.  
  398.     mov    ax,0        ;point to zero page to replace
  399.     mov    es,ax        ;the sio interrupt vector
  400.     mov    ax,es:.mniseg    ;after first saving the current vector
  401.     mov    mnxseg,ax
  402.     mov    ax,es:.mnioff
  403.     mov    mnxoff,ax
  404.     cli
  405.     mov    ax,cs
  406.     mov    es:.mniseg,ax
  407.     mov    ax,offset mnint
  408.     mov    es:.mnioff,ax
  409.     sti
  410.  
  411.     call    stmode        ;set mode & baud to defaults
  412.     call    stbaud
  413.  
  414.     mov    dx,mntdc
  415.     mov    al,00h        ;enable transmission of data
  416.     out    dx,al
  417.  
  418.     mov    dx,mndata    ;dummy read to clear buffer
  419.     in    al,dx
  420.  
  421.     mov    dx,mnmsk
  422.     mov    al,txmsk+tbemsk    ;set interrupt mask (enable read int)
  423.     out    dx,al
  424.  
  425.     mov    dx,icmask
  426.     in    al,dx        ;enable sio interrupts
  427.     and    al,not icmnof
  428.     out    dx,al
  429.  
  430.     pop    es
  431.  
  432. serin2:    ret
  433.  
  434.  
  435. ; serfin - this routine is used to "undo" what serini has done, called
  436. ;       just before exiting back to cp/m.
  437.  
  438. serfin:
  439.     cmp    mninit,0FFh    ;check if initialization has been done
  440.     jne    serfn2        ;if not, don't de-initialize
  441.     mov    mninit,0
  442.  
  443.     push    es
  444.  
  445. ; Unpatch the keyboard conversion table                ;[30a] begin
  446. ; Restore control-X value for DEL key from our 7F value.
  447.  
  448.     les    di, dword ptr kbpat        ;Get the patch location
  449.     or    di, di        ;Did we patch it at all?
  450.     jz    serfia        ; If not, skip this
  451.     mov    kbpat, 0    ;Show no longer patched
  452.     mov    al, 18h        ;Restore control-X value
  453.     mov    es:[di], al
  454. serfia:                ;...and continue    ;[30a] end
  455.  
  456.     cli
  457.     mov    dx,icmask
  458.     mov    al,mnxmsk    ;restore the old interrupt mask
  459.     out    dx,al
  460.     mov    ax,0
  461.     mov    es,ax
  462.     mov    ax,mnxseg    ;restore sio interrupt vector
  463.     mov    es:.mniseg,ax
  464.     mov    ax,mnxoff
  465.     mov    es:.mnioff,ax
  466.     sti
  467.  
  468.     pop    es
  469.  
  470. serfn2:    ret
  471.  
  472.  
  473. ; This routine clears the serial port input buffer.  It is called to
  474. ; clear out excess NAKs that can result from server mode operation.
  475.  
  476. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  477.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  478.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  479.     ret
  480.  
  481. ; set the parity, number of data bits, and number of stop bits
  482.  
  483. stmode:    mov    dx,mncmd
  484.     mov    al,0        ;recommended reset procedure:
  485.     out    dx,al        ;three 0's followed by a cmode
  486.     mov    al,0
  487.     out    dx,al
  488.     mov    al,0
  489.     out    dx,al
  490.     mov    al,cmode    ;enable mode setting
  491.     out    dx,al
  492.     mov    al,m1s        ;1 stop, no parity, 8 data, 16x baud
  493.     add    al,mpn        ;Note: these adds are distinct to
  494.     add    al,m8d        ;      allow the 8251 time to reset
  495.     add    al,m16x
  496.     out    dx,al
  497.     mov    al,crts+cerr+crxe+cdtr+ctxe ;RTS & DTR high, Rx & Tx enabled
  498.     out    dx,al
  499.     ret
  500.  
  501.  
  502. ; set the baud rate
  503.  
  504. stbaud:    mov    al,mnbaud    ;get the baud rate information
  505.     cmp    al,12        ;check for valid range (0-12)
  506.     ja    stb02
  507.     mov    bx,offset baudtb;get address of baud rate table
  508.     add    al,al        ;compute word offset
  509.     mov    ah,0
  510.     add    bx,ax
  511.     mov    dx,tmcmd
  512.     mov    al,tmch1    ;select timer channel 1
  513.     out    dx,al
  514.     mov    dx,tmdata
  515.     mov    ax,[bx]        ;get value
  516.     out    dx,al        ;output low byte
  517.     mov    al,ah
  518.     out    dx,al        ;output high byte
  519. stb02:    ret
  520.  
  521.     dseg $
  522.  
  523. ;    Serial port default parameters
  524.  
  525. mnbaud    db    6        ;300 baud
  526.  
  527. ;    Interval Timer values (assumes 16x baud rate mode)
  528.  
  529. baudtb    dw    0C00h        ;50 baud    0
  530.     dw    0800h        ;75 baud    1
  531.     dw    0600h        ;100 baud    2
  532.     dw    0574h        ;110 baud    3
  533.     dw    0400h        ;150 baud    4
  534.     dw    0300h        ;200 baud    5
  535.     dw    0200h        ;300 baud    6
  536.     dw    0100h        ;600 baud    7
  537.     dw    0080h        ;1200 baud    8
  538.     dw    0040h        ;2400 baud    9
  539.     dw    0020h        ;4800 baud    10
  540.     dw    0010h        ;9600 baud    11
  541.     dw    0008h        ;19200 baud    12
  542.  
  543. mninit    db    0        ;set to 0FFh if initialization has been done
  544. mnxmsk     db    0        ;8259 interrupt mask storage
  545. mnxseg    dw    0        ;system sio interrupt vector
  546. mnxoff    dw    0
  547.  
  548. mnchnd    equ    512        ;Size of circular buffer.
  549. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  550. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  551. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  552. mnchrn    dw    0        ;Number of chars in the buffer.
  553.  
  554. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  555. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  556.  
  557. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  558. xofsnt    db    0        ;[19a] set if XOFF was sent
  559. xofrcv    db    0        ;[19a] set if XOFF was recieved
  560.  
  561.     rw    32        ;Interrupt stack        ;[28e]
  562. mnstk    dw    0        ;bottom of stack        ;[28e]
  563.  
  564. kbpat    dw    0000h,0040h    ;patch location for DEL key    ;[30a]
  565.  
  566.  
  567.     CSEG $
  568.  
  569. ; The following routines do the SET and SHOW for the machine dependent
  570. ; features of Kermit.  At present there are only two:  baud rate setting
  571. ; and port selection.
  572.  
  573. ;    This is the SET BAUD rate subcommand
  574.  
  575. bdset:    mov    dx, offset bdtab
  576.     mov    bx, offset bdhlp
  577.     mov    ah, cmkey
  578.     call    comnd
  579.      jmp    r
  580.     mov    temp1, bx
  581.     mov    ah, cmcfm
  582.     call    comnd        ;Get a confirm.
  583.      jmp    r        ; Didn't get a confirm.
  584.     mov    bx, temp1
  585.     mov    mnbaud, bl    ;Set the baud rate table index.
  586.     call    stbaud
  587.     jmp    rskp
  588.  
  589. ;    This is the SET PORT subcommand (not implemented in APC)
  590.  
  591. prtset:    mov    ah, cmcfm
  592.     call    comnd        ;Get a confirm.
  593.      jmp    $+3        ; Didn't get a confirm.
  594.     mov    dx, offset infms6 ;Tell user it's not implemented
  595.     call    tcrmsg
  596.     jmp    rskp
  597.  
  598.  
  599. ; The following procedures implement the SHOW command for the system
  600. ; dependent features of baud rate and port selection.
  601.  
  602. shobd:    mov    dx, offset bdst    ;Baud rate string.
  603.     call    tcrmsg
  604.     mov    al, mnbaud    ;Print the keyword corresponding to the
  605.     mov    bx, offset bdtab ; current value of mnbaud.
  606.     call    tabprt
  607.     ret
  608.  
  609. shoprt:    ret            ;Port selection not implemented.
  610.  
  611.  
  612.     DSEG $
  613.  
  614. bdtab    db    13        ;Thirteen entries        ;[6] begin
  615.     db    3,'100$'
  616.     dw    0002H
  617.     db    3,'110$'
  618.     dw    0003H
  619.     db    4,'1200$'
  620.     dw    0008H
  621.     db    3,'150$'
  622.     dw    0004H
  623.     db    5,'19200$'
  624.     dw    000CH
  625.     db    3,'200$'
  626.     dw    0005H
  627.     db    4,'2400$'
  628.     dw    0009H
  629.     db    3,'300$'
  630.     dw    0006H
  631.     db    4,'4800$'
  632.     dw    000AH
  633.     db    2,'50$'
  634.     dw    0000H
  635.     db    3,'600$'
  636.     dw    0007H
  637.     db    2,'75$'
  638.     dw    0001H
  639.     db    4,'9600$'
  640.     dw    000BH                        ;[6] end
  641.  
  642. bdhlp    db    cr,lf,'    50    100    150    300    1200    4800    19200'
  643.     db    cr,lf,'    75    110    200    600    2400    9600$'
  644.  
  645.  
  646.  
  647. ; The following routines do screen control.  These are isolated here because
  648. ; the screen control sequences are likely to vary from system to system, even
  649. ; though the Rainbow and APC (the only systems implemented to date) both use
  650. ; ANSI sequences for this purpose.
  651.  
  652.     CSEG $
  653.  
  654. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  655.  
  656. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  657.     mov    cl, 10
  658.     mov    al, [bx]    ;Get row value
  659.     sub    ah, ah
  660.     div    cl        ;units digit in ah, tens digit in al
  661.     add    ax, '00'    ;Convert both to ASCII
  662.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  663.     mov    al, 1[bx]    ;Do same for column value
  664.     sub    ah, ah
  665.     div    cl
  666.     add    ax, '00'
  667.     mov    word ptr anspos+5, ax
  668.     mov    dx, offset anspos    ;Print cursor positioning string.
  669.     call    tmsg
  670.     ret
  671.  
  672. ; CLRSCR - homes cursor and clears screen.
  673.  
  674. clrscr:    mov    dx, offset apccls
  675.     call    tmsg
  676.     ret
  677.  
  678. ; CLRLIN - clears from cursor to end of line.
  679.  
  680. clrlin:    mov    dl, cr        ;Go to beginning of line
  681.     call    bout
  682. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  683.     call    tmsg
  684.     ret
  685.  
  686. ; REVON - turns on reverse video display
  687.  
  688. revon:    mov    dx, offset ansron
  689.     call    tmsg
  690.     ret
  691.  
  692. ; REVOFF - turns off reverse video display
  693.  
  694. revoff:    mov    dx, offset ansrof
  695.     call    tmsg
  696.     ret
  697.  
  698. ; BLDON - turns on bold (highlighted) display
  699.  
  700. bldon:    ret
  701.  
  702. ; BLDOFF - turns off bold (highlighted) display
  703.  
  704. bldoff:    ret
  705.  
  706.  
  707.     DSEG $
  708.  
  709. anspos    db    esc,'[00;00H$'    ;Position cursor to row and column
  710. apccls    db    1Eh,1Ah,'$'    ;Home cursor and clear screen
  711. ansclr    db    esc,'[K$'    ;Clear from cursor to end of line
  712. ansron    db    esc,'[7m$'    ;Turn on reverse video
  713. ansrof    db    esc,'[m$'    ;Turn off reverse video
  714.  
  715.  
  716. ; Here tab expansion is done if necessary.  If not, just return retskp.
  717.  
  718.     cseg $
  719.  
  720. dotab:    cmp    dl, tab        ;A tab?
  721.     je    dotab1
  722.     jmp    rskp        ;No, just proceed.
  723. dotab1:    mov    curbuf, 2    ;Report cursor position command.
  724.     mov    dx, offset curbuf
  725.     mov    cl, 7
  726.     int    220        ;Special BIOS function.
  727.     mov    al, curbuf+2    ;Column position in binary (0-79).
  728.     and    al, 07h        ;Number of spaces needed
  729.     mov    cx, 0008h    ;  = 8 - (col mod 8)
  730.     sub    cl, al
  731. dotab2:    push    cx
  732.     mov    dl, ' '
  733.     call    dbout2
  734.     pop    cx
  735.     loop    dotab2
  736.     ret
  737.  
  738.     dseg $
  739. curbuf    db    2,0,0        ;command, row, column of cursor position ;[7]
  740.  
  741. delstr  db    10O,10O,'$'    ;Delete string.
  742.  
  743. system    db    '        NEC Advanced Personal Computer$'    ;[1][20a]
  744.