%%s 2/2/964 %%d D 1.3 07-May-82 09:14:41 j 3 2 %%c Modified line 144 of bspawn.w`bspawn.src from "ST0:" to "ST1:". %%c The data set descriptor being built at this point in the code is for %%c the file containing the background spawn information, and is expected to %%c be in ~tmp, which is on ST1:, NOT ST0:. This glitch was pointed out to %%c me by Charles Johnson , USF Physics Research. %%s 8/5/958 %%d D 1.2 28-Apr-82 10:26:13 system 2 1 %%c The command file which builds the background spawning capability was %%c modified to ask the user if assembly listings are desired. This is %%c to permit users on small disks to avoid ~120 blocks of storage to be %%c used up by the build procedure. The file modified was bspawn.w`bspbld.cmd. %%s 0/0/0 %%d D 1.1 26-Mar-82 12:30:12 v1.1 1 0 %%c Version 1.1 is the Spring 1982 Distribution of the LBL/Hughes release %%c of the Software Tools Virtual Operating System software and documentation. %%T %%I 1 %%D 2 #-h- bspbld.cmd 2084 asc 25-mar-82 07:26:05 v1.1 (sw-tools v1.1) %%E 2 %%I 2 #-h- bspbld.cmd 2187 asc 28-apr-82 08:03:02 system (system) %%E 2 TIM .ENABLE SUBSTITUTION .ASKS BIN WHAT IS THE BINARY TOOLS UIC [ G,M - DEFAULT IS 105,1 ] .IF = 0 .SETS BIN "105,1" .ASKS SYS WHAT UIC IS RSXMC.MAC ON [ G,M - DEFAULT IS 11,10 ] .IF = 0 .SETS SYS "11,10" .ASKS SDV DEVICE FOR RSXMC AND EXEMC [ DDN - DEFAULT IS LB0 ] .IF = 0 .SETS SDV "LB0" %%I 2 .SETS LDV "SY:" .ASK IFLIST DO YOU DESIRE ASSEMBLY LISTINGS .IFF IFLIST .SETS LDV "NL:" %%E 2 .ASKN [1.:16.:4.] BTS NO OF SIMULTANEOUS BACKGR PROCESSES PERMITTED .ASKN [1.:'BTS'.:2.] MAXBCK MAX NO OF SIMULT BACKGR PROCS/USER .SETS RESLIB ";" .ASK IFRESL DO YOU WISH TO LINK BSPAWN TO AN FCS RESIDENT LIBRARY .IFF IFRESL .GOTO 10 .ASKS RESLIB WHAT IS ITS NAME [EG. FCSRES] .10: PIP BSPAWN.MAC;*/DE/NM,BTTAB.MAC;*,BTDRV.MAC;*,BTPRE.MAC;* .OPEN BTPRE.MAC .DATA B$$T11='BTS'. .DATA MAXBCK='MAXBCK'. .CLOSE PIP BTPRE.MAC/AP=ST0:['BIN']ASM.PRE PIP BSPAWN.MAC=ST0:['BIN']BSPAWN.SRC PIP BTTAB.MAC=ST0:['BIN']BTTAB.SRC PIP BTDRV.MAC=ST0:['BIN']BTDRV.SRC PIP BSP.OBJ;*/DE/NM,BSP.LST;* %%D 2 MAC BSP,BSP/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BSPAWN %%E 2 %%I 2 MAC BSP,'LDV'BSP/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BSPAWN %%E 2 PIP BTTAB.OBJ;*/DE/NM,BTTAB.LST;* %%D 2 MAC BTTAB,BTTAB/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BTTAB %%E 2 %%I 2 MAC BTTAB,'LDV'BTTAB/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BTTAB %%E 2 PIP BTDRV.OBJ;*/DE/NM,BTDRV.LST;* %%D 2 MAC BTDRV,BTDRV/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BTDRV %%E 2 %%I 2 MAC BTDRV,'LDV'BTDRV/-SP='SDV':[1,1]EXEMC/ML,['SYS']RSXMC,SY:''BTPRE,BTDRV %%E 2 PIP BTDRV.TKB;*/DE/NM .OPEN BTDRV.TKB .DATA BTDRV/-HD/-MM,BTDRV/-SP,BTDRV=BTDRV,BTTAB .DATA LB0:[1,54]RSX11M.STB/SS .DATA LB0:[1,1]EXELIB/LB .DATA / .DATA STACK=0 .DATA PAR=DRVPAR:120000:4000 .DATA // .CLOSE PIP BTDRV.TSK;*/DE/NM,BTDRV.MAP;*,BTDRV.STB;* TKB @BTDRV.TKB PIP BSPAWN.TKB;*/DE/NM .OPEN BSPAWN.TKB .DATA BSPAWN/-FP/CP/PR:5,BSPAWN/MA= .DATA BSP .DATA LB0:[1,54]RSX11M.STB/SS .DATA LB0:[1,1]EXELIB/LB .DATA / .DATA UNITS=3 .IFT IFRESL .DATA LIBR='RESLIB':RO .DATA STACK=64 .DATA TASK=BSPAWN .DATA // .CLOSE PIP BSPAWN.TSK;*/DE/NM,BSPAWN.MAP;* TKB @BSPAWN.TKB ; ; ; IT IS NOW NECESSARY TO COPY BTDRV.TSK AND BTDRV.STB INTO ; YOUR SYSTEM UIC. THE EQUIVALENT OF THE FOLLOWING THREE %%D 2 ; COmMANDS MUST BE PERFORMED NOW AND MUST BE ADDED TO %%E 2 %%I 2 ; COMMANDS MUST BE PERFORMED NOW AND MUST BE ADDED TO %%E 2 ; LB0:[1,2]TOOLS.CMD. ; ; >LOA BT:/PAR=GEN/HIGH ! FOR EXAMPLE ; >INS ''BSPAWN ! INSTALL BSPAWN WHEN BOOTING ; >RUN BSPAWN 1T ! START IT RUNNING ; %%D 3 #-h- bspawn.src 19728 asc 25-mar-82 07:26:11 v1.1 (sw-tools v1.1) %%E 3 %%I 3 #-h- bspawn.src 19728 asc 07-may-82 09:12:01 j (sventek j) %%E 3 .title bspawn .enabl lc .nlist bex ; ; ; system macros needed ; ; .mcall rcst$,rcvd$,spwn$,alun$s,srda$s,dir$,mrkt$s .mcall wtse$s,sdat$s,ustp$s,astx$s,qiow$s,exit$s .mcall fdbdf$,fdat$a,fdop$a,nmblk$,fsrsz$,finit$,get$ .mcall put$,ofnb$,delet$,close$ .mcall swstk$ .page .sbttl local definitions fillun=1 ; lun for file operations ttylun=2 ; lun for terminal messages srlun=3 ; lun for send/receive driver lf=12 ; line feed character cr=15 ; carriage return character qioefn=1 ; event flag for use in terminal messages spnefn=2 ; event flag for use in ASN command ok=0 ; value of OK for tools filerr=-1 ; error return for opening file error fbterr=-2 ; error return for free BT error argerr=-3 ; error return for sending arguments error spnerr=-4 ; error return for spawning subtask error .page .sbttl local macros ; ; ; local macros ; ; ; getlin gets an FCS record into buf with length bufl ; ; .macro getlin buf,bufl mov #'buf,r1 get$ #fdb,r1,#'bufl add f.nrbd(r0),r1 clrb (r1) .endm getlin ; ; ; copy copies 0-byte terminated buffer buf into string ; pointed to by r0 ; ; .macro copy buf mov #'buf,r1 call scopy .endm copy ; ; ; macro for debugging purposes ; ; .macro debug buf mov #'buf,r1 call errmsg .endm debug ; ; error macro ; .macro error msg,reason mov #'reason,r0 mov #'msg,r1 call errmsg jmp sendit .endm error ; ; fatal error macro ; .macro ferror msg mov #'msg,r1 call errmsg jmp exit .endm ferror .page .sbttl local impure data found: .blkw 1 ; switch if "BT" DCB found loaded: .blkw 1 ; switch if "BT" driver loaded dcb: .blkw 1 ; location for address of DCB ucb: .blkw 1 ; location for assigned UCB tcb: .blkw 1 ; location for TCB of requestor offset: .blkw 1 ; location for current offset loccmd: .blkw 1 ; switch if "local" command curesb: .blkw 1 ; location to hold ESB addr of AST ucbptr: .blkw b$$t11 ; storage for UCB addresses errsb: .blkw <8.*b$$t11> ; storage for exit status blocks eb=errsb esbptr: ; array of ESB addresses .rept b$$t11 .word eb ; address of ESB eb=eb+16. ; bump to next ESB .endr reqtsk: ; task name of requestor kept here .rept b$$t11 .word 0,0 .endr number: .blkb 10. ; buffer to format number into bspawn: .rad50 "BSPAWN" ; name of this task rcvbuf: ; 30 byte buffer for received msgs sndtsk: .blkw 2 ; first 2 words have sender's name sndbuf: .blkw 13. ; actual data area for sends and rcvs rcstdb: rcst$ ,rcvbuf ; DPB for receive data or stop rcvddb: rcvd$ ,rcvbuf ; DPB for receive data byedpb: spwn$ MCR...,,,,,spnefn,,,byelin,byelen,,BT ; DPB for BYE command asndpb: spwn$ MCR...,,,,,spnefn,,,mcrlin,,,BT ; DPB for ASN command spwndb: spwn$ MCR...,,,,,,spnast,,mcrlin,,,BT ; DPB for spawn call ; BT is the background terminal for ; which the loadable driver code is ; on the distribution mcrlin: .blkb 80. ; buffer for MCR command line img: .blkb 40. ; buffer to receive the image file imgl=.-img arg: .blkb 256. ; buffer to receive the arg string argl=.-arg syd: .blkb 10. ; buffer to receive SY: string sydl=.-syd ; ; ; data blocks and declarations for FCS ; ; fdb: fdbdf$ ; define FDB fdat$a r.var,fd.cr ; variable length recs, list cctl fdop$a fillun ; lun to use in FCS ops .if ndf SRDRV ; if not using send/receive driver dnam: nmblk$ ,ARG ; default extension on arg file .endc fsrsz$ 1 ; generate FCS buffer space for 1 file fdsc: .word devl ; data-set descriptor .word dev .word dirl .word dir fill: .word 0 .word tmp %%D 3 dev: .ascii "ST0:" %%E 3 %%I 3 dev: .ascii "ST1:" %%E 3 devl=.-dev dir: .ascii "[105,3]" dirl=.-dir tmp: .blkb 20. ; block to scopy filename into tsknam: .ascii ".B" nhigh: .byte 0 nlow: .byte 0 .ascii ".0" .byte 0 .even .page .sbttl pure data sections byelin: .ascii "bye" byelen=.-byelin null: .asciz "" local: .asciz "local" inst: .asciz "ins " taskst: .asciz "/task=" final: .asciz "/pri=25./run=rem" asnst: .asciz "asn " termst: .asciz "=sy:/login/term=bt" fndmsg: .asciz "Cannot find BT device in device list." lodmsg: .asciz "Driver for BT not loaded." filmsg: .asciz "Error opening file from requestor." nbtmsg: .asciz "No free BT units available for background task." argmsg: .asciz "Error queuing arguments for sub-task." spnmsg: .asciz "Error spawning background task." .even .page .sbttl initbt - initialize "BT" information ; ; this routine, called when BSPAWN first comes to life, performs ; the following functions: ; ; 1. switches to the system stack and searches for the "BT" DCB ; 2. if found, then places the addresses of all UCB's in the ; array ucbptr ; 3. returns to the user stack ; ; inputs: ; none ; outputs: ; found YES/NO (1/0) if the DCB for "BT" is found ; loaded YES/NO (1/0) if the "BT" driver is loaded in memory ; dcb address of "BT" DCB ; ucbptr addresses of "BT" UCB's ; .enabl lsb initbt: clr found ; "BT" not found clr loaded ; "BT" not loaded swstk$ 40$ ; switch to system state mov #$devhd,r0 ;# address of device listhead 10$: ;# mov (r0),r0 ;# get next DCB address beq 30$ ;# if == 0, "BT" not found cmp #"BT,d.nam(r0) ;# device name "BT"? bne 10$ ;# NO inc found ;# indicate "BT" found tst d.pcb(r0) ;# driver loaded? beq 30$ ;# NO inc loaded ;# indicate driver loaded mov r0,dcb ;# save DCB address mov d.ucb(r0),r1 ;# get address of first UCB mov #b$$t11,r2 ;# number of UCB's mov #ucbptr,r3 ;# address of pointer array 20$: ;# mov r1,(r3)+ ;# copy UCB address bis #u2.log,u.cw2(r1) ; mark device logged off add d.ucbl(r0),r1 ;# bump to next UCB address sob r2,20$ ;# decrement counter and do again 30$: ;# return ;# return to user state 40$: return ; return to caller .page .sbttl getmsg - get next request ; ; this routine gets the next request for a background spawn. ; these requests are communicated via send/receive packets. ; we do a receive data or stop, and an additional receive data ; if we are stopped and then unstopped by the receive data AST ; .enabl lsb getmsg: dir$ #rcstdb ; receive data or stop cmp #1,$dsw ; receive data? beq 10$ ; YES dir$ #rcvddb ; get data that triggered AST 10$: return .page .sbttl opnfil - open file with bspawn info and read it ; ; this routine opens the file named in the request packet in order ; to fetch the image and argument strings. If any of the steps in ; this process fail, the c bit is retured set, otherwise it is ; cleared. ; ; inputs: ; file name in sndbuf ; ; outputs: ; the file is opened, the image stored in img, the arguments ; in arg, and the file is deleted ; .enabl lsb opnfil: ; ; first build data-set descriptor ; mov #tmp,r0 ; buffer for file name copy sndbuf ; copy name into it mov #tmp,r0 ; crunch to upper case call upper ; crunch to upper case mov #tmp,r1 ; address again call length ; calculate length mov r0,fill ; place length in data-set ; ; open file for reading ; mov #fdb,r0 ; FDB address mov #fdb+f.fnb,r1 ; FNB address mov #fdsc,r2 ; data-set desc address clr r3 ; no default FNB call .parse ; parse file name bcs 10$ ; c set => parse error ofnb$ #fdb,#fo.rd ; open file at read access bcs 10$ ; c set => error ; ; now read the records and delete the file ; getlin img,imgl ; get image name getlin arg,argl ; get arguments getlin syd,sydl ; get SY: string delet$ #fdb ; delete file after closing clc ; c clear => success 10$: return .page .sbttl getfbt - get free BT unit ; ; this routine searches for a free BT unit. If found, it is ; logged in under the UIC of the requestor, and the task name ; of the background task is formatted and rad50'ed. ; if no units are available, the c bit is set, else it is cleared ; .enabl lsb getfbt: mov #reqtsk,r0 ; starting address of owner tasks mov #b$$t11,r1 ; initialize counter mov #maxbck,r2 ; maximum back tasks/requestor mov #sndtsk,r3 ; address of task name to find clr tcb ; initialize task not found swstk$ 2$ ; switch to system state 3$: cmp (r0),sndtsk ; first half match? bne 4$ ; NO cmp 2(r0),sndtsk+2 ; second half match? bne 4$ ; NO dec r2 ; increment number of background tasks beq 1$ ; if == 0, then requestor has limit 4$: add #4,r0 ; bump pointer to next entry sob r1,3$ ; decrement and try again call $srstd ;# search for task in STD bcs 1$ ;# c set => not found mov r0,tcb ;# save TCB address 1$: ;# return ;# return to user state 2$: mov tcb,r0 ; get TCB address beq 40$ ; if == 0, return error mov t.ucb(r0),r0 ; have UCB address of requestor's TI: clr r2 ; initialize offset mov #b$$t11,r3 ; initialize counter 10$: mov ucbptr(r2),r1 ; get next BT UCB address bit #u2.log,u.cw2(r1) ; is it logged on? bne 20$ ; NO add #2,r2 ; bump offset by 2 sob r3,10$ ; decrement counter and go again br 40$ ; return error 20$: bic #u2.log!u2.prv,u.cw2(r1); log it on and init non-priveleged bit #u2.prv,u.cw2(r0) ; is TI: priveleged? beq 30$ ; NO bis #u2.prv,u.cw2(r1) ; make "BT" priveleged 30$: mov u.luic(r0),u.luic(r1) ; login UIC mov u.uic(r0),u.uic(r1) ; default UIC mov r1,ucb ; save ucb address for errmsg mov r2,offset ; save offset for spntsk clc ; clear c bit for multiply rol r2 ; multiply by 2 mov sndtsk,reqtsk(r2) ; copy requestor task name mov sndtsk+2,reqtsk+2(r2) ; ; ; now format the unit number in octal for the task name ; mov #number,r0 ; buffer to format into movb u.unit(r1),r1 ; number to format mov #1,r2 ; desire leading zeros call $cbtmg ; convert byte to octal movb -(r0),nlow ; copy low byte into task name movb -(r0),nhigh ; copy high byte clc ; c clear => success br 50$ 40$: sec ; c set => error 50$: return .page .sbttl asnsyd - spawn ASN command to establish SY: ;+ ; this routine formats up an MCR command of the form ; ; asn ddnn:=sy:/login/term=btmm: ; ; the ddnn: string is passed as the third record of the file sent ; by the requestor and is the unit number of the background ; terminal allocated in getfbt ;- .enabl lsb asnsyd: mov #mcrlin,r0 ; output buffer copy asnst ; copy "asn " copy syd ; copy "ddnn:" copy termst ; copy "=sy:/login/term=bt" movb nhigh,(r0)+ ; move : into buffer movb nlow,(r0)+ ; ... movb #':,(r0)+ ; ... clrb (r0) ; terminate string mov #mcrlin,r1 ; address of string call length ; calculate it's length mov #asndpb,r2 ; address of SPWN DPB mov r0,s.pwcl(r2) ; fill in length of command line mov ucb,r3 ; BT UCB address movb u.unit(r3),r3 ; unit number of BT mov r3,s.pwvt(r2) ; fill in unit number in DPB dir$ r2 ; spawn ASN command bcs 10$ ; c set => error, ignore it wtse$s #spnefn ; wait for command to complete 10$: return .page .sbttl fmtmcr - routine to format the MCR command line ; ; this routine formats the MCR command line for the spawn directive. ; if the image is "local", it copies the arguments to mcrlin and sets ; loccmd = 1, else it sets loccmd to 0 and formats the INS command for ; spawning the tool. ; .enabl lsb fmtmcr: mov #mcrlin,r0 ; destination buffer copy arg ; assume local mov #1,loccmd ; mov #local,r0 ; streq(local,image) == YES? mov #img,r1 ; call streq ; bcc 10$ ; YES clr loccmd ; not local mov #mcrlin,r0 ; destination buffer copy inst ; concatenate strings copy img copy taskst copy tsknam copy final 10$: return .page .sbttl sndarg - send arguments to subtask ; ; this routine sends the arguments to the task prior to spawning it ; .enabl lsb sndarg: clc ; initially c bit clear tst loccmd ; local? bne 10$ ; YES, no args to send .if df SRDRV ; use send/receive driver alun$s #srlun,#"SR,#0 ; assign lun to send/receive bcs 10$ ; c set => error mov #tsknam,r0 ; address to start conversion mov #1,r1 ; don't stop at periods call $cat5 ; convert chars 1-3 mov r1,r4 ; save value mov #1,r1 ; do again call $cat5 ; convert chars 4-6 mov r1,r5 ; save it mov #arg,r1 ; address of buffer call length ; length in r0 qiow$s #io.wlb,#srlun,#qioefn,,,, ; send args .iff ; use argument file clr r1 ; set file prot to call .wdffp ; [rwed,rwed,rwed,rwed] mov #4,fill ; set up data-set descriptor mov #tmp,r0 ; movb #'B,(r0)+ ; movb nhigh,(r0)+ ; movb nlow,(r0)+ ; movb #'0,(r0) ; mov #fdb,r0 ; FDB for parse mov #fdb+f.fnb,r1 ; FNB for parse mov #fdsc,r2 ; data-set desc for parse mov #dnam,r3 ; default FNB call .parse ; parse file name bcs 10$ ; c set => error ofnb$ ,#fo.wrt ; open file at write access bcs 10$ ; c set => error mov #arg,r1 ; address of buffer call length ; length in r0 mov r0,r2 ; length in r2 put$ #fdb,r1,r2 ; write record close$ ; close the file .endc 10$: return .page .sbttl spntsk - spawn background task ; ; this routine spawns the background task. ; .enabl lsb spntsk: mov #mcrlin,r1 ; MCR buffer address call length ; calculate length mov offset,r2 ; get offset into esbptr add #esbptr,r2 ; (r2) is exit status bl addr mov #spwndb,r3 ; address of spwn DPB mov (r2),s.pwes(r3) ; exit status bl addr mov r0,s.pwcl(r3) ; length of command line mov ucb,r2 ; get "BT" UCB address movb u.unit(r2),r2 ; get unit number mov r2,s.pwvt(r3) ; unit number of "BT" dir$ #spwndb ; spawn task bcs 10$ ; c set => error mov #sndbuf,r0 ; get send buffer address movb #ok,(r0)+ ; return OK status copy tsknam ; return task name 10$: return .page .sbttl sndmsg - send response to user ; ; this routine sends the response in sndbuf to the requestor ; .enabl lsb sndmsg: sdat$s #sndtsk,#sndbuf ; send message to requestor ustp$s #sndtsk ; unstop waiting task return .page .sbttl spnast - exit ast routine for subtasks ; ; this routine is entered when one of the background tasks spawned ; by BSPAWN exits. This routine simply searches through its array ; of error status block addresses, in an effort to find the one that ; caused the AST (passed on the bottom of the stack). If found, the ; UCB for that "BT" unit is located, and the u2.log bit is set to ; indicate that the "terminal" is not logged in (i.e. free for use) ; .enabl lsb spnast: mov (sp)+,curesb ; save current ESB address mov r0,-(sp) ; save registers mov r1,-(sp) ; clr r0 ; initialize offset mov #b$$t11,r1 ; initialize counter 10$: cmp esbptr(r0),curesb ; is it this ESB? beq 20$ ; YES add #2,r0 ; increment offset sob r1,10$ ; decrement counter and go again br 30$ ; unknown sub-task 20$: mov ucbptr(r0),r1 ; have "BT" UCB address movb u.unit(r1),r1 ; have "BT" unit number mov r1,byedpb+s.pwvt ; place in SPWN DPB dir$ #byedpb ; log terminal off bcs 25$ ; c set => failure wtse$s #spnefn ; wait for BYE to complete br 26$ 25$: mov ucbptr(r0),r1 ; get UCB address again bis #u2.log,u.cw2(r1) ; log "terminal" off 26$: clc ; clear c bit for multiply rol r0 ; multiply by 2 clr reqtsk(r0) ; clear task name clr reqtsk+2(r0) ; 30$: mov (sp)+,r1 ; restore registers mov (sp)+,r0 ; astx$s ; dismiss AST .page .sbttl unsast - unstop ourselves ; ; ; receive data AST routine ; ; simply unstops the current task, since it is stopped for a ; receive data or stop ; unsast: ustp$s #bspawn ; unstop ourselves astx$s ; dismiss AST .page .sbttl streq - check for string equality ; ; this routine checks for the equality of two 0-byte terminated ; strings. If equal, c-bit clear, else c-bit set ; ; inputs: ; r0 address of one string ; r1 address of other string ; ; outputs: ; r0,r1 destroyed ; c bit set if not equal ; c bit clear if equal ; .enabl lsb streq: cmpb (r0)+,(r1) ; compare next character bne 10$ ; if !=, return c-bit set tstb (r1)+ ; is this 0-byte? bne streq ; NO, try next character clc ; c clear => EQUAL br 20$ ; return 10$: sec ; c set => NOT EQUAL 20$: return .page .sbttl upper - crunch 0-byte terminated string to upper case ; ; ; routine to crunch 0-byte terminated string to upper case ; ; call sequence - call upper ; ; inputs: ; ; r0 - address of 0-byte terminated string ; ; outputs: ; string will have lower case letters changed to upper case ; r0 is destroyed ; leta=141 letz=172 umask=40 upper: cmpb (r0),#leta blt 3$ cmpb (r0),#letz bgt 3$ bicb #umask,(r0) 3$: tstb (r0)+ bne upper return .page .sbttl length - calculate length of 0-byte terminated string ; ; routine to calculate the length of the zero byte terminated ; string pointed to by r1. length returned in r0, r1 is left ; unmodified ; ; length: clr r0 ; initialize count mov r1,-(sp) ; save r1 1$: tstb (r1)+ ; see if 0 byte beq 2$ ; yes, done inc r0 br 1$ 2$: mov (sp)+,r1 ; restore r1 return .page .sbttl scopy - copy 0-byte terminated string into destination ; ; ; routine to copy 0-byte terminated string pointed to by r1 ; to string pointed to by r0. r1 is left pointing to character ; after z byte, and r0 points to next available location ; scopy: movb (r1)+,(r0)+ ; copy byte bne scopy ; try again tstb -(r0) ; backup one byte return .page .sbttl errmsg - display error message and return ; ; ; routine to display error message on terminal. address of ; zero byte terminated message is passed in r1. ; the reason for the error is passed in r0, and copied into ; the send message buffer. ; ; ; ; ; errmsg - print error message on console, place error return in ; sndbuf ; ; ; ; local buffer used by errmsg ; outbuf: .byte lf .ascii "bspawn - " obuf: .blkb 132. .even .enabl lsb errmsg: movb r0,sndbuf ; put reason in send buffer tstb (r1) ; see if null message beq 20$ ; YES mov #obuf,r0 ; destination call scopy ; copy string movb #cr,(r0)+ ; copy return into buffer clrb (r0) ; terminate string mov #outbuf,r1 ; calculate length call length ; length in r0 qiow$s #io.wlb,#ttylun,#qioefn,,,, 20$: mov ucb,r0 ; get ucb address beq 10$ ; if == 0, not allocated yet bis #u2.log,u.cw2(r0) ; set "BT" as logged off mov offset,r0 ; get offset clc ; clear c bit for multiply rol r0 ; multiply by 2 clr reqtsk(r0) ; clear task name clr reqtsk+2(r0) ; 10$: return .page .sbttl main - bspawn main routine ; ; this is the main routine of the bspawn task ; it basically coordinates the rest of the activities by calling ; other modules to do particular types of work ; .enabl lsb start: finit$ ; initialize FCS alun$s #ttylun,#"TI,#0 ; assign lun to TI: clr ucb ; no UCB allocated yet call initbt ; initialize "BT" variables tst found ; was "BT" found? bne 10$ ; YES ferror fndmsg ; report error and die 10$: tst loaded ; is the driver loaded? bne 20$ ; YES ferror lodmsg ; report error and die 20$: srda$s #unsast ; establish receive data AST address 100$: ; main loop starts here clr ucb ; indicate UCB not allocated yet call getmsg ; get next request call opnfil ; open file and read records bcc 30$ ; c clear => successful error null,filerr ; report error to requestor 30$: call getfbt ; get a free "BT" unit bcc 40$ ; c clear => successful error null,fbterr ; report error to requestor 40$: call asnsyd ; spawn ASN command for SY: call fmtmcr ; format MCR command line call sndarg ; send arguments to subtask bcc 50$ ; if c clear => successful error null,argerr ; notify user 50$: call spntsk ; spawn the task bcc sendit ; c clear => successful error null,spnerr ; report error to requestor sendit: call sndmsg ; send response to requestor jmp 100$ ; loop forever exit: exit$s ; task exit .end start #-h- bttab.src 1990 asc 25-mar-82 07:26:22 v1.1 (sw-tools v1.1) .title bttab ; ; .ident /01/ .list meb ; ; data tables for "background terminal" driver ; ; ; j. s. sventek, 09-jul-80 ; ; ; this module provides the loadable driver data tables ; for the background terminal driver. ; .mcall ucbdf$ ucbdf$ ; define bit settings and offsets .sbttl defined symbols and macros ; ; ; defined symbols and macros ; ; ld$bt=0 ; driver is loadable ; ; ; macro to build UCB's ; ; .macro blducb unit btst=. .if df m$$cli .word $mcrpt ; CLI pointer .endc .if df m$$mup!m$$cli .word 0,0 ; u.luic & u.own .endc .bt'unit':: .word .btdcb ; DCB pointer .word .-2 ; redirect pointer .byte uc.que,0 ; notify upon queueing .byte unit',0 ; unit number .word dv.rec!dv.ccl!dv.tty ; device characteristics .word u2.log,0 ; log set => not logged in .word 255. ; pick a size .word $bt0 ; SCB pointer .word 0,0,0,0 ; TCB, u.buf, u.buf+2 & u.cnt .blkw 5 ; extry words for TTY device .word 0 ; u.uic .blkw 2 ; two extra words for TTY btnd=. .endm blducb .page .sbttl DCB .iif df ld$bt, $bttbl=0 $BTDAT:: ; start of data base .btdcb: ; background TTY DCB .word 0 ; pointer to next DCB .word .bt0 ; pointer to first UCB .ascii /BT/ ; device name .byte 0,b$$t11-1 ; first and last units .word btnd-btst ; length of UCB .word $bttbl ; pointer to dispatch table .word 160037,0,160031,0,7,0,1,6 ; function codes .if df l$$drv .word 0 ; PCB address for driver .endc .page .sbttl UCB's unit=0 .rept b$$t11 blducb \unit unit=unit+1 .endr .page .sbttl SCB pr0=0 $bt0:: ; background TTY SCB .word 0,.-2 ; IRP DEQUEUE .byte pr0,0 ; device priority, & vector .byte 0,2 ; current and init timeout .byte 0*2,0 ; cont index and status .word 4 ; CSR address .word 0 ; IRP address .word 0,0,0,0 ; fork block .if df l$$drv&m$$mge .word 0 ; extra word in fork block .endc .if df m$$mge&m$$ext .blkw 6 .endc $BTEND:: ; end of data base .end #-h- btdrv.src 1425 asc 25-mar-82 07:26:24 v1.1 (sw-tools v1.1) .TITLE BTDRV .IDENT /01/ ; ; VERSION 01 ; ; J. S. SVENTEK 09-JUL-80 ; ; BACKGROUND "TERMINAL" DEVICE DRIVER. ; ; MACRO LIBRARY CALLS ; ; EQUATED SYMBOLS ; ; LOCAL DATA ; ; NO CONTROLLER IMPURE DATA TABLES (THERE IS NO DEVICE TO ; CAUSE INTERRUPTS) ; ; DRIVER DISPATCH TABLE ; $BTTBL:: .WORD BTINI ;INITIATION .WORD $INTXT ;CANCEL ($INTXT IS A "RETURN") .WORD $INTXT ;TIMEOUT .WORD $INTXT ;POWERFAIL ;+ ; BTDRV AND DRQIO IMPLEMENT a device bt:, which acts as a null device, ; and is always logged in under the uic [BT$GRP,BR$MEM] ; ; This driver permits tasks to be spawned in the background, with their ; TI: redirected to BT:, thus assuring that the tasks are by default ; directed to the "null" device. ;- ; ; DRQIO (BECAUSE THE UC.QUE BIT IS SET IN THE UCB) SETS THE REGISTERS ; TO THE FOLLOWING: ; ; R1 = ADDRESS OF I/O PACKET ; R4 = ADDRESS OF SCB ; R5 = ADDRESS OF UCB ; ; ONLY TWO FIELDS OF AN I/O PACKET MATTER ; I.FCN+1 = THE I/O FUNCTION CODE. ONLY IO.WLB ; AND IO.RLB MAKE IT TO BTDRV ; I.PRM+4 = IF I.FCN+1 IS IO.WLB, THIS IS THE ; NUMBER OF BYTES THE CALLER WANTS TO WRITE ; BTINI: MOV R1,R3 ;POINT AT PACKET FOR $IOFIN MOV #IS.SUC&377,R0 ;A WRITE ALWAYS SUCCEEDS MOV I.PRM+4(R1),R1 ;SAY EVERYTHING WAS WRITTEN CMPB #IO.WLB/400,I.FCN+1(R3) ;WANTS TO WRITE? BEQ 10$ ;IF EQ YES MOV #IE.EOF&377,R0 ;IT IS A READ CLR R1 ;READ NO CHARACTERS 10$: CALLR $IOFIN ;FINISH OFF PACKET .END %%E 1