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

  1. ; * * * * * * * * * * * * * * *  version 2.8  * * * * * * * * * * * * * * *
  2. ; [34] Insert milli-second wait-loop for Break-timing - label MSWAIT:
  3. ; [33] Fix printer on hanging system problem by letting CP/M handle the
  4. ;    interrupts from the 7201 that we don't care about.  Thanks to
  5. ;    Paul Ford, U. of Chicago Graduate School of Business
  6. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  7. ; [30d] Add SET PORT command, currently unimplemented.
  8. ; [30c] Isolate all machine dependencies in KERIO.
  9. ;    RonB, 04/18/84
  10. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  11. ; [28e] Switch to local stack on interrupts.
  12. ;    RonB, 03/28/84
  13. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  14. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  15. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  16. ;    RonB,03/02/84
  17. ; [19a] Add XON/XOFF type flow control
  18. ; [19b]    Clear screen and beginning and end of program.
  19. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  20. ; [19g]    Put in EQU for clock rate for timing loops.
  21. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  22. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  23. ;  [par] Added calls to set parity, strip parity on input if
  24. ;    other than none parity is called for.
  25. ;     JD, 2/84
  26. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  27. ;  [2]    Add a de-initialization routine for the serial port, to restore
  28. ;    changed interrupt vectors, etc.
  29. ;    RonB,12/23/83
  30. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  31. ;    RonB,12/23/83
  32. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  33.  
  34. ; This module contains all the low level communications port I/O
  35. ; routines.
  36.  
  37. ; The following is the I/O code for the DEC Rainbow.
  38.  
  39.         CSEG $
  40.  
  41. ; Clock rate *10 for timing loops    ;[19g]
  42. clckrt    equ    48        ;[19g]  4.8 Mhz
  43.  
  44. ; Interrupt vector locations, in data segment
  45. mnstat    EQU    042H        ;Status port.
  46. mndata    EQU    040H        ;Data port.
  47. mnctrl    EQU    002H        ;Control port.
  48.  
  49. ; Interrupt vector locations.  These are all in data segment 0.
  50.  
  51. mnoff    EQU    90H        ;Main data port interrupt routine offset.
  52. mnseg    EQU    92H        ;Main data port interrupt routine segment.
  53.  
  54. output    EQU    04H        ;Bit for output ready.
  55. input    EQU    01H        ;Bit for input ready.
  56.  
  57. outlmt    EQU    1000H        ;Number of times to check output status
  58.                 ; before giving up on send.        ;[20d]
  59.  
  60.  
  61. ; Input data from port.  Preserves all ACs and returns char in
  62. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  63. ; already there.
  64.  
  65. inchr:    push    bx
  66.     cli            ;Disable interrupts while were are playing.
  67.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  68.     mov    bx, mnchop    ;Get the pointer into the buffer.
  69.     inc    bx        ;Increment to the next char.
  70.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  71.     jb    inchr2
  72.     mov    bx, offset mnchrs ;If so wrap around to the start.
  73. inchr2:    mov    mnchop, bx    ;Save the updated pointer.
  74.     mov    al, [bx]    ;Get the character.
  75.     sti            ;All done, we can restore interrupts.
  76.     pop    bx
  77.     cmp    parflg,parnon    ;[par] no parity?
  78.     je    inchr3        ;[par] yup, don't bother stripping
  79.     and    al,7fh        ;[par] checking parity, strip off
  80. inchr3:    cmp    floctl, floxon    ; do flow control?        [19a] start
  81.     je    inchr4        ;If yes jump
  82.     ret
  83. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  84.     je    inchr5        ;Jump if yes
  85.     ret
  86. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  87.     jb    inchr6        ;yes - jump
  88.     ret
  89. inchr6:    push    ax        ;save current character
  90.     mov    al, xon
  91.     call    prtout        ;send an XON
  92.     mov    xofsnt, false    ;turn off the flag
  93.     pop    ax        ;get back character
  94.     ret            ;                [19a] end
  95.  
  96.  
  97. ; Output data to port. Trashes DX and prints char in AL.
  98.  
  99. outchr:    mov    dx, mndata
  100.     out    dx, al
  101.     ret
  102.  
  103.  
  104. ; Test if data is available from port.
  105.  
  106. instat:    cmp    mnchrn, 0    ;Any chars in the buffer?
  107.     jnz    inst2
  108.      ret
  109. inst2:    jmp    rskp
  110.  
  111.  
  112. ; Test if port is ready to send next char.  Returns RETSKP if ready.
  113. ; Trashes dx.
  114.  
  115. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  116.     jne    outwta        ;no - go on
  117.     cmp    xofrcv, true    ;are we being held?
  118.     jne    outwta        ;no - ok go on
  119.     ret            ;held - say we're busy.    [19a] end
  120. outwta:    push    ax
  121.     mov    dx, mnstat
  122.     in    al, dx
  123.     test    al, output
  124.     pop    ax
  125.     jnz    outwt2
  126.      ret
  127. outwt2:    jmp    rskp
  128.  
  129.  
  130. ; Output the character, checking first to make sure the port is clear.
  131.  
  132. prtout:    call    dopar        ;[par]
  133.     push    dx
  134.     push    cx                        ;[20d] begin
  135.     mov    cx,outlmt
  136. prtou2:    call    outwt        ;Wait until the port is ready
  137.      loop    prtou2        ; or too much time has passed.
  138.      nop
  139.     call    outchr        ;Output it.
  140.     pop    cx                        ;[20d] end
  141.     pop    dx
  142.     ret
  143.  
  144.  
  145. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  146. mnsp    dw    0        ;  for use by interrupt handler
  147. mnsseg    dw    0
  148. mndseg    dw    0
  149.  
  150. ; This routine handles the interrupts on input.
  151.  
  152. mnint:    cli
  153.     mov    cs:mnax, ax    ;Save interrupt stack location.
  154.     mov    ax, sp
  155.     mov    cs:mnsp, ax
  156.     mov    ax, ss
  157.     mov    cs:mnsseg, ax
  158.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  159.     mov    ss, ax
  160.     mov    sp, offset mnstk
  161.     push    ds        ;Save all registers.
  162.     push    es
  163.     push    bp
  164.     push    di
  165.     push    si
  166.     push    dx
  167.     push    cx
  168.     push    bx
  169.     mov    ds, ax
  170.     call    mnproc        ;Process the character.
  171.     mov    dx, mnstat    ;Get the status port.
  172.     mov    al, 38H
  173.     out    dx, al        ;Tell the port we finished with the interrupt.
  174.     pop    bx        ;Restore all registers.
  175.     pop    cx
  176.     pop    dx
  177.     pop    si
  178.     pop    di
  179.     pop    bp
  180.     pop    es
  181.     pop    ds
  182.     mov    ax, cs:mnsp    ;Restore the original stack.
  183.     mov    sp, ax
  184.     mov    ax, cs:mnsseg
  185.     mov    ss, ax
  186.     mov    ax, cs:mnax
  187.     iret            ;Return from the interrupt.    ;[28e] end
  188.  
  189.  
  190. ; This routine (called by MNINT) gets a char from the main port
  191. ; and puts it in the infamous circular buffer.
  192.  
  193. mnproc:    mov    dx, mnstat
  194.     in    al, dx        ;Get the port status.
  195.     test    al, input    ;Any there?
  196.     jnz    mnpro2        ;Yup, go take care of it.
  197.  
  198. ;[33] Begin addition
  199. ; If not a received character, simulate an interrupt transferring
  200. ; control to the CPM routine. Let it handle worrisome things like
  201. ; someone turning on the printer.
  202.  
  203.      pushf            ; Save flags, like an int.
  204.      callf dword ptr mnoldo    ; Call CPM's routine.
  205.      ret            ; Now back to MNINT.
  206.  
  207. ;[33] End addition
  208.  
  209. mnpro2:    mov    al, 1        ;Point to RR1.
  210.     out    dx, al
  211.     in    al, dx        ;Read RR1.
  212.     mov    ah, al        ;Save it.
  213.     mov    al, 30H        ;Reset any errors.
  214.     out    dx, al
  215.     mov    dx, mndata
  216.     in    al, dx        ;Read the char.
  217.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  218.     jne    mnpr2b        ;no - go on
  219.     cmp    al, xoff    ;is it an XOFF?
  220.     jne    mnpr2a        ;no - go on
  221.     mov    xofrcv, true    ;set the flag
  222.     ret
  223. mnpr2a:    cmp    al, xon        ;an XON?
  224.     jne    mnpr2b        ;no
  225.     mov    xofrcv, false    ;clear the flag
  226.     ret            ;                [19a] end
  227. mnpr2b:    cmp    mnchrn, mnchnd    ;Is the buffer full?
  228.     je    mnperr        ;If so, take care of the error.
  229.     inc    mnchrn        ;Increment the character count.
  230.     mov    bx, mnchip    ;Get the buffer input pointer.
  231.     inc    bx        ;Increment it.
  232.     cmp    bx, offset mnchrs+mnchnd ;Past the end?
  233.     jb    mnpro3
  234.     mov    bx, offset mnchrs ;Yes, point to the start again.
  235. mnpro3:    mov    mnchip, bx    ;Save the pointer.
  236.     mov    [bx], al    ;Put the character in the buffer.
  237.     cmp    floctl, floxon    ;do flow control?        [19a] start
  238.     je    mnpro4        ;If yes jump
  239.     ret
  240. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  241.     jnz    mnpro5
  242.     ret            ;return if we have
  243. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  244.     ja    mnpro6        ;yes - jump
  245.     ret
  246. mnpro6:    mov    al, xoff
  247.     call    prtout        ;send an XOFF
  248.     mov    xofsnt, true    ;set the flag
  249.     ret            ;                [19a] End
  250.  
  251. mnperr:    ret            ;Just return on an error for now.
  252.  
  253.  
  254. ; prtbrk - send a break        ;                [19e] start
  255.  
  256. prtbrk:                ;
  257.     mov    dx, mnstat    ;status reg. address for port
  258.     mov    al, 15H        ;select reg. 5
  259.     out    dx, al        ;
  260.     mov    al, 0FAH    ;8 bits, TX, Break, RTS, & DTR
  261.     out    dx, al        ;Turn Break on
  262.     mov    ax, 275        ;.. for 275 millisec's        [34]
  263.     call    mswait        ;                [34]
  264.     mov    al, 15H        ;select reg. 5
  265.     out    dx, al        ;
  266.     mov    al, 0EAH    ;same as above without Break
  267.     out    dx, al        ;turn it off
  268.     ret            ;                 [19e] end
  269.  
  270. mswait:                ;                [34] start
  271.     mov    cx,5*clckrt    ; inner loop count for 1 millisec.
  272. mswai1:
  273.     sub    cx,1        ;** inner loop takes 20 clock cycles
  274.     jnz    mswai1        ;**
  275.     dec    ax        ; outer loop counter
  276.     jnz    mswait        ; wait another millisecond
  277.     ret            ;                [34] end
  278. ;
  279. ; Init the 7201 for 8 bits, no parity, and 1 stop bit.
  280.  
  281. serini:    call    ansmod        ;Switch from VT52 to ANSI mode    ;[30c]
  282.  
  283.     mov    ax, ds
  284.     mov    cs:mndseg, ax    ;Save the data segment somewhere in CSEG.
  285.     push    ds        ;Save the data segment.
  286.     mov    ax, 0
  287.     mov    ds, ax        ;We want DSEG = 0.
  288.     cli            ;Turn off interrupts.
  289.     mov    bx, .mnoff    ;[33] Get original interrupt offset.
  290.     mov    es, .mnseg    ;[33] Get original interrupt segment.
  291.     mov    ax, offset mnint;Point to the interrupt routine offset.
  292.     mov    .mnoff, ax    ;Put in the main port interrupt offset addr.
  293.     mov    ax, cs        ;Get our code segment.
  294.     mov    .mnseg, ax    ;Put in the main port interrupt segment addr.
  295.     sti            ;Restore interrupts.
  296.     pop    ds        ;Restore data segment.
  297.  
  298.     mov    mnoldo, bx    ;[33] Stash original serial interrupt offset.
  299.     mov    mnolds, es    ;[33] Stash original segment.
  300.  
  301.     mov    dx, mnstat    ;Point to status port.
  302.     mov    al, 18H
  303.     out    dx, al        ;Reset the port.
  304.     mov    al, 14H
  305.     out    dx, al        ;Select register 4.
  306.     mov    al, 44H        ;16X clock, 1 stop bit, no parity.
  307.     out    dx, al
  308.     mov    al, 13H
  309.     out    dx, al        ;Select register 3.
  310.     mov    al, 0C1H    ;8 bits/char, RX enable.
  311.     out    dx, al
  312.     mov    al, 15H
  313.     out    dx, al        ;Select register 5.
  314.     mov    al, 0EAH    ;8 bits/char, TX enable, RTS and DTR.
  315.     out    dx, al
  316.     mov    al, 11H
  317.     out    dx, al        ;Select register 1.
  318.     mov    al, 18H
  319.     out    dx, al        ;Enable interrupt processing on this port.
  320.     mov    dx, mnctrl    ;point to comm control port
  321.     mov    al, 0F0H    ;set RTS & DTR high
  322.     out    dx, al
  323.     ret
  324.  
  325. serfin:    
  326.     call    clrscr        ;[19b] clear screen        ;[30c]
  327.  
  328.     ret            ;Nothing to deinitialize on Rainbow.
  329.  
  330. ; This routine clears the serial port input buffer.  It is called to
  331. ; clear out excess NAKs that can result from server mode operation.
  332.  
  333. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  334.     mov    mnchip, offset mnchrs-1+mnchnd ;Reset input pointer.
  335.     mov    mnchop, offset mnchrs-1+mnchnd ;Reset output pointer.
  336.     ret
  337.  
  338.     DSEG $
  339.  
  340. mnchnd    equ    256        ;[19a] Size of circular buffer.
  341. mntrg1    equ    64        ;[19a] Low trigger point for Auto XON/XOFF
  342. mntrg2    equ    192        ;[19a] High trigger point for Auto XON/XOFF
  343.  
  344. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  345. xofsnt    db    0        ;[19a] set if XOFF was sent
  346. xofrcv    db    0        ;[19a] set if XOFF was recieved
  347.  
  348. mnchrn    DW    0        ;[19a] Number of chars in the buffer.
  349. mnchrs    RB    mnchnd        ;Circular character buffer for input.
  350. mnchip    DW    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  351. mnchop    DW    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  352.  
  353. mnoldo    RW    1        ;[33] CPM's 7201 interrupt vector offset
  354. mnolds    RW    1        ;[33] and segment.
  355.  
  356.     rw    32        ;Interrupt stack        ;[28e]
  357. mnstk    dw    0        ;bottom of stack        ;[28e]
  358.  
  359.  
  360.     CSEG $
  361.  
  362. ; The following routines do the SET and SHOW for the machine dependent
  363. ; features of Kermit.  At present there are only two:  baud rate setting
  364. ; and port selection.
  365.  
  366. ;    This is the SET BAUD rate subcommand (not implemented in Rainbow)
  367.  
  368. bdset:    mov    ah, cmcfm
  369.     call    comnd        ;Get a confirm.
  370.      jmp    $+3        ; Didn't get a confirm.
  371.     mov    dx, offset infms6 ;Tell user it's not implemented
  372.     call    tcrmsg
  373.     jmp    rskp
  374.  
  375. ;    This is the SET PORT subcommand (not implemented in Rainbow)
  376.  
  377. prtset:    mov    ah, cmcfm
  378.     call    comnd        ;Get a confirm.
  379.      jmp    $+3        ; Didn't get a confirm.
  380.     mov    dx, offset infms6 ;Tell user it's not implemented
  381.     call    tcrmsg
  382.     jmp    rskp
  383.  
  384.  
  385. ; The following procedures implement the SHOW command for the system
  386. ; dependent features of baud rate and port selection.
  387.  
  388. shobd:    ret            ;Baud rate selection not implemented.
  389.  
  390. shoprt:    ret            ;Port selection not implemented.
  391.  
  392.  
  393.  
  394.  
  395. ; The following routines do screen control.  These are isolated here because
  396. ; the screen control sequences are likely to vary from system to system, even
  397. ; though the Rainbow and APC (the only systems implemented to date) both use
  398. ; ANSI sequences for this purpose.
  399.  
  400.     CSEG $
  401.  
  402. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  403.  
  404. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  405.     mov    cl, 10
  406.     mov    al, [bx]    ;Get row value
  407.     sub    ah, ah
  408.     div    cl        ;units digit in ah, tens digit in al
  409.     add    ax, '00'    ;Convert both to ASCII
  410.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  411.     mov    al, 1[bx]    ;Do same for column value
  412.     sub    ah, ah
  413.     div    cl
  414.     add    ax, '00'
  415.     mov    word ptr anspos+5, ax
  416.     mov    dx, offset anspos ;Print cursor positioning string.
  417.     call    tmsg
  418.     ret
  419.  
  420. ; CLRSCR - homes cursor and clears screen.
  421.  
  422. clrscr:    mov    dx, offset anscls
  423.     call    tmsg
  424.     ret
  425.  
  426. ; CLRLIN - clears from cursor to end of line.
  427.  
  428. clrlin:    mov    dl, cr        ;Go to beginning of line
  429.     call    bout
  430. clreol:    mov    dx, offset ansclr ;Clear from cursor to end of line
  431.     call    tmsg
  432.     ret
  433.  
  434. ; REVON - turns on reverse video display
  435.  
  436. revon:    mov    dx, offset ansron
  437.     call    tmsg
  438.     ret
  439.  
  440. ; REVOFF - turns off reverse video display
  441.  
  442. revoff:    mov    dx, offset ansrof
  443.     call    tmsg
  444.     ret
  445.  
  446. ; BLDON - turns on bold (highlighted) display
  447.  
  448. bldon:    mov    dx, offset ansbon
  449.     call    tmsg
  450.     ret
  451.  
  452. ; BLDOFF - turns off bold (highlighted) display
  453.  
  454. bldoff:    mov    dx, offset ansbof
  455.     call    tmsg
  456.     ret
  457.  
  458. ; ANSMOD - enters ANSI mode from VT52 mode
  459.  
  460. ansmod:    mov    dx, offset ansion
  461.     call    tmsg
  462.     ret
  463.  
  464.     DSEG $
  465.  
  466. anspos    db    esc,'[00;00H$'        ;Position cursor to row and column
  467. anscls    db    esc,'[H',esc,'[J$'    ;Home cursor and clear screen
  468. ansclr    db    esc,'[K$'        ;Clear from cursor to end of line
  469. ansron    db    esc,'[7m$'        ;Turn on reverse video
  470. ansrof    db    esc,'[m$'        ;Turn off reverse video
  471. ansbon    db    esc,'[1m$'        ;Turn on bold (highlight) display
  472. ansbof    db    esc,'[m$'        ;Turn off bold display
  473. ansion    db    esc,'<$'        ;Enter ANSI mode
  474.  
  475. ; Here tab expansion is done if necessary.  If not, just return retskp.
  476.  
  477.     CSEG $
  478. dotab:    jmp rskp
  479.  
  480.     DSEG $
  481. delstr    db    ' ',10O,10O,'$'    ;Delete string.
  482.  
  483. system    db    '                DEC Rainbow-100$'
  484.  
  485.