.enabl lc .dsabl gbl .title XMODEM .ident /1.0/ .nlist bex ; 23-Apr-88 11:59:00 Billy Y ; It should be noted that for proper operation of this program one must ; SET TT BITS=8,8BIT Billy Y. ; ; 1-May-88 20:53:00 Billy Y ; Modified rwait to 2.0 secs. Added code to hold off .com file till exit. ; ; Xmodem file transfer program, for TSX-Plus version 5.1 or later, ; when the command SET TT EIGHTBIT is available. Will not function ; properly under RT-11 due to the fact RT-11 normally strips all ; terminal I/O data of the high order (parity) bit, thus preventing ; an 8 bit data path from being used. ; Due to the fact that nulls [zero bytes] cannot be passed to the ; running TSX-plus program via the terminal handler, this program ; cannot be used to accept UPLOADs of Xmodem files. Will only ; function in the DOWNLOAD mode. ; Created by: Chuck Sadoian ; 821 Newton Drive ; Dinuba, CA 93618 ; (209) 591-2631 ; Version 1.0 14-June-86 ; macro definitions .mcall .print,.exit,.lookup,.ttyout,.scca .mcall .ttinr,.gtlin,.close,.purge .mcall .readw,.twait,.csispc,.cmkt,.mrkt ; define usefull macros .macro crlf .print #crlf .endm .macro call subr jsr pc,subr .endm .macro return rts pc .endm .macro push reg mov reg, -(sp) .endm .macro pop reg mov (sp)+, reg .endm ; define some stuff for xmodem soh = 1 ;start of header eot = 4 ;end of transmission ack = 6 ;acknowledge packet (ok) nak = 25 ;negative acknowledge (not ok) can = 30 ;cancel transfer nkwait = 60. ;initial wait for first nak (sec) rwait = 2. ;wait after abort or complete xfer\BY\ ; misc definitions del = 177 ;delete key cr = 15 ;carriage return lf = 12 ;line feed bs = 10 ;backspace bell = 7 ;bell space = 40 ;space comma = 54 ;comma jsw = 44 ;rt11 job status word rmon = 54 ;address of resident monitor sysgen = 372 ;sysgen option word channel = 2 ;i/o channel errbyt = 52 ;error byte location crc = 1 ;bit mask CRC enabled .csect main start: .print #prgnam ;Sign on mov rmon,r1 ;we need to check for TSX-Plus tst sysgen(r1) ;is the proper bit set? bmi 10$ ;yes, then this is at least 5.0 .print #msg1 ;else inform user we won't run jmp exit 10$: mov #single,r0 ;set single character activation emt 375 mov #nowait,r0 ;put job in nowait mode for input emt 375 .scca #sarea,#ctrlc ;inhibit ctrlc begin: clr status ;clear status word .gtlin #buffer,#prompt ;Get some input to start us out mov #buffer,r1 ;get address of buffer cmpb (r1),cr ;Did user enter a cr? bne 10$ ;no jmp exit ;Yes, exit the program 10$: mov #cstrng,r2 ;point to csi input buffer mov r1,r3 ;save starting address add #15.,r3 ;limit of user input 20$: cmpb (r1),cr ;end of input? beq 30$ movb (r1)+,(r2)+ cmp r1,r3 ;limit? bne 20$ jmp limit 30$: movb #'=,(r2)+ clrb (r2) mov r2,eos ;save end of string mov #cstrng,r1 ;point to buffer mov sp,r2 ;save stack .csispc #csi,#deftxt,r1 ;process filename mov r2,sp ;restore stack bcc 40$ ;skip if no error .print #msg3 ;Error on filename br begin ;try again 40$: .lookup #area,#channel,#csi ;lookup the file bcc 50$ ;is it there? .print #msg4 ;file not found br begin ;start again 50$: mov r0,block ;save size of file in blocks asl r0 ;figure xmodem 128 byte blocks asl r0 ;(multiply by 4) mov r0,xblock ;and save it mov eos,r0 ;remember end of filespec movb #200,-(r0) ;get rid of the = so we can print it .print #msg5 ;tell user about the file .print #cstrng ;print filename .ttyout #comma ;and a comma .ttyout #space ;and a space mov xblock,r0 ;remember size of file in xmodem blks call prtdec ;print it .print #msg6 ;tell user we are ready! .print #msg6a .print #msg6b bis #10100,@#jsw ;put keyboard in single char/nowait movb #1,hieff ;code to turn on high efficiency mov #hieff,r0 ;turn on high efficiency mode emt 375 call waitnk ;look for the initial nak tst aflag ;error detected? bne abort ;yes, kill transfer clr blkcnt ;clear block count mov #1,xrecno ;init xmodem block count dnload: call rdblk ;read some input bcs eof ;branch if eof 10$: call sndblk ;send a checksummed block call getack ;look for ack from remote tst aflag ;check result from receiver beq 20$ ;zero is an acked block cmp #1,aflag ;1 means we naked it beq 10$ ;so send it again jmp abort ;else we abort the transfer 20$: inc xrecno ;bump record number add #128.,point ;update buffer pointer cmp point,bytcnt ;are we at the end of buffer? beq dnload ;yes, then better read in some more jmp 10$ ;else go send another block eof: mov #eot,r0 ;send end of transmission .ttyout call getack ;wait for an acknowledgement tst aflag ;check result beq 10$ ;zero means all ok! cmp #1,aflag ;1 means they naked it beq eof ;so try it again jmp abort ;else we need to abort 10$: .print #msg8 ;file transfer completed jmp reset ;and reset paramenters limit: .print #msg2 ;Input line too long! jmp begin abort: .print #msg7 ;tell use we have aborted reset: .twait #warea,#xtime ;wait for remote to come back 10$: .ttinr ;suck up garbage bcc 10$ .purge #channel ;dump the i/o channel bic #10100,@#jsw ;clear nowait bit clrb hieff ;turn off high efficiency mode mov #hieff,r0 emt 375 jmp begin ;and try it again exit: .print #letgo ;enable .com file input on exit \BY\ .exit ; waitnak - waits for initial nak from remote waitnk: clr aflag ;clear abort flag mov #nkwait*60.,mtime+2 ;wait for preset time call stimer ;start the timer 10$: .ttinr ;pick up a character bcc 30$ ;did we get something? tst tflag ;no, did we time-out? bne 40$ ;yes, we should abort this 20$: .twait #warea,#wtime ;else sleep a bit, so we don't burn br 10$ ;up the cpu time. Then check again 30$: cmpb r0,#nak ;did we get a nak? beq 50$ ;yes, return normally cmpb r0,#can ;cancel transmission? beq 40$ ;yes, abort this cmpb r0,#'C ;Checksum request? bne 10$ bis #crc,status ;indicate CRC mode br 50$ 40$: com aflag ;else set abort br 60$ 50$: clr aflag ;clear abort 60$: .cmkt #marea,#0 ;cancel timer return ; getack - waits for ack from remote getack: clr aflag ;clear abort flag 10$: .ttinr ;pick up a character bcc 20$ ;did we get something? .twait #warea,#wtime ;else sleep a bit, so we don't burn br 10$ ;up the cpu time. Then check again 20$: cmpb r0,#ack ;did we get an ack? beq 40$ ;yes, return normally cmpb r0,#nak ;did we get a nak? beq 30$ ;yes cmpb r0,#can ;cancel? bne 10$ ;no, keep looking mov #2,aflag ;else set abort return 30$: mov #1,aflag ;set aflag to 1 return 40$: clr aflag ;clear abort return ; sndblk - send a checksummed block to the remote sndblk: clr chksum ;clear checksum clr r3 ;clear crc mov #rbuff,r1 ;get address of read buffer add point,r1 ;add in offset mov #soh,r0 ;send a soh .ttyout mov xrecno,r0 ;send record number .ttyout com r0 ;send complement of record # .ttyout mov #128.,r2 ;initialize counter 10$: movb (r1)+,r0 add r0,chksum ;update checksum call updcrc ;update crc .ttyout ;send it sob r2,10$ ;finished? 20$: mov chksum,r0 bit #crc,status ;crc enabled? beq 30$ call getcrc ;get the crc value swab r0 ;high byte first .ttyout swab r0 ;then low byte 30$: .ttyout ;send checksum return ; rdblk - read 10 blocks from the input file rdblk: clr point ;clear pointer .readw #rarea,#channel,#rbuff,#256.*10.,blkcnt bcs 10$ ;if eof... asl r0 ;convert word count to byte count mov r0,bytcnt ;and store it add #10.,blkcnt ;update block count clc ;clear carry return 10$: tstb @#errbyt ;make sure it is EOF beq 20$ ;yes it is .print #msg9 ;we had a read error! jmp exit ;exit the program 20$: sec ;make sure carry it set return ; stimer - schedule a completion routine stimer: .cmkt #marea,#0 ;first, cancel outstanding requests clr tflag ;clear timout flag .mrkt #marea,#mtime,#timout,#1;issue a timer request return timout: com tflag ;set timout flag to indicate time-out return ; updcrc - updates CRC, routine from Steve Brecher's COM program con = 10041 ;constant = 1021 hex, for CCITT ;recomdended ;polynomial of x**16 + x**12 + x**5 + 1. ; Update CRC in R3 with data byte in r0 low half; regs preserved ; ; Algorithm: for each data bit from bit 7 to bit 0, shift the bit ; into the LSB of the CRC. If 1 shifts out of MSB of CRC, ; xor the CRC with the constant. updcrc: push r0 ;save some registers push r1 push r2 mov #con,r2 mov #8.,r1 1$: rolb r0 rol r3 bcc 2$ xor r2,r3 2$: sob r1,1$ pop r2 pop r1 pop r0 return ; getcrc After CRC has been initialized and all error-free data byte ; passed through UPDCRC, call this routine to get the final ; CRC, for transmission, into R0. getcrc: clr r0 call updcrc call updcrc mov r3,r0 return ; Print the decimal value of the word in r0 prtdec: push r1 ;save r1 and r2 push r2 mov #bufend,r2 ;point to end of output buffer mov r0,r1 ;set up for divide 10$: clr r0 ;clear high word for divide div #10.,r0 ;get least significant digit add #'0,r1 ;make remainder into ASCII movb r1,-(r2) ;save digit in output buffer mov r0,r1 ;set up for next divide bne 10$ ;Until nothing left .print r2 ;display number at terminal pop r2 ;restore r1 and r2 pop r1 ; return .blkb 5 ;5 character output buffer bufend: .byte 200 ;no cr for the .print .even prgnam: .byte 35,116 ;hold off .com file \BY\ .asciz "Xmodem V1.0 14-June-86" crlf: .ascii <200> prompt: .ascii "Enter filename to download [Return to end]: "<200> msg1: .asciz "?XMODEM-F-Cannot run under RT11 monitor" msg2: .asciz "?XMODEM-E-Input line too long" msg3: .asciz "?XMODEM-E-Invalid filename specified" msg4: .asciz "?XMODEM-E-File not found" msg5: .ascii "File open: "<200> msg6: .asciz " Xmodem blocks." msg6a: .asciz "[to abort type a few ^X and wait 2 secs for time out]" msg6b: .asciz "Awaiting ready signal... " msg7: .asciz "?XMODEM-E-Aborting transfer" msg8: .asciz "File transfer completed" msg9: .asciz "?XMODEM-F-File read error" letgo: .byte 35,117 ;enable .com file \BY\ .even csi: .blkw 39. ;area for CSI to use deftxt: .word 0 ;no default extensions .word 0 .word 0 .word 0 area: .blkw 3 ;for .lookup marea: .blkw 4 ;area for the .mrkt request mtime: .word 0,0 ;timer interval warea: .blkw 2 ;area for .twait request wtime: .word 0,15. ;sleep for 1/4 second xtime: .word 0,rwait*60. ;wait time when finished or abort rarea: .blkw 5 ;emt area for .readw sarea: .blkw 2 ;for .scca ctrlc: .word 0 hieff: .byte 1,120 ;turn on or off high eff mode nowait: .byte 0,152 ;to set the nowait state .word 'U .word 0 single: .byte 0,152 ;single character activation .word 'S .word 0 tflag: .word 0 ;time-out flag aflag: .word 0 ;abort flag eos: .word 0 ;save end of string block: .word 0 ;size of file in RT-11 blocks blkcnt: .word 0 ;for .readw, block to start read xrecno: .word 0 ;record number for packets xblock: .word 0 ;size of file in Xmodem blocks chksum: .word 0 ;checksum point: .word 0 ;pointer to read buffer bytcnt: .word 0 ;number of bytes in input buffer status: .word 0 ;status word cstrng: .blkb 16. ;input to the csi rbuff: .blkw 256.*10. ;10 blocks of the input file buffer: .blkb 256. ;gtline input buffer .even .end start