home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / test / pdp11 / krtxmo.mac < prev   
Text File  |  1996-10-17  |  16KB  |  501 lines

  1.     .title    KRTXMO    XMODEM, SEND command interface
  2.     .ident    "V04.64"
  3.  
  4. ; /E64/    07-Apr-96  John Santos
  5. ;
  6. ;    Conditionalize for RSTS.  Make c$send work, and remove XMODEM, which
  7. ;    I currently have no way of testing, and which has lots of RT11
  8. ;    calls built into it.
  9. ;    Check for errors after calling fparse.  (This only occurs in code
  10. ;    that is conditionalized for RT11, but I put it in so we don't
  11. ;    forget to do this if/when RSTS ever supports xmodem.)
  12.  
  13. ; /63/    29-Jan-96  Billy Youdelman
  14. ;
  15. ;    disallow sends from TT (not supported, makes Kermit hang)..
  16.  
  17. ; /62/    27-Jul-93  Billy Youdelman  V03.62
  18. ;
  19. ;    move command interface here from KRTCM1
  20.  
  21. ; /BBS/     1-Dec-91  Billy Youdelman  V03.61
  22. ;
  23. ; This module uses xmodem written by Chuck Sadoian, Dinuba, CA
  24.  
  25. ; Xmodem here supports either checksum or CRC error detection, however it
  26. ; only does so one file at a time, using 128 byte blocks, under TSX-Plus.
  27. ; Transmission is presently only on the controlling terminal (this Kermit
  28. ; must be the remote system) and is also SEND-only from here to the other
  29. ; system, because the TSX-Plus terminal handler does not pass nulls (zero
  30. ; bytes) to a running program.
  31. ;
  32. ; The Xmodem protocol requires an 8-bit path.  If this isn't the system's
  33. ; default, you must from KMON issue the command SET TT 8BIT,BITS=8 before
  34. ; running Kermit.  "BITS=8" is a hardware parameter and must be done on a
  35. ; primary line only.  Setting it on a subprocess may write garbage in the
  36. ; line_parameters word, rendering the line useless.
  37. ;
  38. ; Xmodem doesn't work under RT-11 because RT strips all terminal I/O data
  39. ; of the high order (parity) bit, thus preventing an 8-bit data path from
  40. ; being used.
  41.  
  42.  
  43.     .include "IN:KRTMAC.MAC"
  44.     .iif ndf  KRTINC  .error    <; .include for IN:KRTMAC.MAC failed>
  45.     .include "IN:KRTDEF.MAC"
  46.     .iif ndf  MSG$DA  .error    <; .include for IN:KRTDEF.MAC failed>
  47.  
  48.     .mcall    .CMKT    ,.MRKT    ,.PURGE    ,.SCCA
  49.     .mcall    .READW    ,.TTINR    ,.TTYOUT,.TWAIT
  50.  
  51.  
  52.     .macro    beep2
  53.     wrtall    #$beep2            ; make the terminal beep twice
  54.     .endm    beep2
  55.  
  56.  
  57.     .sbttl    Local data
  58.  
  59.     ACK    = 6            ; acknowledge packet (ok)
  60.     CAN    = 30            ; cancel transfer
  61.     CRC    = 1            ; bit mask CRC enabled
  62.     EOT    = 4            ; end of transmission
  63.     NAK    = 25            ; negative acknowledge (not ok)
  64.     NKWAIT    = 13.            ; initial wait for first NAK in secs
  65.  
  66.     .psect    xmodat    ,rw,d,lcl,rel,con
  67. .if df    RT11                ; /E64/
  68. aflag:    .word    0            ; abort flag
  69. blkcnt:    .word    0            ; for .readw, block just read
  70. block:    .word    0            ; file size in RT-11 blocks
  71. bytcnt:    .word    0            ; number of bytes in input buffer
  72. chksum:    .word    0            ; checksum
  73. hieff:    .byte    0 ,120            ; high efficiency terminal mode emt
  74. marea:    .word    0 ,0 ,0 ,0        ; .mrkt work area
  75. mtime:    .word    0 ,0            ; nkwait in ticks lives here
  76. nosingle:.byte    0 ,152
  77.     .word    'T&137,0        ; turn off single char mode
  78. onewide:.byte    0 ,152
  79.     .word    'Q&137,1        ; /62/ activate on field width of 1
  80. point:    .word    0            ; pointer to read buffer
  81. rbuff:    .word    0            ; input file buffer pointer
  82. single:    .byte    0 ,152
  83.     .word    'S&137,0        ; turn on single char mode
  84. sizbuf:    .byte    0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ; ascii'd size in xmodem blocks
  85. tflag:    .word    0            ; time-out flag
  86. ttctlc:    .word    0 ,0 ,0            ; for .scca
  87. wtime:    .word    0 ,6            ; 1/10 second (slightly more @ 50Hz)
  88. xblock:    .word    0 ,0            ; file size in xmodem blocks
  89. xmosts:    .word    0            ; status word
  90. xrecno:    .word    0            ; record number for packets
  91. xtime:    .word    0 ,30.            ; wait 0.5sec when finished or abort
  92. .endc    ;RT11                ; /E64/
  93.  
  94.     .psect    $pdata            ; /63/ consolidate here..
  95. $beep2:    .byte    bell ,bell ,0        ; two bells
  96. sen.10:    .asciz    <bell>"Send completed"    ; /62/
  97. sen.11:    .asciz    <bell>"Send failed"
  98. sen.12:    .asciz    'Processing file name "'
  99. sen.13:    .asciz    '"'
  100. .if df    RT11                ; /E64/
  101. xmo.01:    .asciz    "File open: "        ; tell user about the file
  102. xmo.02:    .asciz    "["            ; size in RT-11 blocks goes here
  103. xmo.03:    .asciz    "], "            ; format the display
  104. xmo.04:    .ascii    " Xmodem (128 byte) blocks"<cr><lf>    ; tag file size
  105.     .asciz    "Awaiting ready signal (^X aborts).."    ; ready to rip..
  106. xmo.05:    .asciz    "File transfer completed"
  107. .endc    ;RT11                ; /E64/
  108.     .even
  109.  
  110.  
  111.     .psect    $code
  112.     .sbttl    Send file(s)        ; /BBS/ somewhat modified..
  113.                     ; /62/ moved here for smaller root
  114. c$send::clr    wasmore            ; init multi-args display flag
  115.     tst    inopn            ; is an input file currently open?
  116.     beq    10$            ; no
  117.     calls    close    ,<#lun.in>    ; yes, please close old file up
  118. 10$:    mov    argbuf    ,r1        ; address of command line buffer
  119.     tstb    @r1            ; anything there?
  120.     beq    20$            ; no
  121.     call    isitas            ; SEND file asfile?  get asname
  122.     tst    r0            ; any parse error?
  123.     beq    30$            ; no
  124. 20$:    mov    #er$snd    ,r0        ; emit a syntax error message
  125.     br    50$            ; goto error handler
  126.  
  127. 30$:    calls    chk.tt    ,<#srcnam>    ; /63/ disallow TT as an input dev
  128.     tst    r0            ; /63/ well?
  129.     bne    50$            ; /63/ it was TT
  130.     tst    wasmore            ; working with more than 1 file?
  131.     beq    40$            ; no
  132.     calls    printm    ,<#3,#sen.12,#srcnam,#sen.13> ; ya, say which it is
  133. 40$:    upcase    #srcnam            ; upper case the input file name
  134.     tst    remote            ; in remote mode?
  135.     beq    70$            ; no
  136.     clr    index            ; /62/ init lookup's file counter
  137.     calls    lookup    ,<#srcnam,#spare1> ; /62/ look for something to do
  138.     tst    r0            ; /62/ well?
  139.     beq    60$            ; /62/ at least one file exists
  140.     cmp    r0    ,#er$nmf    ; if error is "No more files"
  141.     bne    50$            ; then make it say
  142.     mov    #er$fnf    ,r0        ; "File not found"
  143. 50$:    direrr    r0            ; emit an error message
  144. .if df    RT11                ; /E64/
  145.     .purge    #lun.sr            ; /62/ hose dir search channel
  146. .endc    ;RT11                ; /E64/
  147.     br    130$            ; go say it's over..
  148.  
  149. 60$:    calls    suspend    ,<sendly>    ; allow time to start REC at other end
  150.  
  151. 70$:    call    opentt            ; open and initialize the link
  152.     tst    r0            ; did it work?
  153.     bne    120$            ; no, error displayed by ttyini
  154.     call    cantyp            ; flush any accumulated NAKs
  155. 80$:    calls    xbinread,<#-1>        ; /63/ read with no wait to flush
  156.     tst    r0            ; /63/ any possible junk in buffer
  157.     beq    80$            ; /63/ loop until nothing remains
  158.     tst    locase            ; SET FIL NAM LOWER-CASE?
  159.     bne    90$            ; ya, leave output file name..
  160.     upcase    #asname            ; no, make it upper case
  161. 90$:    clr    index            ; /62/ wildcard_file_number := 0
  162.     call    getnxt            ; get the first file name please
  163.     tst    r0            ; did it work?
  164.     bne    120$            ; no, getnxt has sent the error packet
  165.     mov    sp    ,inprogress    ; packets are being exchanged
  166.     calls    sensw    ,<#msg$snd>    ; now send the file
  167.     tst    r0            ; did it work?
  168.     bne    120$            ; no
  169.     mov    nextone    ,r0        ; ya, any more arguments to process?
  170.     bne    100$            ; ya, go do it
  171.     calls    printm    ,<#1,#sen.10>    ; no, done
  172.     br    140$            ; note r0 is clear here too
  173. 100$:    cmpb    (r0)    ,#space        ; is first byte a blank?
  174.     bne    110$            ; no
  175.     inc    r0            ; ya, skip past it
  176.     br    100$            ; and check what is now the first byte
  177. 110$:    copyz    r0 ,argbuf ,#ln$max    ; pull up remaining args to top of buf
  178.     jmp    10$            ; /63/ loop back for more
  179.  
  180. 120$:    calls    printm    ,<#1,#sen.11>    ; it failed, say so if local
  181. 130$:    inc    status            ; /45/ flag for batch exit
  182. 140$:    clrb    asname            ; /36/ ensure no more alternate names
  183.     call    clostt            ; release the link
  184.     jmp    clrcns            ; /62/ flush TT input, clear r0
  185.  
  186.  
  187.     .sbttl    XMODEM a file        ; /62/ moved this here too..
  188.  
  189. .if df    RT11                ; /E64/
  190. c$xmodem::tst    tsxsav            ; send only, via TT only
  191.     bne    10$            ; must be TSX for this to work
  192.     mov    #er$tsx    ,r0        ; say it's not TSX
  193.     br    60$            ; goto error handler
  194.  
  195. 10$:    tst    inopn            ; input file currently open?
  196.     beq    20$            ; no
  197.     calls    close    ,<#lun.in>    ; yes, please close old file first
  198. 20$:    upcase    argbuf            ; upper case all command args
  199.     mov    argbuf    ,r1        ; address of command line buffer
  200.     tstb    @r1            ; anybody home?
  201.     bne    30$            ; ya
  202.     mov    er$wld    ,r0        ; no, point to err msg
  203.     beq    60$            ; goto error message output
  204. 30$:    mov    #srcnam    ,r2        ; where to store file name
  205. 40$:    movb    (r1)+    ,(r2)+        ; copy the name over
  206.     beq    50$            ; can't XMODEM file asfile
  207.     cmpb    @r1    ,#space        ; so stop at first space
  208.     bgt    40$            ; next byte
  209.     clrb    @r2            ; ensure source name is asciz
  210. 50$:    calls    iswild    ,<#srcnam>    ; check for wildcarding
  211.     tst    r0            ; if .ne., then wildcarded
  212.     bne    60$            ; can't process wildcards
  213.     calls    fparse,<#srcnam,#filnam>  ; parse file name
  214. ;.if df    RSTS                ; /E64/
  215. ;    tst    r0            ; /E64/ if access restricted
  216. ;    bne    60$            ; /E64/ then die
  217. ;.endc    ;RSTS                ; /E64/
  218.     calls    open,<#filnam,#lun.in,#binary>  ; try to open the file
  219.     tst    r0            ; did it work?
  220.     beq    70$            ; ya..
  221. 60$:    direrr    r0            ; no.. print mapped error msg
  222.     call    incsts            ; /62/ set global error flag
  223.     br    80$            ; and bail out
  224.  
  225. 70$:    call    x$modem            ; run xmodem
  226.     calls    close    ,<#lun.in>    ; close file
  227.     .newline            ; ensure prompt is on a newline
  228. 80$:    clr    r0            ; any error was already handled
  229.     return
  230. .endc    ;RT11                ; /E64/
  231.  
  232. .if df    RSTS                ; /E64/
  233. c$xmodem::mov    #er$uns    ,r0        ; /E64/  say it's unsupported
  234.     direrr    r0            ; /E64/
  235.     call    incsts            ; /E64/ set global error flag
  236.     clr    r0            ; /E64/ any error was already handled
  237.     return                ; /E64/
  238. .endc    ;RSTS                ; /E64/
  239.  
  240.     .sbttl    Initialization
  241.  
  242. .if df    RT11                ; /E64/
  243. x$modem:.scca    #ttctlc    ,#ttctlc+4    ; /62/ off ^C
  244.     .cmkt    #marea    ,#40        ; and setcc's mark timer
  245.     clr    xmosts            ; clear status word
  246.     wrtall    #xmo.01            ; /63/ "File open: "
  247.     wrtall    #filnam            ; print file specification
  248.     wrtall    #xmo.02            ; /63/ "["
  249.     mov    #lun.in    ,r4        ; get I/O channel number
  250.     asl    r4            ; word indexing
  251.     mov    sizof(r4),r0        ; /63/ recover the file size
  252.     call    L10266            ; /63/ dump it to the terminal
  253.     wrtall    #xmo.03            ; /63/ "], "
  254.     mov    buflst(r4),rbuff    ; file input buffer pointer
  255.     mov    sizof(r4),r1        ; get file size
  256.     mov    r1    ,block        ; save size of file in blocks
  257.     clr    r0            ; clear hi word
  258.     asl    r1            ; non-eis
  259.     adc    r0            ; 32-bit
  260.     asl    r1            ; multiply
  261.     adc    r0            ; by four
  262.     mov    r0    ,xblock        ; save hi word
  263.     mov    r1    ,xblock+2    ; save low word
  264.     clr    r2            ; suppress leading 0s in $cddmg output
  265.     mov    #xblock    ,r1        ; address of 32-bit number
  266.     mov    #sizbuf    ,r0        ; address of out buff for ascii
  267.     call    $cddmg            ; convert 32-bit integer to ascii
  268.     clrb    @r0            ; null terminate the string
  269.     wrtall    #sizbuf            ; and dump it to TT
  270.     wrtall    #xmo.04            ; /63/ tag & say awaiting ready signal
  271.     call    l$nolf            ; /63/
  272.  
  273.     mov    #nosingle,r0        ; single char input dies in hieff mode
  274.     emt    375            ; if activation chars are declared
  275.     calls    t.ttyini,<#0>        ; init TT
  276.     movb    #1    ,hieff        ; setup high efficiency emt
  277.     mov    #hieff    ,r0
  278.     emt    375            ; do it
  279.  
  280.     call    waitnk            ; look for the initial NAK
  281.     tst    aflag            ; error detected?
  282.     bne    abort            ; yes, kill transfer
  283.     clr    blkcnt            ; clear block count
  284.     mov    #1    ,xrecno        ; init xmodem block count
  285.     .br    dnload            ; /63/
  286.  
  287. .endc    ;RT11                ; /E64/
  288.  
  289.     .sbttl    Download
  290.  
  291. .if df    RT11                ; /E64/
  292. dnload:    call    rdblk            ; read some input
  293.     bcs    eof            ; branch if EOF
  294. 10$:    call    sndblk            ; send a checksummed block
  295.     call    getack            ; look for ACK from remote
  296.     tst    aflag            ; check result from receiver
  297.     beq    20$            ; zero is an ACKed block
  298.     cmp    #1    ,aflag        ; 1 means we NAKed it
  299.     beq    10$            ; so send it again
  300.     jmp    abort            ; else we abort the transfer
  301. 20$:    inc    xrecno            ; bump record number
  302.     add    #128.    ,point        ; update buffer pointer
  303.     cmp    point    ,bytcnt        ; are we at the end of buffer?
  304.     beq    dnload            ; yes, then better read in some more
  305.     br    10$            ; else go send another block
  306.  
  307. .endc    ;RT11                ; /E64/
  308.  
  309.     .sbttl    End of file processing
  310.  
  311. .if df    RT11                ; /E64/
  312. eof:    mov    #eot    ,r0        ; send end of transmission
  313.     .ttyout
  314.     call    getack            ; wait for an acknowledgment
  315.     tst    aflag            ; check result
  316.     beq    10$            ; zero means all ok!
  317.     cmp    #1    ,aflag        ; 1 means they NAKed it
  318.     beq    eof            ; so try it again
  319.     br    abort            ; else we need to abort
  320. 10$:    beep2
  321.     .newline
  322.     wrtall    #xmo.05            ; /63/ "File transfer completed"
  323.     br    reset            ; and reset parameters
  324.  
  325. .endc    ;RT11                ; /E64/
  326.  
  327.     .sbttl    Clean up and exit Xmodem
  328.  
  329. .if df    RT11                ; /E64/
  330. abort:    beep2
  331.     .newline
  332.     direrr    #er$abt            ; aborting transfer..
  333.  
  334. reset:    .twait    #rtwork    ,#xtime        ; wait for remote to come back
  335. 10$:    mov    #onewide,r0        ; kludge single char input
  336.     emt    375
  337.     .ttinr                ; suck up garbage
  338.     bcc    10$
  339.     clrb    hieff            ; set emt argument off hi eff mode
  340.     mov    #hieff    ,r0
  341.     emt    375            ; do it
  342.     call    ttyrst            ; use existing TT reset stuff
  343.     mov    #single    ,r0        ; restore single char input mode
  344.     emt    375
  345.     clr    r0            ; no errors passed back..
  346.     return
  347.  
  348. .endc    ;RT11                ; /E64/
  349.  
  350.     .sbttl    Wait for initial NAK from remote
  351.  
  352. .if df    RT11                ; /E64/
  353. waitnk:    clr    aflag            ; clear abort flag
  354.     mov    #nkwait*60.,mtime+2    ; wait for preset time
  355.     call    stimer            ; start the timer
  356. 10$:    mov    #onewide,r0        ; kludge single char input
  357.     emt    375
  358.     .ttinr                ; pick up a character
  359.     bcc    20$            ; did we get something?
  360.     tst    tflag            ; no, did we time-out?
  361.     bne    30$            ; yes, we should abort this
  362.     .twait    #rtwork    ,#wtime        ; else sleep a bit, so we don't burn
  363.     br    10$            ; up the cpu time.  Then check again
  364. 20$:    cmpb    r0    ,#nak        ; did we get a NAK?
  365.     beq    40$            ; yes, return normally
  366.     cmpb    r0    ,#can        ; cancel transmission?
  367.     beq    30$            ; yes, abort this
  368.     cmpb    r0    ,#'C&137    ; CRC checksum request?
  369.     bne    10$            ; nope
  370.     bis    #crc    ,xmosts        ; ya, enable CRC mode
  371.     br    40$
  372. 30$:    com    aflag            ; else set abort
  373.     br    50$
  374. 40$:    clr    aflag            ; clear abort
  375. 50$:    .cmkt    #marea    ,#41        ; cancel timer
  376.     return
  377.  
  378. .endc    ;RT11                ; /E64/
  379.  
  380.     .sbttl    Wait for ACK from remote
  381.  
  382. .if df    RT11                ; /E64/
  383. getack:    clr    aflag            ; clear abort flag
  384. 10$:    mov    #onewide,r0        ; kludge single char input
  385.     emt    375
  386.     .ttinr                ; pick up a character
  387.     bcc    20$            ; did we get something?
  388.     .twait    #rtwork    ,#wtime        ; no, sleep a bit, don't burn cpu time
  389.     br    10$            ; then check again
  390. 20$:    cmpb    r0    ,#ack        ; did we get an ACK?
  391.     beq    40$            ; yes, return normally
  392.     cmpb    r0    ,#nak        ; did we get a NAK?
  393.     beq    30$            ; yes
  394.     cmpb    r0    ,#can        ; cancel?
  395.     bne    10$            ; no, keep looking
  396.     mov    #2    ,aflag        ; else set abort
  397.     return
  398. 30$:    mov    #1    ,aflag        ; set aflag to 1
  399.     return
  400. 40$:    clr    aflag            ; clear abort
  401.     return
  402.  
  403. .endc    ;RT11                ; /E64/
  404.  
  405.     .sbttl    Send a checksummed block to the remote
  406.  
  407. .if df    RT11                ; /E64/
  408. sndblk:    clr    chksum            ; clear checksum
  409.     clr    r3            ; clear CRC
  410.     mov    rbuff    ,r1        ; get address of read buffer
  411.     add    point    ,r1        ; add in offset
  412.     mov    #soh    ,r0        ; send a SOH
  413.     .ttyout
  414.     mov    xrecno    ,r0        ; send record number
  415.     .ttyout
  416.     com    r0            ; send complement of record #
  417.     .ttyout
  418.     mov    #128.    ,r2        ; initialize counter
  419. 10$:    movb    (r1)+    ,r0        ; get next byte
  420.     add    r0    ,chksum        ; update checksum
  421.     call    updcrc            ; update CRC
  422.     .ttyout                ; send it
  423.     sob    r2    ,10$        ; finished?
  424.     mov    chksum    ,r0        ; copy of checksum to send
  425.     bit    #crc    ,xmosts        ; CRC enabled?
  426.     beq    20$            ; no
  427.     call    getcrc            ; get the CRC value
  428.     swab    r0            ; high byte first
  429.     .ttyout
  430.     swab    r0            ; then low byte
  431. 20$:    .ttyout                ; send checksum
  432.     return
  433.  
  434. .endc    ;RT11                ; /E64/
  435.  
  436.     .sbttl    Read a block from the input file
  437.  
  438. .if df    RT11                ; /E64/
  439. rdblk:    clr    point            ; clear pointer
  440.     .readw    #rtwork,#lun.in,rbuff,#256.,blkcnt
  441.     bcs    20$            ; /63/ if EOF...
  442.     asl    r0            ; words to bytes, carry is clear here
  443.     mov    r0    ,bytcnt        ; and store it
  444.     inc    blkcnt            ; update block cnt, carry still clear
  445. 10$:    return                ; /63/ return with carry bit intact
  446.  
  447. 20$:    movb    @#errbyt,r0        ; make sure it is EOF
  448.     beq    10$            ; /63/ yes it is, carry is already set
  449.     asl    r0            ; not EOF, use word indexing to
  450.     mov    reaerr(r0),r0        ; point to error message text
  451.     .newline            ; ensure starting on a fresh line
  452.     direrr    r0            ; we had a read error!
  453.     beep2                ; this doesn't preserve r0..
  454.     jmp    reset            ; exit the program
  455.  
  456. .endc    ;RT11                ; /E64/
  457.  
  458.     .sbttl    Schedule a completion routine
  459.  
  460. .if df    RT11                ; /E64/
  461. stimer:    .cmkt    #marea    ,#41        ; cancel possible outstanding request
  462.     clr    tflag            ; clear timout flag
  463.     .mrkt    #marea    ,#mtime    ,#timout,#41 ; issue a timer request
  464.     return
  465. timout:    com    tflag            ; set timout flag to indicate time-out
  466.     return
  467.  
  468. .endc    ;RT11                ; /E64/
  469.  
  470.     .sbttl    Update CRC, routine from Steve Brecher's COM program
  471.  
  472. .if df    RT11                ; /E64/
  473. ; Update CRC in r3 with datum in the low byte of r0.  Registers preserved.
  474. ;
  475. ; Algorithm:    for each data bit from bit 7 to bit 0, shift the bit
  476. ;        into the LSB of the CRC.  If 1 shifts out of MSB of CRC,
  477. ;        XOR the CRC with the constant.
  478.  
  479. CON    = 10041        ;constant = 1021 hex, for CCITT, recommended
  480.             ;polynomial of x**16 + x**12 + x**5 + 1
  481.  
  482. updcrc:    save    <r0,r1,r2>
  483.     mov    #con    ,r2        ; the constant
  484.     mov    #8.    ,r1        ; number of data bits
  485. 10$:    rolb    r0            ; rotate left, byte mode
  486.     rol    r3            ; rotate left, word mode
  487.     bcc    20$            ; nothing shifted out of msb
  488.     xor    r2    ,r3        ; something shifted out, fix it
  489. 20$:    sob    r1    ,10$        ; next data bit
  490.     unsave    <r2,r1,r0>
  491.     return
  492.  
  493. getcrc:    clr    r0            ; after all data have passed through
  494.     call    updcrc            ; updcrc, call this routine to get the
  495.     call    updcrc            ; final CRC, for transmission, into r0
  496.     mov    r3    ,r0
  497.     return
  498. .endc    ;RT11                ; /E64/
  499.  
  500.     .end
  501.