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

  1. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  2. ;    Tektronix 4170 version - TransEra Corporation
  3. ;    Robert Raymond, 3707 North Canyon Road, Building 4, Provo, UT 84601
  4. ; [31c] set default baud to 9600
  5. ; [31b] Changes made for 4170 port hardware
  6. ; [31a] Use ansi routines from 86keri.rb
  7. ; * * * * * * * * * * * * * * *  version 2.7  * * * * * * * * * * * * * * *
  8. ; [30d] Add SET PORT command, currently unimplemented.
  9. ; [30c] Isolate all machine dependencies in KERIO.
  10. ; [30a] Add keyboard DEL key alteration for APC
  11. ;    RonB, 04/18/84
  12. ; * * * * * * * * * * * * * * *  version 2.6  * * * * * * * * * * * * * * *
  13. ; [28e] Switch to local stack on interrupts.
  14. ;    RonB, 03/28/84
  15. ; * * * * * * * * * * * * * * *  version 2.4  * * * * * * * * * * * * * * *
  16. ; [20b] Add PRTBRK to send break & set correct clock rate for NEC.
  17. ; [20d] Add a pseudo time-out to PRTOUT so it doesn't loop forever.
  18. ;    RonB,03/02/84
  19. ; [19a] Add XON/XOFF type flow control
  20. ; [19b]    Clear screen and beginning and end of program.
  21. ; [19e]    Add PRTBRK to send break to port (Rainbow only)
  22. ; [19g]    Put in EQU for clock rate for timing loops.
  23. ;    Rg, 2/84     <Oc.Garland%CU20B@Columbia-20>
  24. ; * * * * * * * * * * * * * * *  version 2.3  * * * * * * * * * * * * * * *
  25. ;  [par] Added calls to set parity, strip parity on input if
  26. ;        other than none parity is called for.
  27. ;     JD, 2/84
  28. ; * * * * * * * * * * * * * * *  version 2.2  * * * * * * * * * * * * * * *
  29. ;  [2]    Add a de-initialization routine for the serial port, to restore
  30. ;    changed interrupt vectors, etc.
  31. ;    RonB,12/23/83
  32. ;  [1]    Add I/O support for the NEC Advanced Personal Computer
  33. ;    RonB,12/23/83
  34. ; * * * * * * * * * * * * * * *  version 2.0  * * * * * * * * * * * * * * *
  35.  
  36. ; This module contains all the low level communications port I/O
  37. ; routines.
  38.  
  39. ; Here are the I/O routines for the TEK 4170.
  40.  
  41.     CSEG $
  42.  
  43. ; Clock rate *10 for timing loops    ;[19g]
  44. clckrt    equ    49        ;[19g]  4.9 Mhz            ;[20b]
  45.  
  46. ; Interrupt vector locations, in data segment 0
  47.  
  48. mnioff    equ    200h        ;HO_In_Int interrupt offset    ;[31b]
  49. mniseg    equ    202h        ;HO_In_Int interrupt segment    ;[31b]
  50.  
  51. ;
  52. ; equates for 2661B chip -- host initialization parameters
  53. ;
  54.  
  55. HO_Data    equ    0e0h
  56. HO_Stat    equ    0e2h
  57. HO_Mode    equ    0e4h
  58. HO_Cmd    equ    0e6h
  59.  
  60. HOCLKRATE    equ    02h    ;sets async mode, 16x clock on host port
  61. HOSB2    equ    0c0h    ;two stop bits
  62. HOSB1    equ    040h    ;one stop bits
  63. HOEVEN    equ    020h    ;select even parity, not odd parity
  64. HOPENB    equ    010h    ;enable parity on the host
  65.  
  66. HOSTART    equ    037h    ;RTS, DTR set, Rx & Tx enabled, reset errors
  67. HOBREAK equ    4    ; force break
  68.  
  69. HO_Thre    equ    01h    ;one on this indicates thre, 0 is thr busy
  70. HO_DRdy    equ    02h    ;one indicates data ready, 0 no data
  71.  
  72.  
  73.  
  74. outlmt    EQU    1000H        ;Number of times to check output status
  75.                 ; before giving up on send.        ;[20d]
  76.  
  77.  
  78. ; Test if port is ready to send next char.  Returns RSKP if ready.
  79. ; Trashes dx.
  80.  
  81. outwt:    cmp    floctl, floxon    ;are we doing flow-control?    [19a] start
  82.     jne    outwta        ;no - go on
  83.     cmp    xofrcv, true    ;are we being held?
  84.     jne    outwta        ;no - ok go on
  85.     ret            ;held - say we're busy.    [19a] end
  86. outwta:    push    ax
  87.     mov    dx,HO_Stat    ;[31b] begin
  88.     in    al,dx
  89.     test    al,HO_Thre    ;transmit holding register empty
  90.     pop    ax
  91.     jnz    outwt2
  92.      ret
  93. outwt2:    jmp    rskp        ;[31b] end
  94.  
  95.  
  96. ; Output data to port. Trashes DX and prints char in AL.
  97.  
  98. outchr:    mov    dx,HO_Data    ;[31b] begin
  99.     out    dx,al
  100.                 ; don't ask me why we do this:
  101.  
  102.     mov    al,HO_START    ;rts and start scanning
  103.     out    HO_Cmd,al    
  104.     ret            ;[31b] end
  105.  
  106.  
  107. ; Output the character in AL, checking first to make sure the port is clear.
  108.  
  109. prtout:    call    dopar        ;[par] set parity
  110.     push    dx
  111.     push    cx                        ;[20d] begin
  112.     mov    cx,outlmt
  113. prtou2:    call    outwt        ;Wait until the port is ready
  114.      loop    prtou2        ; or too much time has passed.
  115.      nop
  116.     call    outchr        ;Output it.
  117.     pop    cx                        ;[20d] end
  118.     pop    dx
  119.     ret
  120.  
  121.  
  122. ; Test if data is available from port.
  123.  
  124. instat:    cmp    mnchrn,0    ;Any chars in the buffer?
  125.     jnz    inst2
  126.      ret
  127. inst2:    jmp    rskp
  128.  
  129.  
  130. ; Input data from port.  Preserves all registers and returns char in
  131. ; AL.  Gets the char from the ring buffer.  Assumes a char is
  132. ; already there.
  133.  
  134. inchr:    push    bx
  135.     cli            ;Disable interrupts while were are playing.
  136.     dec    mnchrn        ;Decrement the number of chars in the buffer.
  137.     mov    bx,mnchop    ;Get the pointer into the buffer.
  138.     inc    bx        ;Increment to the next char.
  139.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  140.     jb    inchr2
  141.     lea    bx,mnchrs    ;If so wrap around to the start.
  142. inchr2:    mov    mnchop,bx    ;Save the updated pointer.
  143.     mov    al,[bx]        ;Get the character.
  144.     sti            ;All done, we can restore interrupts.
  145.     pop    bx
  146.     cmp    parflg,parnon    ;[par] no parity?
  147.     je    inchr3        ;[par] yup, don't bother stripping
  148.     and    al,7fh        ;[par] checking parity, strip off
  149. inchr3:    cmp    floctl, floxon    ;do flow-control?        [19a] start
  150.     je    inchr4        ;If yes jump
  151.     ret
  152. inchr4:    cmp    xofsnt, true    ;Have we sent an XOFF
  153.     je    inchr5        ;Jump if yes
  154.     ret
  155. inchr5:    cmp    mnchrn, mntrg1    ;Under the low trigger point?
  156.     jb    inchr6        ;yes - jump
  157.     ret
  158. inchr6:    push    ax        ;save current character
  159.     mov    al, xon
  160.     call    prtout        ;send an XON
  161.     mov    xofsnt, false    ;turn off the flag
  162.     pop    ax        ;get back character
  163.     ret            ;                [19a] end
  164.  
  165.  
  166.  
  167. mnax    dw    0        ;Storage in CSEG        ;[28e] begin
  168. mnsp    dw    0        ;  for use by interrupt handler
  169. mnsseg    dw    0
  170. mndseg    dw    0
  171.  
  172. ; This routine handles the interrupts on input.
  173.  
  174. mnint:    cli
  175.     mov    cs:mnax, ax    ;Save interrupt stack location.
  176.     mov    ax, sp
  177.     mov    cs:mnsp, ax
  178.     mov    ax, ss
  179.     mov    cs:mnsseg, ax
  180.     mov    ax, cs:mndseg    ;Switch to our internal stack.
  181.     mov    ss, ax
  182.     lea    sp, mnstk
  183.     push    ds        ;Save all registers.
  184.     push    es
  185.     push    bp
  186.     push    di
  187.     push    si
  188.     push    dx
  189.     push    cx
  190.     push    bx
  191.     mov    ds, ax        ;Get our data segment address.
  192.     call    mnproc        ;Process the character.
  193.     pop    bx        ;Restore all registers.
  194.     pop    cx
  195.     pop    dx
  196.     pop    si
  197.     pop    di
  198.     pop    bp
  199.     pop    es
  200.     pop    ds
  201.     mov    ax, cs:mnsp    ;Restore the original stack.
  202.     mov    sp, ax
  203.     mov    ax, cs:mnsseg
  204.     mov    ss, ax
  205.     mov    ax, cs:mnax
  206.     iret            ;Return from the interrupt.    ;[28e] end
  207.  
  208.  
  209. ; This routine (called by MNINT) gets a char from the serial port
  210. ; and puts it in the ring buffer.
  211.  
  212. mnproc:    mov    dx,HO_Stat    
  213.     in    al,dx        ;Get the port status.        [31b] start
  214.     test    al,HO_DRdy    ;Is a character waiting?
  215.     jnz    mnpro2        ;   Yes, go take care of it.
  216.      ret            ;   No, just a false alarm.
  217.  
  218. mnpro2:    mov    dx,HO_Data
  219.     in    al,dx        ;Read the char.            [31b] end
  220.     cmp    floctl, floxon    ;are we doing flow-control ?    [19a] start
  221.     jne    mnpr2b        ;no - go on
  222.     cmp    al, xoff    ;is it an XOFF?
  223.     jne    mnpr2a        ;no - go on
  224.     mov    xofrcv, true    ;set the flag
  225.     ret
  226. mnpr2a:    cmp    al, xon        ;an XON?
  227.     jne    mnpr2b        ;no
  228.     mov    xofrcv, false    ;clear the flag
  229.     ret            ;                [19a] end
  230. mnpr2b:    cmp    mnchrn,mnchnd    ;Is the buffer full?
  231.     je    mnperr        ;If so, take care of the error.
  232.     inc    mnchrn        ;Increment the character count.
  233.     mov    bx,mnchip    ;Get the buffer input pointer.
  234.     inc    bx        ;Increment it.
  235.     cmp    bx,offset mnchrs+mnchnd ;Past the end?
  236.     jb    mnpro3
  237.     lea    bx,mnchrs    ;Yes, point to the start again.
  238. mnpro3:    mov    mnchip,bx    ;Save the pointer.
  239.     mov    [bx],al        ;Put the character in the buffer.
  240.     cmp    floctl, floxon    ;do flow-control?        [19a] start
  241.     je    mnpro4        ;If yes jump
  242.     ret
  243. mnpro4:    cmp    xofsnt, true    ;Have we sent an XOFF
  244.     jnz    mnpro5
  245.     ret            ;return if we have
  246. mnpro5:    cmp    mnchrn, mntrg2    ;Past the High trigger point?
  247.     ja    mnpro6        ;yes - jump
  248.     ret
  249. mnpro6:    mov    al, xoff
  250.     call    prtout        ;send an XOFF
  251.     mov    xofsnt, true    ;set the flag
  252.     ret            ;                [19a] End
  253.  
  254. mnperr:    ret            ;Just return on an error for now.
  255.  
  256.  
  257. ; prtbrk - send a break        ;                [31b] start
  258.  
  259. prtbrk:
  260.     mov    dx,HO_Cmd    ;break goes to command port
  261.     mov    al,HO_START+HO_BREAK    ;add break to normal command
  262.     out    dx,al
  263.     mov    cx, 25000    ;sit for a while
  264. prtbk1:    loop    prtbk1
  265.     mov    al,HO_START    ;normal command,RTS & DTR high, Rx & Tx enabled
  266.     out    dx,al        ;return to normal setting
  267.     ret
  268.  
  269.  
  270. ; serini - This routine initializes all devices that need it.
  271. ;       Called at the start of the program.
  272.  
  273. serini:    cmp    mninit,0FFh    ; must only do this initialization once
  274.     je    serin2
  275.     mov    mninit,0FFh
  276.     call    ansmod        ; switch from tek mode to ansi mode
  277.  
  278.     push    es
  279. ;code could be added here
  280. ;to tell the interrupt controller to diable host interrupt
  281.     mov    ax,ds        ;save data segment in cseg
  282.     mov    cs:mndseg,ax    ;   for use by the interrupt handler
  283.  
  284.     mov    ax,0        ;point to zero page to replace
  285.     mov    es,ax        ;the sio interrupt vector
  286.     mov    ax,es:.mniseg    ;after first saving the current vector
  287.     mov    mnxseg,ax
  288.     mov    ax,es:.mnioff
  289.     mov    mnxoff,ax
  290.     cli
  291.     mov    ax,cs
  292.     mov    es:.mniseg,ax
  293.     mov    ax,offset mnint
  294.     mov    es:.mnioff,ax
  295.     sti
  296.  
  297.     call    stmode        ;set mode & baud to defaults
  298.     call    stbaud
  299.  
  300.                 ;enable transmission of data
  301.     mov    al,HOSTART    ;DTR high, Rx & Tx enabled, reset error
  302.     out    HO_Cmd,al
  303.  
  304.     in    al,HO_Data    ;dummy read to clear buffer
  305.  
  306. ;code could be added here
  307. ;to tell the interrupt controller to re-enable host interrupt
  308.     mov    dx,0ebh
  309.     mov    al,24h            ;turn on host read interrupt
  310.     out    dx,al                        ;[31b] end
  311.  
  312.     pop    es
  313.  
  314. serin2:    ret
  315.  
  316.  
  317. ; serfin - this routine is used to "undo" what serini has done, called
  318. ;       just before exiting back to cp/m.
  319.  
  320. serfin:
  321.     call    clrscr        ;[19b] clear screen    ;[30c]
  322.  
  323.     cmp    mninit,0FFh    ;check if initialization has been done
  324.     jne    serfn2        ;if not, don't de-initialize
  325.     mov    mninit,0
  326.  
  327.     push    es
  328.  
  329.     cli
  330. ;code could be added here to assure the interrupt controller
  331. ;is restored to the state is was in when kermit started
  332.     mov    ax,0
  333.     mov    es,ax
  334.     mov    ax,mnxseg    ;restore sio interrupt vector
  335.     mov    es:.mniseg,ax
  336.     mov    ax,mnxoff
  337.     mov    es:.mnioff,ax
  338.     sti
  339.  
  340.     pop    es
  341.  
  342. serfn2:    ret
  343.  
  344.  
  345. ; This routine clears the serial port input buffer.  It is called to
  346. ; clear out excess NAKs that can result from server mode operation.
  347.  
  348. cfibf:    mov    mnchrn, 0    ;Say no characters in the buffer.
  349.     mov    mnchip, OFFSET mnchrs-1+mnchnd ;Reset input pointer.
  350.     mov    mnchop, OFFSET mnchrs-1+mnchnd ;Reset output pointer.
  351.     ret
  352.  
  353. ; set the parity, number of data bits, and number of stop bits
  354.  
  355. stmode:    mov    dx,HO_Cmd                    ;[31b] start
  356.     mov    al,0        ;reset
  357.     out    dx,al    
  358.     in    al,dx        ;reset mode1/2 sequencer
  359.     mov    dx,HO_Mode
  360.     mov    al,HOCLKRATE    ;init async mode, 16x baud, no parity
  361.     add    al,HOSB1    ;1 stop bit
  362.     add    al,0ch        ;8 data bits
  363.     out    dx,al                        ;[31b] end
  364.     ret
  365.  
  366.  
  367. ; set the baud rate
  368.  
  369. stbaud:    mov    dx,HO_Cmd                    ;[31b] start
  370.     in    al,dx        ;reset mode1/2 sequencer
  371.     mov    dx,HO_Mode
  372.     in    al,dx        ;get mode1 register
  373.  
  374.                 ; can the next 4 lines be skipped?
  375.  
  376.     mov    ah,al        ;save it
  377.     in    al,dx        ;get mode2 register to reset sequence
  378.     mov    al,ah        ; write back old contents of mode 1
  379.     out    dx,al
  380.                 ; next out will set mode 2 - baud rate
  381.  
  382.     mov    al,mnbaud    ;get the baud rate information
  383.     cmp    al,15        ;check for valid range (0-15)
  384.     ja    stb02
  385.     or    al, 70h        ;internal baud clock, 16x
  386.     out    dx,al                        ;[31b] end
  387. stb02:    ret
  388.  
  389.     dseg $
  390.  
  391. ;    Serial port default parameters
  392.  
  393. mnbaud    db    0dh        ;9600 baud  [31c]
  394.  
  395. mninit    db    0        ;set to 0FFh if initialization has been done
  396. mnxseg    dw    0        ;system host interrupt vector
  397. mnxoff    dw    0
  398.  
  399. mnchnd    equ    512        ;Size of circular buffer.
  400. mnchrs    rb    mnchnd        ;Circular character buffer for input.
  401. mnchip    dw    mnchrs-1+mnchnd    ;Input pointer into character buffer.
  402. mnchop    dw    mnchrs-1+mnchnd    ;Output pointer into character buffer.
  403. mnchrn    dw    0        ;Number of chars in the buffer.
  404.  
  405. mntrg1    equ    128        ;[19a] Low trigger point for Auto XON/XOFF
  406. mntrg2    equ    384        ;[19a] High trigger point for Auto XON/XOFF
  407.  
  408. floctl    db    1        ;[19a] If floctl=floxon do Auto XON/XOFF logic
  409. xofsnt    db    0        ;[19a] set if XOFF was sent
  410. xofrcv    db    0        ;[19a] set if XOFF was recieved
  411.  
  412.     rw    32        ;Interrupt stack        ;[28e]
  413. mnstk    dw    0        ;bottom of stack        ;[28e]
  414.  
  415.     CSEG $
  416.  
  417. ; The following routines do the SET and SHOW for the machine dependent
  418. ; features of Kermit.  At present there are only two:  baud rate setting
  419. ; and port selection.
  420.  
  421. ;    This is the SET BAUD rate subcommand
  422.  
  423. bdset:    lea    dx, bdtab
  424.     lea    bx, bdhlp
  425.     mov    ah, cmkey
  426.     call    comnd
  427.      jmp    r
  428.     mov    temp1, bx
  429.     mov    ah, cmcfm
  430.     call    comnd        ;Get a confirm.
  431.      jmp    r        ; Didn't get a confirm.
  432.     mov    bx, temp1
  433.     mov    mnbaud, bl    ;Set the baud rate table index.
  434.     call    stbaud
  435.     jmp    rskp
  436.  
  437. ;    This is the SET PORT subcommand (not implemented in TEK)
  438.  
  439. prtset:    mov    ah, cmcfm
  440.     call    comnd        ;Get a confirm.
  441.      jmp    $+3        ; Didn't get a confirm.
  442.     lea    dx, infms6    ;Tell user it's not implemented
  443.     call    tcrmsg
  444.     jmp    rskp
  445.  
  446.  
  447. ; The following procedures implement the SHOW command for the system
  448. ; dependent features of baud rate and port selection.
  449.  
  450. shobd:    lea    dx, bdst    ;Baud rate string.
  451.     call    tcrmsg
  452.     mov    al, mnbaud    ;Print the keyword corresponding to the
  453.     lea    bx, bdtab    ;   current value of mnbaud.
  454.     call    tabprt
  455.     ret
  456.  
  457. shoprt:    ret            ;Port selection not implemented.
  458.  
  459.  
  460.     DSEG $
  461.  
  462. bdtab    db    16        ; 16 entries        ;[31d] begin
  463.     db    3,'110$'
  464.     dw    0003H
  465.     db    4,'1200$'
  466.     dw    0008H
  467.     db    3,'135$'
  468.     dw    0004H
  469.     db    3,'150$'
  470.     dw    0005H
  471.     db    4,'1800$'
  472.     dw    0009H
  473.     db    5,'19200$'
  474.     dw    000EH
  475.     db    4,'2000$'
  476.     dw    000AH
  477.     db    4,'2400$'
  478.     dw    000BH
  479.     db    3,'300$'
  480.     dw    0006H
  481.     db    5,'38400$'
  482.     dw    000FH
  483.     db    2,'45$'
  484.     dw    0000H
  485.     db    4,'4800$'
  486.     dw    000CH
  487.     db    2,'50$'
  488.     dw    0001H
  489.     db    3,'600$'
  490.     dw    0007H
  491.     db    2,'75$'
  492.     dw    0002H
  493.     db    4,'9600$'
  494.     dw    000DH
  495.  
  496. bdhlp    db    cr,lf,'    45    75    135    300    1200    2000    4800    19200'
  497.     db    cr,lf,'    50    110    150    600    1800    2400    9600    38400$'
  498.                                   ;[31d] end
  499. ;[31a] begin -- to end of file
  500.  
  501. ; The following routines do screen control.  These are isolated here because
  502. ; the screen control sequences are likely to vary from system to system, even
  503. ; though the Rainbow and APC (the only systems implemented to date) both use
  504. ; ANSI sequences for this purpose.
  505.  
  506.     CSEG $
  507.  
  508. ; POSCUR - positions cursor to row and col (each 1 byte) pointed to by dx.
  509.  
  510. poscur:    mov    bx, dx        ;Do ANSI cursor positioning.
  511.     mov    cl, 10
  512.     mov    al, [bx]    ;Get row value
  513.     sub    ah, ah
  514.     div    cl        ;units digit in ah, tens digit in al
  515.     add    ax, '00'    ;Convert both to ASCII
  516.     mov    word ptr anspos+2, ax    ;Save reversed (al,ah)
  517.     mov    al, 1[bx]    ;Do same for column value
  518.     sub    ah, ah
  519.     div    cl
  520.     add    ax, '00'
  521.     mov    word ptr anspos+5, ax
  522.     lea    dx, anspos    ;Print cursor positioning string.
  523.     call    tmsg
  524.     ret
  525.  
  526. ; CLRSCR - homes cursor and clears screen.
  527.  
  528. clrscr:    lea    dx, anscls
  529.     call    tmsg
  530.     ret
  531.  
  532. ; CLRLIN - clears from cursor to end of line.
  533.  
  534. clrlin:    mov    dl, cr        ;Go to beginning of line
  535.     call    bout
  536. clreol:    lea    dx, ansclr    ;Clear from cursor to end of line
  537.     call    tmsg
  538.     ret
  539.  
  540. ; REVON - turns on reverse video display
  541.  
  542. revon:    lea    dx, ansron
  543.     call    tmsg
  544.     ret
  545.  
  546. ; REVOFF - turns off reverse video display
  547.  
  548. revoff:    lea    dx, ansrof
  549.     call    tmsg
  550.     ret
  551.  
  552. ; BLDON - turns on bold (highlighted) display
  553.  
  554. bldon:    lea    dx, ansbon
  555.     call    tmsg
  556.     ret
  557.  
  558. ; BLDOFF - turns off bold (highlighted) display
  559.  
  560. bldoff:    lea    dx, ansbof
  561.     call    tmsg
  562.     ret
  563.  
  564. ; ANSMOD - enters ANSI mode from Tek mode
  565.  
  566. ansmod:    lea    dx, ansion
  567.     call    tmsg
  568.     ret
  569.  
  570.     DSEG $
  571.  
  572. anspos    db    esc,'[00;00H$'        ;Position cursor to row and column
  573. anscls    db    esc,'[H',esc,'[J$'    ;Home cursor and clear screen
  574. ansclr    db    esc,'[K$'        ;Clear from cursor to end of line
  575. ansron    db    esc,'[7m$'        ;Turn on reverse video
  576. ansrof    db    esc,'[m$'        ;Turn off reverse video
  577. ansbon    db    esc,'[1m$'        ;Turn on bold (highlight) display
  578. ansbof    db    esc,'[m$'        ;Turn off bold display
  579. ansion    db    esc,'%!1$'        ;SelectCode Ansi mode
  580.  
  581. ; Here tab expansion is done if necessary.  If not, just return retskp.
  582.  
  583.     CSEG $
  584. dotab:    jmp rskp
  585.  
  586.     DSEG $
  587. delstr    db    ' ',10O,10O,'$'    ;Delete string.
  588.  
  589. system    db    '                 Tektronix 4170$'
  590.