home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / b / krtxmo.mac < prev    next >
Text File  |  2020-01-01  |  15KB  |  453 lines

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