e _vߋt ***THIS VOLUME DOES NOT CONTAIN A HARDWARE BOOTABLE SYSTEM *** VOL1D%B000DECFILE11AHDR100010000000100 00000 00000 000000DECFILE11AEOF14444444444324410 P=p w%MS  5,w5 wU VwNf  $| p-d ~ ) BE`ȁ     1Ý -,d34@DOSLNX`31AUG;0135506DOSLNX [001,001] DECFILE11A XkkQkd HMkQ HMd# .title DOS -- DOS device interface .dsabl gbl .enabl lc;+;<; File exchange program for ASCII/IMAGE transfer between RSX;; and DOS for E11 PCs. It can also list the DOS directory.;3; Copyright (c) 1999 by John Shilling & Associates,4; 5404 Knoxville Drive?; College Park, MD 20740 U.S.A..; (301) 441-2357;; an unpublished work.;.; John Shilling ; 28-Jan-1999; Email: john@jsacomp.com-;S; Adapted from:;.4; DOS file device handler for RT-11 V4.0 and later.; By John Wilson.9; Copyright (C) 1998 by Digby's Bitpile, Inc. DBA D Bit.t; All rights reserved. ;yI; This program accesses DOS files using the DOS file device in Ersatz-11. D; It allows only one file at a time to be read or written. The fileF; must be located in the current DOS directory, and has to have an 8.3(; filename with no non-RAD50 characters.;i;-;; RSX System macros ;m$ .mcall mrkt$s, wtse$s, exit$s, dir$ .mcall fcsmc$, fcsbt$, fdof$l fcsmc$r fcsbt$ ;the FCS kitchen sink fdof$l. fsrsz$ 1g' ie.eof = -10. ;they forgot this one...D UISAR0 = 177640; '; Externals from Executive Symbol TableO;i .globl $NS0, $NS7, $DSW; ; Internal macros;l6 .macro mova arg ;mov our address to absadr doubleword mov arg,-(sp) jsr pc,cvtadr .endm .macro mess arg ;type a message mov #arg,-(sp) jsr pc,typita .endm mess .macro fatal arg ;fatal message mov #arg,-(sp)s jsr pc,die$ .endm fatal; ; DOS Device CSR bits:;f/dovec= 400 ;7-bit vector/4 starts with this bitg>dopri= 20 ;3-bit interrupt priority (4-7) starts with this bitdobsy= 4 ;NZ => device busyedogo= 2 ;set to start command0doie= 1 ;int enableI;r6; Function codes (for CMDCMD field in command packet):; doopn= 0 ;open file-&docrt= 1 ;create (but don't open) filedodel= 2 ;delete fileedordd= 3 ;read datajdowrd= 4 ;write datadosek= 5 ;seek#dofst= 6 ;find first wildcard match,"donxt= 7 ;find next wildcard matchdocls= 8. ;close filet;; Use a standard CSR and vectora; do$csr = 176470o;;do$vec = 240 ;in use!$do$vec = 274 ;Free on our system...do$ba= do$csr+2 ;bus addr rego"do$bae= do$csr+4 ;bus addr ext reg;+;a; Impure Storage;c.; Note: Adjacency assumed in all of the below!;-;0/base = . ;virtual base of program when runningi:absadr: 0,0 ;absolute address of our address of something"savvct: 0,0 ;saved vector address"ferr: 0 ;RSX generated error codemode: 0 ;0=ASCII, 1=imagefunc: 0 ;1=read, -1=writeother: 0 ;1=directory"cmdpkt: ; command packet goes here#cmdcmd: .blkw ;command code, 0-8.F6cmdsts: .blkw ;status (-1=timeout, 0=OK, >0=DOS err) cmdhnd: .blkw ;DOS file handle.cmdprm: .blkw ;parameter (if defined by cmd)/cmdlen: .blkw ;length of data buffer in bytesv4cmdba: .blkw 2 ;22-bit absolute addr of data buffercmdbae = cmdba+2"hnd: .word 0 ;DOS handle for file:flg: .word 0 ;NZ if handle is valid (0 => opened raw dev);e8fdb: fdbdf$ ;RSX general-purpose File Descriptor Block! fdat$a r.fix,fd.blk,512.,32.,64.n fdrc$a ,fcsbuf,512. fdop$a 1,dspt0mdspt0: 0,0 ;default device 0,0 ;default UICedspt: 0,file ;default filename!blkno: 0 ;the block in questionk-iobuff: .blkw 1024. ;4-block transfer bufferk$rsxmod: 0 ;NZ if it's from a GCML$.gcml: .byte 127.,41. ;QIO for get command line"rsxcmd: ;data goes here ;GMCR line(fcsbuf: .blkw 256. ;RSX/FCS file buffer .blkb 2 ;space for CR/LF!crjt: 0 ;NZ if last char was CRX%file: .blkw 10./2 ;FILNAM.EXT bufferf7 .blkb 128.-10. ;more space for pathname in DOFST/DONXTflfile= .-file ;length of buf%efile: .blkb ;guaranteed NUL at end  .even a;i; Start the program;; %start: finit$ ;Init FCS impure area , cmp @#do$vec,#$NS0 ;see if vector is in use blo 5$ ;yesG cmp @#do$vec,#$NS7 ;maybe blos 10$ ;no, OK$5$: fatal vecuse ;Vector is in use!-10$: call dosatt ;attach the DOS file devicel'15$: call getopr ;get the next commands bcs 90$ ;error call deccmd ;decode commandb bcc 20$ ;ok1 mess invcmd ;else bad commandi br 15$ ;try again="20$: call decfnm ;decode filename bcc 30$ ;okN mess invnam ;bad name br 15$ ;try againa $30$: tst func ;see if read or write blt 60$ ;if write, enter file  bgt 50$ ;if read, lookup file tst other ;other function? beq 15$ ;noK$ call direct ;else it's a directory mess opcomp ;it is donec br 15$  e50$: call readfl ;read it br 80$e x60$: call writfl ;write it80$: bcc 15$ ;okd mess opfail ;else it failed. br 15$  s$90$: call dosdet ;detach DOS device exit$sl e;+$; Read a file from DOS, write to RSX;-#readfl: call lookup ;find the filea bcs 80$ ;error% clr blkno ;start with 1st DOS block % clr fdb+f.fver ;always a new version 1 fdat$r #fdb,,,,#32.,#64. ;large alloc and extent$ tst mode ;ASCII mode?s beq 105$ ;yesy mov #r.fix,(r0) ;no, image mode. mov #512.,f.rsiz(r0) ;set fixed record length open$w ;open the RSX file bcs 70$ ;error;d ; read blocks ;s%10$: call reados ;read DOS to IOBUFFo bcc 12$ ;OKO cmpb ferr,#ie.eof ;EOF? bne 60$ ;nol tst r5 ;any bytes? beq 100$ ;no, all OK# call padzro ;zero-fill last blockr'12$: add #4,blkno ;next chunk next time mov #4,r4 ;max blocks to write" mov #iobuff,r1 ;address of buffer!15$: mov r5,r2 ;length remainingS! cmp r2,#512. ;more than 1 block?# ble 20$ ;no  mov #512.,r2 ;yes20$: put$ #fdb,r1,r2 ;put RSX  bcs 90$ ;error sub r2,r5 ;more to go? ble 10$ ;no add r2,r1 ;yes dec r4 ;failsafe count...  bgt 15$ ;continue  br 10$ ;go again!60$: mess dosgte ;DOS read error; br 95$?!70$: mess rsxope ;RSX open erroro br 95$i80$: mess file mess dosope ;DOS open errort br 95$m trsxpe =.x"90$: mess rsxpte ;RSX write error95$: call 101$ ;close itr sec returne n100$: mess opcomp ;Complete!1"101$: mov #fdb,r0 ;close the file call .trncl ;t .globl .trncl$ call close ;close the DOS file too clc returnb; do ASCII moder4105$: mov #fd.cr*400+r.var,(r0) ;set variable length% clr f.rsiz(r0) ;no record length yets open$w ;open the RSX file bcs 70$ ;error( mov #fcsbuf,r3 ;init the output address clr crjt ;init flag for cr/lfo; ; read blocksm;&110$: call reados ;read DOS to IOBUFF bcc 112$ ;OK cmpb ferr,#ie.eof ;EOF? bne 60$ ;no0 tst r5 ;any bytes? beq 180$ ;no, all OK112$: add #4,blkno ;next chunk" mov #iobuff,r1 ;address of buffer; next output byte115$: movb (r1)+,r2 ;get a byted beq 150$ ;ignore NULLr cmpb r2,#15 ;izit CR?e# beq 130$ ;if so, write the recordt cmpb r2,#12 ;izit LF?h bne 125$ ;no tst crjt ;LF after CR?+ bne 160$ ;yes, no need to output a recordt& br 140$ ;no, we must output a record(125$: movb r2,(r3)+ ;place in FCS buffer" clr crjt ;last byte was not a CR" cmp r3,#fcsbuf+510. ;long record? blo 150$ ;no& ;yes, split the record if too long!130$: tst crjt ;two CR in a row?u bne 150$ ;yest$140$: call putfcs ;write the record inc crjt ;we just "wrote" a CR150$: dec r5 ;more in buffer? bgt 115$ ;yese br 110$ ;no, read DOS file&160$: clr crjt ;clear after seeing LF br 150$ ;continue,)180$: cmp r3,#fcsbuf ;null buffer at end?w beq 190$ ;yese$ call putfcs ;no, write last record190$: br 100$ ;and done!t6; output one text-editor-compatible record to RSX file&putfcs: sub #fcsbuf,r3 ;compute length;; beq 5$ ;no blank lines...t( put$ #fdb,#fcsbuf,r3 ;output one record bcs 10$ ;file write errord/5$: mov #fcsbuf,r3 ;re-point to start of buffer5 return ;and doneb 1#10$: tst (sp)+ ;return to mainlinei br trsxpe ; %; zero-fill the last 512-byte segmentc)padzro: mov #iobuff,r1 ;address of buffere' add r5,r1 ;point past the filled parts10$: bit #777,r5 ;EOB? beq 30$ ;yes clrb (r1)+ ;no, pad onet inc r5 ;extend lengtho br 10$ ;go again 30$: return,;+"; subroutine to read open DOS file; returns R5 = BCb;-reados: clr r5 ;no length yet" call seek ;set up "seek" command bcs 60$ ;(no open file, skip)f call docmd ;send itn bcs 40$ ;failedp call addr ;load up buffer addr mov #dordd,cmdcmd ;set command2 call docmd ;do command bcs 40$! mov cmdlen,r5 ;get actual length  beq 30$ ;EOF, specialr mov r5,r4 ;copy5 sub #2048.,r4 ;test bytes readr0 beq 20$ ;if eq, request satisfied by bytecount* ;short read, indicates EOF on DOS file$30$: movb #-10.,ferr ;show EOF error sec20$: return ;done ,40$: movb #-4,ferr ;show unrecoverable error br 30$b"60$: movb #-42.,ferr ;no open file br 30$e i;+); Write a file to DOS. Read it from RSX.e;-,writfl: clr blkno ;start with 1st DOS block1 call nulfil ;convert filename, see if it's nullu bcs 80$ ;yes% clr fdb+f.fver ;always a new version5, mov #512.,fdb+f.urbd ;allow a 512-byte file% opns$r #fdb ;lookup the file on RSX bcs 80$ ;error call enter ;create DOS filem bcs 70$ ;failedw" mov #iobuff,r1 ;address of buffer tst mode ;ASCII mode?; beq 10$ ;yes mov #fdb,r0 ;restore R0!1 mov #512.,f.rsiz(r0) ;change to 512-byte records  mov #r.fix,(r0) ;;e$; read RSX records, write DOS blocks;;%10$: call readrs ;read RSX to fcsbuf  bcs 60$ ;EOF/error ;r5 has bytecount$*20$: cmp r1,#iobuff+<512.*4> ;output full? blo 30$ ;nof$ call wridos ;yes, write DOS buffer bcs 75$ ;error230$: movb (r2)+,(r1)+ ;copy RSX byte to DOS buffer dec r5 ;RSX buffer done? bgt 20$ ;noo br 10$ ;yess!60$: cmpb f.err(r0),#ie.eof ;EOF? beq 90$ ;yes, OK mess rsxgte ;RSX read error1 call wridos ;dump DOS buffer bcs 75$ ;error on DOS too! br 95$ ;else doner!70$: mess dosope ;DOS open errore br 95$a"75$: mess dospte ;DOS write error br 95$ !80$: mess rsxope ;RSX open error5 br 95$u(90$: call wridos ;write last DOS buffer bcs 75$ ;error br 100$ ;doner95$: call 101$ ;close itp sec returnO u100$: mess opcomp ;Complete!?"101$: close$ #fdb ;close the file$ call close ;close the DOS file too clc returnK;+,; read RSX file using FCS, convert to stream;O*readrs: mov #fcsbuf,r2 ;point to my buffer! get$ #fdb,r2,#512. ;get a recorde mov f.nrbd(r0),r5 ;get length bcs 80$ ;error6 bitb #fd.cr,f.ratt(r0) ;do we need a CRLF at the end? beq 80$ ;no5# movb #15,fcsbuf(r5) ;yes, place itO movb #12,fcsbuf+1(r5) ;* add #2,r5 ;adjust length, can't overflow80$: return ;return cc/cs$;+&; subroutine to write to open DOS file%; R1 points to end of buffer to writeh;-)wridos: call seek ;set up "seek" commandX bcs 30$ ;(no open file, skip)m call docmd ;send itu bcs 20$ ;failedu call addr ;load up buffer addr sub #iobuff,r1 ;compute lengthe mov r1,cmdlen ;length ble 5$ ;nothing to dod mov #dowrd,cmdcmd ;set commandq call docmd ;do command bcs 20$ ;error# add #4,blkno ;advance block to put#(5$: mov #iobuff,r1 ;reset buffer address 10$: returntdoerr =.%20$: movb #-53.,ferr ;say fatal error 25$: sec returno&30$: movb #-42.,ferr ;say no open file br 25$e;+; Close open file.;-$close: call gethnd ;get file handle bcs 10$ ;not open$ mov #docls,cmdcmd ;func=close call docmd ;close the handle 10$: returne;+5; Delete a file. At present, this is not referenced.o;-&delete: call getnam ;convert filename mov #dodel,cmdcmd ;func=delete,0 call docmd ;execute it, come back on interrupt bcs doerr ;error returnt;+; Look up an existing file.,;-&lookup: call nulfil ;see if it's null bcs 40$ ;yes5 mov #1,cmdprm ;access=RO, sharing=compatibility model clr cmdcmd ;func=opend call docmd ;execute it bcs 40$ ;error call savhnd ;save handle clc return;operr =."40$: movb #-26.,ferr ;no such file sec returnt;+; Enter a new file.o;-%enter: mov #docrt,cmdcmd ;func=createe0 call docmd ;execute it, come back on interrupt bcs operr ;error3 clr cmdprm ;access=RW, sharing=compatibility modeo clr cmdcmd ;func=open0 call docmd ;execute it, come back on interrupt bcs operr ;error call savhnd ;save handle10$: clc returnc c;+; Handle directory reads.;;c3; We read filenames from the host OS one at a time.0; Unfortunately we get no size/date information.;s;-)direct: ;get the directory search startede, mov #dofst,cmdcmd ;command=find first match br 30$ ;skip20$: ; retrieve next filenamet+ mov #donxt,cmdcmd ;command=find next match,30$: mov #file,r5 ;point at bufr mova r5 mov absadr,cmdba ;set addrc mov absadr+2,cmdbae! mov #lfile,cmdlen ;length of buf call docmd ;get next dir entry bcs 80$ ;failed ' clrb efile ;guarantee terminating NULi mess file ;show on tty br 20$ ;back for next file80$: return ;and done! o;+7; Set up a "seek" command packet for file addr of blknoo;-seek: call gethnd ;get handle bcs 10$ ;not open0 mov r0,-(sp) ;save 2n mov r1,-(sp)x# mov blkno,r0 ;get starting block #0 mov r0,r1 ;copyi swab r0 ;left 85 clrb r0 ;(clear LSB) asl r0 ;left 9 mov r0,cmdba ;set low addrn! swab r1 ;right 8, old b7 in b15  asl r1 ;right 7, old b7 in C adc r1 ;old b7 in b0 bic #^C777,r1 ;isolate high 9 mov r1,cmdbae! clr cmdprm ;seek from BOF (C=0): mov #dosek,cmdcmd ;[func=seek]  mov (sp)+,r1 ;restore 2 mov (sp)+,r0d 10$: rts pc;+@; Load up address (etc.) information for DOS file device access.;-.addr: mova #iobuff ;address of the DOS buffer mov absadr,cmdba ;save addr# mov absadr+2,cmdbae ;high bits tool mov #2048.,cmdlen ;length rts pcm;+;t ; Get file handle for open file.;76; Returned in CMDHND, or C=1 if raw device or no file.;i; R0 trashed, others preserved.h;;-+gethnd: tst flg ;could there be file open?: beq 10$ ;nom& mov hnd,cmdhnd ;yes, fetch the handle tst (pc)+ ;C=0, skip SEC10$: sec ;no file  rts pce;+); Save file handle for newly opened file.-;d(; Stack space already checked by NULFIL.;; R0 trashed, others preserved.v;-savhnd: inc flg ;say open filev mov cmdhnd,hnd ;save handle rts pct;+; ;; Parse filename, see if they're opening the null filename.i;aC; Return C=1 if so (or if out of stack space), stack entry created.e7; C=0 if not, so open the file and add its stack entry.m;m;-&nulfil: call getnam ;convert filename2 cmp cmdlen,#1 ;anything besides the "." we added? bgt 20$ ;yes, C=0d clr flg ;say no open filed10$: sec 20$: rts pc ;++; Set address of filename in command buffere;-+getnam: mov #file,r4 ;point at filename bufv mova r4 ;set up its addressp mov absadr,cmdba ;set addr  mov absadr+2,cmdbae clr cmdlen ;compute its length5$: tstb (r4)+ ;string done?s beq 10$ ;yes inc cmdlen ;no br 5$510$: mov cmdlen,dspt ;set filename length for RSX toof returng;++; Do the current command, return when done.g;-)docmd: mova #cmdpkt ;point at packet bufd$ mov absadr,@#do$ba ;set packet addr mov absadr+2,@#do$bae mov #do$vec,r0 ;get vectorm asr r0 ;/4 asr r0m swab r0 ;in LH- bis #<4*dopri>!dogo,r0 ;set PRI=4, GO, no IEr mov r0,@#do$csr ;start command # mov #100.,r0 ;start failsafe timer;#5$: mrkt$s #1,#1,#1 ;wait a tick...s wtse$s #1+ bit #dogo,@#do$csr ;still busy after this? beq doint ;no, donee dec r0 ;wait more? bgt 5$ ;yesr$;;; no way to abort cmd in progress? clr @#do$csr ;kill ints sec ;no rts pc ;return to caller;+; "Interrupt" service routine.;-&doint: clr @#do$csr ;kill further ints) cmp #1,cmdsts ;C=1 if CMDSTS is non-zero  rts pc ;process result;+5; make an address within our task an absolute addressn;*; 2(sp) = address (popped off upon return);-#cvtadr: mov r0,-(sp) ;save a couple1 mov r1,-(sp)d mov 6(sp),r1 ;get our address ashc #4,r0n% bic #^c<16>,r0 ;use word indexed APR , mov uisar0(r0),r1 ;get base segment address clr r0 ;' ashc #6,r0 ;convert to 22-bit addressn mov r0,absadr+2 ; mov r1,absadr ;storen$ mov 6(sp),r1 ;get our address again' bic #160000,r1 ;use offset without APRs( add r1,absadr ;compute physical address$ adc absadr+2 ;(shouldn't need this) mov (sp)+,r1 ;restore 2 mov (sp)+,r0 ;p& mov (sp)+,(sp) ;adjust return address return ;and done!;+; "attach" the DOS device ;-5dosatt: mov @#do$vec,savvct ;save the original vectorn mov @#do$vec+2,savvct+2/ mov @#4,@#do$vec ;make any interrupt trap to 4  mov @#6,@#do$vec+2- returns;+; "detach" the DOS device,;-"dosdet: tst savvct ;vector saved? beq 10$ ;nob* mov savvct,@#do$vec ;restore prior vector mov savvct+2,@#do$vec+2 ; 10$: returnc s;+; Decode the command;-#deccmd: call nxnbl ;next non-blank  bcs 80$ ;error clr func ;assume nothing clr other ;n call nxbln ;next blank bcs 5$ ;none means no filename cmpb r2,#'G ;Get?g beq 10$ ;yes cmpb r2,#'P ;Put?2 beq 20$ ;yes cmpb r2,#'D ;Directory?p bne 5$ ;no" inc other ;yes, it's a directory5$: return ;return cs/cc10$: inc func ;it's a read? return$ n20$: dec func ;it's a write 80$: returnt;+; Decode the filename;;-"decfnm: mov #file,r4 ;put 'em here! clr r3 ;no valid characters yetx" call nxnbl ;advance to non-blank bcc 5$ ;if any tst other ;a directory? beq 80$ ;noa! mov #"*.,(r4)+ ;init to "*.*"<0>e mov #'*,(r4)+ clr (r4)+ ;$ mov #4,r3 ;set the length clc ;it's OKc returnD*5$: call israd ;valid filename character? bcs 20$ ;noo movb r2,(r4)+ ;place in buffer inc r3 ;countt call nxnbl ;next character bcs 30$ ;donea cmp r3,#8. ;all we can take? blo 5$ ;no"20$: cmpb r2,#'. ;izit extension? bne 80$ ;no, it's bad! movb r2,(r4)+ ;place in buffer; clr r3 ;go again call nxnbl ;next character bcs 50$ ;no more, it's OKn+25$: call israd ;valid filename character?* bcs 30$ ;no4 movb r2,(r4)+ ;place in buffert inc r3 ;countO call nxnbl ;next character bcs 30$ ;done  cmp r3,#3. ;all we can take? blo 25$ ;noc!30$: clr mode ;assume ascii model tstb r2 ;more stuff in buffer? beq 50$ ;no, we're done  cmpb r2,#'/ ;switch coming?: bne 80$ ;no, error call nxnbl ;next character bcs 80$ ;must be something cmpb r2,#'I ;image?a beq 40$ ;yes cmpb r2,#'B ;binary? beq 40$ ;yes cmpb r2,#'A ;ASCII?s beq 50$ ;yes br 80$ ;no 40$: inc mode ;set binary model!50$: clrb (r4)+ ;null after namec clc ;everything cool! return$ d80$: sec ;something bad... return ;2 ; scan for next word .enabl lsbm(nxnbl: tstb (r1) ;is there a character? beq 80$ ;no'$ cmpb (r1),#40 ;some ctrl character? bhi 10$ ;non tstb (r1)+ ;yes, skip it br nxnbl s%10$: movb (r1)+,r2 ;get the character  cmpb r2,#140 ;lower? blo 15$ ;no  bicb #40,R2 ;toupper15$: clc ;good returnb80$: clr r2 ;null character sec ;there isn't any more returnc ; scan for end of word(nxbln: tstb (r1) ;is there a character? beq 80$ ;noe$ cmpb (r1),#40 ;some ctrl character? blos 15$ ;yes. tstb (r1)+ ;no, skip it) br nxbln .dsabl lsb*; is character in R2 a radix-50 character?israd: cmpb r2,#'Z ;gt Z? bgt 50$ ;yes, badt cmpb r2,#'A ;lt A? bge 30$ ;no, it's good ;try number2 cmpb r2,#'9 ;gt 9? bgt 50$ ;yes, bad2 cmpb r2,#'0 ;lt 0? bge 30$ ;yes, in numeric range tst other ;in a directory? beq 50$ ;no cmpb r2,#'* ;wildcard? bne 50$ ;no, bad 30$: tst (pc)+ ;skip bad return50$: sec ;set bad return return ;donec;+ ; Go away ;-$die: mov 2(sp),r0 ;Print the message call typ1#bail: call dosdet ;kill DOS devicex close$ #fdb ;close RSX file# exit$s? b;+); Get a command line from user or the CLI$;-*getopr: tst rsxmod ;is this command mode?$ bgt bail ;yes, no further commands% dir$ #gcml ;first, try command liner bcc 20$ ;oko45$: mess prompt ;Prompt for a function and filename" mov #io.rvb,qfn ;next, try a read .globl io.rvb( mov #rsxcmd,r1 ;point to command buffer, mov #"DO,(r1)+ ;Simulate the command prefix mov #"S ,(r1)+ ;t& mov r1,qbf ;Set up read terminal QIO mov #76.,qln ;c mov #40,qcc dir$ #qm ;issue the read bcs 80$ ;if cs, this is fatale tstb qiosb ;check for ctrl-Z ble 80$ ;must be...s mov qiosb+2,r0 ;get the lengthn beq 5$ ;nothing on lineg add r1,r0 ;point past buffer movb #15,(r0)+ ;place CR inline clrb (r0)+ ;null at endi call nxnbl ;anything on line?r! dec r1 ;back up for next callerc! bcs 5$ ;no command on the line.v dec rsxmod ;not gcml$ mode return ;return CC )*20$: mov #rsxcmd+3,r1 ;point past cmd name"25$: call nxbln ;look for a blank bcs 5$ ;none call nxnbl ;anything on line?i! dec r1 ;back up for next callert! bcs 5$ ;no command on the line.q$ inc rsxmod ;yes, it's from a GCML$ returnn80$: sec ;some error...s return;+#; Type a message on user's terminal);-typit: mov 2(sp),r0xtyp1: mov r0,qbf5$: bitb #177,(r0) ;end? beq 20$ ;yes tstb (r0)+ ;no, count it br 5$ d 20$: mov #40,qcc ;assume normal tstb (r0) ;izit normal?v beq 30$ ;yes! clr qcc ;no, so no car.ctl here 30$: sub qbf,r0 ;compute length mov r0,qln ;set length$ mov #io.wvb,qfn ;set write function .globl io.wvb dir$ #qm ;write it mov (sp)+,(sp) ;pop arg.' return ;doner;r; RSX Terminal I/O;eqm: .byte 3,14 ;QIOW$+qfn: io.wvb,5,1,qiosb,0 ;to user's terminalyqbf: 0 ;the bufferqln: 0 ;the lengthqcc: 0 ;the carriage control 0,0,0 ;garbage wordsnqiosb: 0,0 ;the status;q ; Messages;m"opfail: .asciz "Operation failed!"!invnam: .asciz "Invalid Filename"r,vecuse: .asciz "Sorry, DOS vector is in use"Dinvcmd: .asciz "Usage: DOS {GET | PUT | DIR} FILENAME.EXT [/A | /I]"#prompt: .asciz <15><12>"DOS> "<200>($rsxope: .asciz "RSX file open error"$dosope: .asciz "DOS file open error"%rsxpte: .asciz "RSX file write error" $rsxgte: .asciz "RSX file read error"%dospte: .asciz "DOS file write error"h$dosgte: .asciz "DOS file read error"$opcomp: .asciz "Operation Complete!" .even .end startl: .asciz "Operation failed!"!invnam: .asciz "Invalid Filename"r,vecuse: .asciz "Sorry, DOS vdos;1/-cp/pr,dos;1/-sp=doslb:[1,54]rsx11m.stb/ss/ suplib=fcsfsl:svstack=60asg=sy:1 task=...dos<//DOS> "<200>($rsxope: .asciz "RSX file open error"$dosope: .asciz "DOS file open error"%rsxpte: .asciz "RSX file write error" $rsxgte: .asciz "RSX file read error"%dospte: .asciz "DOS file write error"h$dosgte: .asciz "DOS file read error"$opcomp: .asciz "Operation Complete!" .even .end startl: .asciz "Operation failed!"!invnam: .asciz "Invalid Filename"r,vecuse: .asciz "Sorry, DOS v, .title LNX -- DO: device interface to Linux .dsabl gblu .enabl lc .nlist bex;+;1<; File exchange program for ASCII/IMAGE transfer between RSX?; and Linux for E11 PCs. It can also list the Linux directory. ;e8; Copyright (c) 1999-2005 by John Shilling & Associates,; an unpublished work.;e; John Shillinga ; 28-Jan-1999r; ; Adapted from:a;z4; DOS file device handler for RT-11 V4.0 and later.; By John Wilson.9; Copyright (C) 1998 by Digby's Bitpile, Inc. DBA D Bit.,; All rights reserved.d;c;; DOS program (DOS <--> RSX file transfer program) adapted ; for Linux;cK; This program accesses Linux files using the DO: file device in Ersatz-11. D; It allows only one file at a time to be read or written. The fileB; must be located in the current directory, and has to have an 9.3(; filename with no non-RAD50 characters.;a!; 8-Dec-2000 Expand buffer lengthr$; Use 32-bit math for disk address#; Make length argument a variables3; Conditionally make transfer faster (see OLDWAY)d;c>; 11-Mar-2002 Added E11 Command Interface Switch (/X cmd-line);f?; 19-Mar-2003 Changed "In Use" vector check to compare to same i3; as @4 (=OD trap) instead of to between $NS0 andt,; $NS7 for compatibility between releases.;-;o; RSX System macrosd;c$ .mcall mrkt$s, wtse$s, exit$s, dir$ .mcall fcsmc$, fcsbt$, fdof$l fcsmc$- fcsbt$ ;the FCS kitchen sink fdof$l2 fsrsz$ 1o' ie.eof = -10. ;they forgot this one...a UISAR0 = 177640;o'; Externals from Executive Symbol Table; .globl $DSW;e; Internal macros; 6 .macro mova arg ;mov our address to absadr doubleword mov arg,-(sp) jsr pc,cvtadr .endm .macro mess arg ;type a message mov #arg,-(sp) jsr pc,typiti .endm messn l .macro fatal arg ;fatal message mov #arg,-(sp)r jsr pc,die .endm fatal;c; DO: Device CSR bits:;/dovec= 400 ;7-bit vector/4 starts with this bit2>dopri= 20 ;3-bit interrupt priority (4-7) starts with this bitdobsy= 4 ;NZ => device busyrdogo= 2 ;set to start commanddoie= 1 ;int enableI;r6; Function codes (for CMDCMD field in command packet):; doe11= -1 ;inject E11 commandrdoopn= 0 ;open file&docrt= 1 ;create (but don't open) filedodel= 2 ;delete fileidordd= 3 ;read datadowrd= 4 ;write datadosek= 5 ;seek#dofst= 6 ;find first wildcard matcht"donxt= 7 ;find next wildcard matchdocls= 8. ;close filer;s; Use a standard CSR and vector3;tdo$csr = 176470t;;do$vec = 240 ;in use!$do$vec = 274 ;Free on our system...do$ba= do$csr+2 ;bus addr rege"do$bae= do$csr+4 ;bus addr ext reg;(&; Define the DOS <-> RSX Buffer Length;onbblok = 8. ;# of blocksr;+;=; Impure Storage;=.; Note: Adjacency assumed in all of the below!;-;i/base = . ;virtual base of program when runninge:absadr: 0,0 ;absolute address of our address of something"savvct: 0,0 ;saved vector address"ferr: 0 ;RSX generated error codemode: 0 ;0=ASCII, 1=imagefunc: 0 ;1=read, -1=writeother: 0 ;1=directory"cmdpkt: ; command packet goes here#cmdcmd: .blkw ;command code, 0-8.u6cmdsts: .blkw ;status (-1=timeout, 0=OK, >0=DOS err) cmdhnd: .blkw ;DOS file handle.cmdprm: .blkw ;parameter (if defined by cmd)/cmdlen: .blkw ;length of data buffer in bytes 4cmdba: .blkw 2 ;22-bit absolute addr of data buffercmdbae = cmdba+2"hnd: .word 0 ;DOS handle for file:flg: .word 0 ;NZ if handle is valid (0 => opened raw dev);8fdb: fdbdf$ ;RSX general-purpose File Descriptor Block! fdat$a r.fix,fd.blk,512.,32.,64.n fdrc$a ,fcsbuf,512. fdop$a 1,dspt0mdspt0: 0,0 ;default device 0,0 ;default UICidspt: 0,rfile ;default filename #blkno: 0,0 ;the block in question 9iobuff: .blkw 256.*nbblok ;"nbblok"-block transfer bufferf$rsxmod: 0 ;NZ if it's from a GCML$.gcml: .byte 127.,41. ;QIO for get command line"rsxcmd: ;data goes here ;GMCR line(fcsbuf: .blkw 256. ;RSX/FCS file buffer .blkb 2 ;space for CR/LF!crjt: 0 ;NZ if last char was CRe2file: .blkw 10./2 ;path/filename buffer for Linux7 .blkb 128.-10. ;more space for pathname in DOFST/DONXT;lfile= .-file ;length of buf%efile: .blkb ;guaranteed NUL at end .even.rfile: .blkw 41. ;FILENAME.EXT buffer for RSX ;must be after "file" buffer)lpath: .word rfile ;Points to Linux path c;b; Start the program ; %start: finit$ ;Init FCS impure areaG* cmp @#do$vec,@#4 ;see if vector is in use bne 10$ ;no, OK ! fatal vecuse ;Vector is in use!l-10$: call dosatt ;attach the DOS file devicen)again =. ;entry after LNX /X completion '15$: call getopr ;get the next command= bcs 90$ ;error call deccmd ;decode commande bcc 20$ ;ok mess invcmd ;else bad commandN br 15$ ;try againX"20$: call decfnm ;decode filename bcc 30$ ;oke mess invnam ;bad name br 15$ ;try again  g$30$: tst func ;see if read or write blt 60$ ;if write, enter filee bgt 50$ ;if read, lookup filen tst other ;other function? beq 15$ ;no$ call direct ;else it's a directory mess opcomp ;it is done  br 15$  c50$: call readfl ;read it br 80$e x60$: call writfl ;write it80$: bcc 15$ ;okd mess opfail ;else it failed. br 15$  s$90$: call dosdet ;detach DOS device exit$sl e;+$; Read a file from DOS, write to RSX;-#readfl: call lookup ;find the file  bcs 80$ ;error% clr blkno ;start with 1st DOS block  clr blkno+2 ;e% clr fdb+f.fver ;always a new versiont1 fdat$r #fdb,,,,#32.,#64. ;large alloc and extente tst mode ;ASCII mode?y beq 105$ ;yesi mov #r.fix,(r0) ;no, image mode. mov #512.,f.rsiz(r0) ;set fixed record length open$w ;open the RSX file bcs 70$ ;error;e ; read blocks; %10$: call reados ;read DOS to IOBUFF bcc 12$ ;OKl cmpb ferr,#ie.eof ;EOF? bne 60$ ;no  tst r5 ;any bytes? beq 100$ ;no, all OK# call padzro ;zero-fill last blocka(12$: mov #nbblok,r4 ;max blocks to write# add r4,blkno ;next chunk next timet adc blkno+2 ;," mov #iobuff,r1 ;address of buffer!15$: mov r5,r2 ;length remaining ! cmp r2,#512. ;more than 1 block? ble 20$ ;no. mov #512.,r2 ;yes20$: put$ #fdb,r1,r2 ;put RSXe bcs 90$ ;error sub r2,r5 ;more to go? ble 10$ ;no0 add r2,r1 ;yes dec r4 ;failsafe count...  bgt 15$ ;continuee br 10$ ;go again!60$: mess dosgte ;DOS read error  br 95$ !70$: mess rsxope ;RSX open errorc br 95$m80$: mess file mess dosope ;DOS open error  br 95$n trsxpe =."90$: mess rsxpte ;RSX write error95$: call 101$ ;close itr sec returne n100$: mess opcomp ;Complete!1"101$: mov #fdb,r0 ;close the file call .trncl ;t .globl .trncl$ call close ;close the DOS file too clc returnb; do ASCII moder4105$: mov #fd.cr*400+r.var,(r0) ;set variable length% clr f.rsiz(r0) ;no record length yets open$w ;open the RSX file bcs 70$ ;error( mov #fcsbuf,r3 ;init the output address clr crjt ;init flag for cr/lfo; ; read blocksn;&110$: call reados ;read DOS to IOBUFF bcc 112$ ;OK cmpb ferr,#ie.eof ;EOF? bne 60$ ;no0 tst r5 ;any bytes? beq 180$ ;no, all OK#112$: add #nbblok,blkno ;next chunk adc blkno+2 ;c" mov #iobuff,r1 ;address of buffer; next output byte115$: movb (r1)+,r2 ;get a byte4 beq 150$ ;ignore NULLl cmpb r2,#15 ;izit CR? # beq 130$ ;if so, write the recorde cmpb r2,#12 ;izit LF?  bne 125$ ;no cmp crjt,#12 ;2 LF in a row?s beq 120$ ;yes, output it tst crjt ;LF after CR?+ bne 160$ ;yes, no need to output a record.120$: mov #11,crjt ;make the flag into LF next& br 140$ ;no, we must output a record(125$: movb r2,(r3)+ ;place in FCS buffer" clr crjt ;last byte was not a CR" cmp r3,#fcsbuf+510. ;long record? blo 150$ ;no& ;yes, split the record if too long!130$: tst crjt ;two CR in a row?  bne 150$ ;yes;$140$: call putfcs ;write the record inc crjt ;we just "wrote" a CR150$: dec r5 ;more in buffer? bgt 115$ ;yesu br 110$ ;no, read DOS file&160$: clr crjt ;clear after seeing LF br 150$ ;continuer)180$: cmp r3,#fcsbuf ;null buffer at end?, beq 190.t:#z31AUG;0135506@V. xQz31AUG;0135506WXXD. kz31AUG;0135506J.NNz31AUG;0135506V|.*O:z31AUG;01355063.z31AUG;0135534.I,,kkQ31AUG;013574731AUG;0135747+.pkd31AUG;013574731AUG;0135747/. O11HMkQ31AUG;013574731AUG;01357470 Y#. pHMd31AUG;013574731AUG;0135747zt:#z xQz kzNNz*O:zze$ ;yes $ call putfcs ;no, write last record190$: br 100$ ;and done!a6; output one text-editor-compatible record to RSX file&putfcs: sub #fcsbuf,r3 ;compute length;; beq 5$ ;no blank lines... ( put$ #fdb,#fcsbuf,r3 ;output one record bcs 10$ ;file write erroro/5$: mov #fcsbuf,r3 ;re-point to start of buffer5 return ;and doneb 1#10$: tst (sp)+ ;return to mainlinei br trsxpe ; %; zero-fill the last 512-byte segmentc)padzro: mov #iobuff,r1 ;address of buffere' add r5,r1 ;point past the filled parts10$: bit #777,r5 ;EOB? beq 30$ ;yes clrb (r1)+ ;no, pad onet inc r5 ;extend lengtho br 10$ ;go again 30$: return,;+"; subroutine to read open DOS file; returns R5 = BCf;-reados: clr r5 ;no length yet" call seek ;set up "seek" command bcs 60$ ;(no open file, skip)b call docmd ;send itd bcs 40$ ;failed( call addr ;load up buffer addr mov #dordd,cmdcmd ;set command5 call docmd ;do command bcs 40$! mov cmdlen,r5 ;get actual length1 beq 30$ ;EOF, specialp mov r5,r4 ;copy,% sub #512.*nbblok,r4 ;test bytes read 0 beq 20$ ;if eq, request satisfied by bytecount* ;short read, indicates EOF on DOS file$30$: movb #-10.,ferr ;show EOF error sec20$: return ;donen,40$: movb #-4,ferr ;show unrecoverable error br 30$$"60$: movb #-42.,ferr ;no open file br 30$d b;+); Write a file to DOS. Read it from RSX.r;-,writfl: clr blkno ;start with 1st DOS block clr blkno+2 ;41 call nulfil ;convert filename, see if it's nullE bcs 80$ ;yes% clr fdb+f.fver ;always a new version;, mov #512.,fdb+f.urbd ;allow a 512-byte file% opns$r #fdb ;lookup the file on RSXi bcs 80$ ;error call enter ;create DOS fileh bcs 70$ ;failed" mov #iobuff,r1 ;address of buffer tst mode ;ASCII mode?e beq 10$ ;yes mov #fdb,r0 ;restore R0!1 mov #512.,f.rsiz(r0) ;change to 512-byte recordsO mov #r.fix,(r0) ;;$; read RSX records, write DOS blocks;S%10$: call readrs ;read RSX to fcsbuf  bcs 60$ ;EOF/error ;r5 has bytecount$/20$: cmp r1,#iobuff+<512.*nbblok> ;output full?m blo 30$ ;nou$ call wridos ;yes, write DOS buffer bcs 75$ ;error230$: movb (r2)+,(r1)+ ;copy RSX byte to DOS buffer dec r5 ;RSX buffer done? bgt 20$ ;nor br 10$ ;yesu!60$: cmpb f.err(r0),#ie.eof ;EOF?1 beq 90$ ;yes, OK mess rsxgte ;RSX read errorr call wridos ;dump DOS buffer bcs 75$ ;error on DOS too! br 95$ ;else doner!70$: mess dosope ;DOS open error  br 95$ "75$: mess dospte ;DOS write error br 95$y!80$: mess rsxope ;RSX open errorb br 95$t(90$: call wridos ;write last DOS buffer bcs 75$ ;error br 100$ ;doner95$: call 101$ ;close itp sec returnO u100$: mess opcomp ;Complete!?"101$: close$ #fdb ;close the file$ call close ;close the DOS file too clc returnK;+,; read RSX file using FCS, convert to stream; *readrs: mov #fcsbuf,r2 ;point to my buffer! get$ #fdb,r2,#512. ;get a recordo mov f.nrbd(r0),r5 ;get length bcs 80$ ;error6 bitb #fd.cr,f.ratt(r0) ;do we need a CRLF at the end? beq 80$ ;no /;;* Patch out CR/LF for Linux -- just xfer %;; movb #15,fcsbuf(r5) ;yes, place it5;; movb #12,fcsbuf+1(r5) ;,;; add #2,r5 ;adjust length, can't overflow# movb #12,fcsbuf(r5) ;yes, place ite inc r5l;; ** End patchO80$: return ;return cc/cs+;+&; subroutine to write to open DOS file%; R1 points to end of buffer to writeo;-)wridos: call seek ;set up "seek" command bcs 30$ ;(no open file, skip)b call docmd ;send itf bcs 20$ ;failed call addr ;load up buffer addr sub #iobuff,r1 ;compute length  mov r1,cmdlen ;length ble 5$ ;nothing to do; mov #dowrd,cmdcmd ;set commandf call docmd ;do command bcs 20$ ;error( add #nbblok,blkno ;advance block to put adc blkno+2 ;(5$: mov #iobuff,r1 ;reset buffer address 10$: returnudoerr =.%20$: movb #-53.,ferr ;say fatal erroro25$: sec returnr&30$: movb #-42.,ferr ;say no open file br 25$;+; Close open file.;-$close: call gethnd ;get file handle bcs 10$ ;not opend mov #docls,cmdcmd ;func=close call docmd ;close the handle 10$: returne;+5; Delete a file. At present, this is not referenced.m;-&delete: call getnam ;convert filename mov #dodel,cmdcmd ;func=delete 0 call docmd ;execute it, come back on interrupt bcs doerr ;error returnr;+; Look up an existing file.,;-&lookup: call nulfil ;see if it's null bcs 40$ ;yes5 mov #1,cmdprm ;access=RO, sharing=compatibility model clr cmdcmd ;func=opend call docmd ;execute it bcs 40$ ;error call savhnd ;save handle clc return;operr =."40$: movb #-26.,ferr ;no such file sec returnt;+; Enter a new file.m;-%enter: mov #docrt,cmdcmd ;func=createe0 call docmd ;execute it, come back on interrupt bcs operr ;error3 clr cmdprm ;access=RW, sharing=compatibility modeo clr cmdcmd ;func=open0 call docmd ;execute it, come back on interrupt bcs operr ;error call savhnd ;save handle10$: clc returnc c;+; Handle directory reads.;;c3; We read filenames from the host OS one at a time.0; Unfortunately we get no size/date information.;s;-)direct: ;get the directory search startede! call getnam ;put name in bufferu, mov #dofst,cmdcmd ;command=find first match br 30$ ;skip20$: ; retrieve next filename;+ mov #donxt,cmdcmd ;command=find next matchc30$: mov #file,r5 ;point at buf; mova r5 mov absadr,cmdba ;set addrs mov absadr+2,cmdbae! mov #lfile,cmdlen ;length of buft call docmd ;get next dir entry bcs 80$ ;failedr' clrb efile ;guarantee terminating NULi mess file ;show on tty br 20$ ;back for next file80$: return ;and done! o;+7; Set up a "seek" command packet for file addr of blknoo;-seek: call gethnd ;get handle bcs 10$ ;not open0 mov r0,-(sp) ;save 2n mov r1,-(sp)x% mov blkno+2,r0 ;get starting block #: mov blkno,r1 ;i# ashc #9.,r0 ;* 512 = file addressb mov r1,cmdba ;set low addrm mov r0,cmdbae ;set high address! clr cmdprm ;seek from BOF (C=0)e mov #dosek,cmdcmd ;[func=seek]f mov (sp)+,r1 ;restore 2 mov (sp)+,r0i 10$: rts pct;+@; Load up address (etc.) information for DOS file device access.;-.addr: mova #iobuff ;address of the DOS buffer mov absadr,cmdba ;save addr# mov absadr+2,cmdbae ;high bits toov mov #512.*nbblok,cmdlen ;length rts pck;+; ; Get file handle for open file.; 6; Returned in CMDHND, or C=1 if raw device or no file.;t; R0 trashed, others preserved.i;a;-+gethnd: tst flg ;could there be file open?# beq 10$ ;nof& mov hnd,cmdhnd ;yes, fetch the handle tst (pc)+ ;C=0, skip SEC10$: sec ;no files rts pci;+); Save file handle for newly opened file.r;o; R0 trashed, others preserved.u;-savhnd: inc flg ;say open filem mov cmdhnd,hnd ;save handle rts pcv;+;n;; Parse filename, see if they're opening the null filename. ;nC; Return C=1 if so (or if out of stack space), stack entry created.t7; C=0 if not, so open the file and add its stack entry.l;;;-&nulfil: call getnam ;convert filename2 cmp cmdlen,#1 ;anything besides the "." we added? bgt 20$ ;yes, C=0s clr flg ;say no open file10$: sec 20$: rts pcn;++; Set address of filename in command bufferv;-+getnam: mov #file,r4 ;point at filename bufc mova r4 ;set up its addressv mov absadr,cmdba ;set addre mov absadr+2,cmdbae+ mov lpath,r3 ;set up path for this commandr clr cmdlen ;compute its length!5$: movb (r3)+,(r4) ;string done?  beq 10$ ;yes! cmpb (r4)+,#100 ;change filename blo 7$ ; too cmpb -1(r4),#132 ; lower?1 bhi 7$ ;no bisb #40,-1(r4) ;yes7$: inc cmdlen ;no br 5$ 10$: returnf;++; Do the current command, return when done.f;-)docmd: mova #cmdpkt ;point at packet buff$ mov absadr,@#do$ba ;set packet addr mov absadr+2,@#do$bae mov #do$vec,r0 ;get vectore asr r0 ;/4 asr r0 swab r0 ;in LH- bis #<4*dopri>!dogo,r0 ;set PRI=4, GO, no IEt mov r0,@#do$csr ;start command # mov #100.,r0 ;start failsafe timer 5$: .if df OLDWAYf mrkt$s #1,#1,#1 ;wait a tick... wtse$s #1+ bit #dogo,@#do$csr ;still busy after this? beq doint ;no, done .iff bit #dogo,@#do$csr ;busy? beq doint ;no, doneu mrkt$s #1,#1,#1 ;wait a tick... wtse$s #1 .endc dec r0 ;wait more? bgt 5$ ;yesc$;;; no way to abort cmd in progress? clr @#do$csr ;kill ints sec ;no rts pc ;return to caller;+; "Interrupt" service routine.;-&doint: clr @#do$csr ;kill further ints) cmp #1,cmdsts ;C=1 if CMDSTS is non-zero  rts pc ;process result;+5; make an address within our task an absolute addressl;s*; 2(sp) = address (popped off upon return);-#cvtadr: mov r0,-(sp) ;save a couplet mov r1,-(sp)m mov 6(sp),r1 ;get our address ashc #4,r0.% bic #^c<16>,r0 ;use word indexed APRe, mov uisar0(r0),r1 ;get base segment address clr r0 ;' ashc #6,r0 ;convert to 22-bit address  mov r0,absadr+2 ; mov r1,absadr ;store.$ mov 6(sp),r1 ;get our address again' bic #160000,r1 ;use offset without APRn( add r1,absadr ;compute physical address$ adc absadr+2 ;(shouldn't need this) mov (sp)+,r1 ;restore 2 mov (sp)+,r0 ;p& mov (sp)+,(sp) ;adjust return address return ;and done!;+; "attach" the DOS deviceg;-5dosatt: mov @#do$vec,savvct ;save the original vectore mov @#do$vec+2,savvct+2/ mov @#4,@#do$vec ;make any interrupt trap to 46 mov @#6,@#do$vec+2i return ;+; "detach" the DOS devicea;-"dosdet: tst savvct ;vector saved? beq 10$ ;no#* mov savvct,@#do$vec ;restore prior vector mov savvct+2,@#do$vec+2 ; 10$: returns +;+; Decode the command;-#deccmd: call nxnbl ;next non-blankm bcs 7$ ;errorj clr func ;assume nothing clr other ; cmpb r2,#'/ ;Only a switch?* beq 40$ ;Yes, assume it's an E11 command call nxbln ;next blank bcs 3$ ;none means no filename cmpb r2,#'G ;Get?r beq 10$ ;yes cmpb r2,#'P ;Put?r beq 20$ ;yes3$: cmpb r2,#'D ;Directory? bne 5$ ;no" inc other ;yes, it's a directory return,5$: sece 7$: return10$: inc func ;it's a read2 returnr r20$: dec func ;it's a write return- 40$: call nxnbl ;next character bcs 7$ ;none! cmpb r2,#'X ;execute something?c bne 5$ ;no call nxbln ;skip spacesh bcs 7$ ;cs means no command  tst (sp)+ ;return to mainlinet mov r1,r0 ;copyo45$: tstb (r0)+ ;skip to end# bne 45$ sub r1,r0 ;find length dec r0 ; without the null& mova r1 ;figure the absolute address ; fill in command packeta mov absadr,cmdba ;set addre mov absadr+2,cmdbae. mov #doe11,cmdcmd ;command=inject E11 command mov r0,cmdlen ;length call docmd ;do the command jmp again ;start all over;+; Decode the filenamei;-$decfnm: clr mode ;assume ascii mode mov #rfile,r4 ;put 'em here& mov r4,lpath ;assume no separate path! clr r3 ;no valid characters yet)" call nxnbl ;advance to non-blank bcc 5$ ;if any tst other ;a directory? beq 80$ ;nog! mov #"*.,(r4)+ ;init to "*.*"<0>n mov #'*,(r4)+ clr (r4)+ ;m mov #4,r3 ;set the length, clc ;it's OK1 return;*5$: call israd ;valid filename character? bcs 20$ ;nom movb r2,(r4)+ ;place in buffers inc r3 ;count call nxnbl ;next character bcs 30$ ;donee cmp r3,#9. ;all we can take? blo 5$ ;no"20$: cmpb r2,#'. ;izit extension? bne 80$ ;no, it's bad! movb r2,(r4)+ ;place in buffer; clr r3 ;go again call nxnbl ;next character bcs 30$ ;no more, it's OKn+25$: call israd ;valid filename character?# bcs 30$ ;no( movb r2,(r4)+ ;place in buffern inc r3 ;counts call nxnbl ;next character bcs 30$ ;donem cmp r3,#3. ;all we can take? blo 25$ ;nol!30$: clrb (r4)+ ;null after namec sub #rfile+1,r4 ;compute length# bmi 35$ ;bad only if R4 is a patht) mov r4,dspt ;set length of RSX filename $35$: tstb r2 ;more stuff in buffer? beq 60$ ;no, we're donef cmpb r2,#'/ ;switch coming?  bne 80$ ;no, error call nxnbl ;next character bcs 80$ ;must be something cmpb r2,#'I ;image?3 beq 40$ ;yes cmpb r2,#'B ;binary? beq 40$ ;yes cmpb r2,#'A ;ASCII?t beq 50$ ;yes cmpb r2,#'P ;Path? beq 100$ ;yest br 80$ ;no n40$: inc mode ;set binary moden br 55$b50$: clr mode ;set ascii mode)55$: call nxnbl ;seeif any more switchess bcc 35$ ;yes60$: clc ;everything cool! returnt 80$: sec ;something bad... return ;p 2E; Process the PATH switch -- allow anything until blank in the stringt;$100$: mov #file,r4 ;reset the output) mov r4,lpath ;point this to the path tooB clr r3 ;reset the length' call nxnbl ;get a non-blank characterc bcs 80$ ;no more - bad movb r2,(r4)+ ;copy string105$: cmpb (r1),#40 ;at EOS? beq 110$ ;yes0# call nxnbl ;no, get the characterl bcs 30$ ;i movb r2,(r4)+ ;copy to output+ br 105$ ; (no translation except TOUPPER)'110$: call nxnbl ;advance to non-blank  br 30$ ;see if a switchs c; scan for next word .enabl lsbe(nxnbl: tstb (r1) ;is there a character? beq 80$ ;nor$ cmpb (r1),#40 ;some ctrl character? bhi 10$ ;no  tstb (r1)+ ;yes, skip it br nxnbln h%10$: movb (r1)+,r2 ;get the characterv cmpb r2,#140 ;lower? blo 15$ ;no1 bicb #40,R2 ;toupper15$: clc ;good return 80$: clr r2 ;null character sec ;there isn't any more return0 ; scan for end of word(nxbln: tstb (r1) ;is there a character? beq 80$ ;nob$ cmpb (r1),#40 ;some ctrl character? blos 15$ ;yes. tstb (r1)+ ;no, skip it) br nxbln .dsabl lsbb*; is character in R2 a radix-50 character?israd: cmpb r2,#'Z ;gt Z? bgt 50$ ;yes, badt cmpb r2,#'A ;lt A? bge 30$ ;no, it's good ;try number2 cmpb r2,#'9 ;gt 9? bgt 50$ ;yes, bad2 cmpb r2,#'0 ;lt 0? bge 30$ ;yes, in numeric range tst other ;in a directory? beq 50$ ;no cmpb r2,#'* ;wildcard? bne 50$ ;no, bad 30$: tst (pc)+ ;skip bad return50$: sec ;set bad return return ;doner;+ ; Go away5;-$die: mov 2(sp),r0 ;Print the message call typ1#bail: call dosdet ;kill DOS deviced close$ #fdb ;close RSX file2 exit$s  ;+); Get a command line from user or the CLI3;-*getopr: tst rsxmod ;is this command mode?$ bgt bail ;yes, no further commands% dir$ #gcml ;first, try command linem bcc 20$ ;okt45$: mess prompt ;Prompt for a function and filename" mov #io.rvb,qfn ;next, try a read .globl io.rvb( mov #rsxcmd,r1 ;point to command buffer, mov #"LN,(r1)+ ;Simulate the command prefix mov #"X ,(r1)+ ;t& mov r1,qbf ;Set up read terminal QIO mov #76.,qln ;c mov #40,qcc dir$ #qm ;issue the read bcs 80$ ;if cs, this is fatale tstb qiosb ;check for ctrl-Z ble 80$ ;must be...s mov qiosb+2,r0 ;get the lengthn beq 5$ ;nothing on lineg add r1,r0 ;point past buffer movb #15,(r0)+ ;place CR inline clrb (r0)+ ;null at endi call nxnbl ;anything on line?r! dec r1 ;back up for next callerc! bcs 5$ ;no command on the line.v dec rsxmod ;not gcml$ mode return ;return CC )*20$: mov #rsxcmd+3,r1 ;point past cmd name"25$: call nxbln ;look for a blank bcs 5$ ;none call nxnbl ;anything on line?i! dec r1 ;back up for next callert! bcs 5$ ;no command on the line.q$ inc rsxmod ;yes, it's from a GCML$ returnn80$: sec ;some error...s return;+#; Type a message on user's terminalr;-typit: mov 2(sp),r0 typ1: mov r0,qbf5$: bitb #177,(r0) ;end? beq 20$ ;yes tstb (r0)+ ;no, count it br 5$ 20$: mov #40,qcc ;assume normal tstb (r0) ;izit normal?m beq 30$ ;yes! clr qcc ;no, so no car.ctl herel 30$: sub qbf,r0 ;compute length mov r0,qln ;set length$ mov #io.wvb,qfn ;set write function .globl io.wvb dir$ #qm ;write it mov (sp)+,(sp) ;pop arg.i return ;done;r; RSX Terminal I/O;eqm: .byte 3,14 ;QIOW$+qfn: io.wvb,5,1,qiosb,0 ;to user's terminaliqbf: 0 ;the bufferqln: 0 ;the lengthqcc: 0 ;the carriage control 0,0,0 ;garbage words qiosb: 0,0 ;the status;q ; Messages;m"opfail: .asciz "Operation failed!"!invnam: .asciz "Invalid Filename"r,vecuse: .asciz "Sorry, DO: vector is in use"Oinvcmd: .ascii "Usage: LNX {GET | PUT | DIR} FILENAME.EXT [/A | /I /P]"<15><12>d- .asciz " -or- LNX /X E11-command-line-text"#prompt: .asciz <15><12>"LNX> "<200>l$rsxope: .asciz "RSX file open error"&dosope: .asciz "Linux file open error"%rsxpte: .asciz "RSX file write error"e$rsxgte: .asciz "RSX file read error"'dospte: .asciz "Linux file write error"h&dosgte: .asciz "Linux file read error"$opcomp: .asciz "Operation Complete!" .even .end startvecuse: .asciz "Sorry, DO: vector is in use"Oinvcmd: .ascii "Usage: LNX {GET | PUT | DIR} Flnx;1/-cp/pr,lnx;1/-sp=lnxlb:[1,54]rsx11m.stb/ss/ suplib=fcsfsl:svstack=60asg=sy:1 task=...lnx"// "<200>l$rsxope: .asciz "RSX file open error"&dosope: .asciz "Linux file open error"%rsxpte: .asciz "RSX file write error"e$rsxgte: .asciz "RSX file read error"'dospte: .asciz "Linux file write error"h&dosgte: .asciz "Linux file read error"$opcomp: .asciz "Operation Complete!" .even .end startvecuse: .asciz "Sorry, DO: vector is in use"Oinvcmd: .ascii "Usage: LNX {GET | PUT | DIR} F