mirror of
https://github.com/PDP-10/its.git
synced 2026-03-03 10:22:59 +00:00
726 lines
17 KiB
Plaintext
726 lines
17 KiB
Plaintext
;;; -*-Midas-*-
|
||
|
||
title DQXDEV -- Fake DQDEV so COMSAT won't keep barfing its cookies
|
||
|
||
;;; If you think this looks a lot like LPDEV, you're right.
|
||
|
||
;;; Accumulators
|
||
|
||
a==:1
|
||
b==:2
|
||
c==:3
|
||
d==:4
|
||
e==:5
|
||
t==:6
|
||
tt==:7
|
||
|
||
x==:10 ; used in RENMWO code as CH/IN index
|
||
y==:11 ; used in SIOT code to handle PCLSRing
|
||
; what the hell, make these ACs too
|
||
rrptr==:15 ; Pointer to buffered answer
|
||
rrecnt==:16 ; Byte count of buffered answer
|
||
|
||
p=:17
|
||
|
||
;;; Channels
|
||
|
||
tty==:1 ; for debugging
|
||
boj==:2 ; for talking to the user
|
||
dsk==:3 ; for reading HOSTS3
|
||
|
||
;;; Flags
|
||
|
||
%f==:0,,525252 ; Flags in RH(0)
|
||
%fdbug==:000100 ; Being debugged as an OJB server under DDT
|
||
%fval==: 000200 ; BOJ interrupts clear this "valid" bit
|
||
%frwo==: 000400 ; User last seen in a RENMWO
|
||
%fiot==: 001000 ; User last seen in an IOT
|
||
%fsiot==:002000 ; User last seen in a SIOT
|
||
%fclos==:004000 ; User last seen in a CLOSE
|
||
|
||
;;; Instructions and macros
|
||
|
||
.insrt system;t20mac >
|
||
|
||
call=: pushj p,
|
||
ret=: popj p,
|
||
pause=: .break 16,100000
|
||
tyo=: .iot tty,
|
||
nop=: jfcl
|
||
|
||
retskp=:jrst .
|
||
rskp: aos (p)
|
||
r: ret
|
||
|
||
quit=: call .
|
||
$quit: trne %fdbug
|
||
pause
|
||
.logout 1,
|
||
|
||
define syscall name,args
|
||
.call [setz ? sixbit /name/ ? args(400000)]
|
||
termin
|
||
|
||
define report &text&
|
||
call [ trnn %fdbug
|
||
ret
|
||
call $report
|
||
.length text
|
||
ascii text]
|
||
termin
|
||
|
||
$repor: exch t,(p)
|
||
push p,tt
|
||
move tt,0(t)
|
||
movei t,1(t)
|
||
hrli t,440700
|
||
tyo [^P]
|
||
tyo ["A]
|
||
syscall siot,[movei tty ? t ? tt]
|
||
.lose %lssys
|
||
tyo [^P]
|
||
tyo ["A]
|
||
pop p,tt
|
||
pop p,t
|
||
ret
|
||
|
||
define barf code
|
||
jrst [movsi tt,code ? jrst $barf]
|
||
termin
|
||
|
||
$barf: .call joberr
|
||
quit
|
||
quit
|
||
|
||
IF1,[
|
||
|
||
DEFINE IFCE A,B
|
||
IFE SIXBIT/A/-SIXBIT/B/,TERMIN ;SUBSTITUTE FOR IFSE THAT IGNORES CASE
|
||
|
||
PRINTX /Limit to KA-10 instructions? /
|
||
.TTYMAC KAONLY
|
||
IRPS Z,,[YES Y]
|
||
IFCE Z,KAONLY,{
|
||
$$KA10==1
|
||
.ISTOP
|
||
}
|
||
TERMIN
|
||
TERMIN
|
||
|
||
IFNDEF $$KA10, $$KA10==0
|
||
]
|
||
|
||
$$arpa==1
|
||
$$chaos==1
|
||
$$hostnm==1
|
||
$$symlook==1
|
||
.insrt syseng;netwrk
|
||
|
||
.vector pdl(lpdl==:50.)
|
||
|
||
go: setz ; clear flags
|
||
move p,[-lpdl,,pdl-1]
|
||
.suset [.roption,,a]
|
||
tlnn a,%opddt
|
||
jrst noddt
|
||
tro %fdbug
|
||
tlo a,%opojb
|
||
.open tty,[.uao\%tjdis,,'tty ? setz ? setz]
|
||
.lose %lssys
|
||
.value [asciz ""]
|
||
noddt: tlo a,%opint\%opopc
|
||
move tt,[-3,,[ .soption,,a
|
||
.smsk2,,[1_boj]
|
||
.sdf2,,[1_boj]
|
||
]]
|
||
.suset tt
|
||
report "Ready..."
|
||
.open boj,[.uio,,'boj ? setz ? setz]
|
||
quit
|
||
move tt,[-loargs,,oargs]
|
||
.call jobcal
|
||
quit
|
||
tlne t,%jgcls ; Why does this happen?
|
||
quit
|
||
hrrzs t
|
||
caie t,%joopn ; better be an open call
|
||
barf %enrdv ; it wasn't, device not ready
|
||
hrrz t,omode
|
||
caie t,.uii ; only mode we support
|
||
barf %ensmd
|
||
setzm hstdat ; No table mapped in yet so no table date
|
||
setzm chkdat ; Never checked it either
|
||
.call jobrt0 ; tell user we're open
|
||
quit
|
||
|
||
tro %fval ; Haven't taken any interrupts yet...
|
||
report "opened, enabling PI"
|
||
.suset [.sdf2,,[0]] ; Enable BOJ interrupts
|
||
; fall into noose
|
||
|
||
noose: trne %fval ; Do we understand the situation?
|
||
.hang ; Yes: Twiddle thumbs
|
||
report "MP wakeup"
|
||
tro %fval ; Set valid flag
|
||
trne %fclos ; Trying to close?
|
||
quit ; Yup, do it
|
||
trne %frwo ; New query to process?
|
||
jrst query ; Yup, go do it
|
||
trne %fiot\%fsiot ; User wants to read something?
|
||
jrst output ; Yup, send it off
|
||
trne %fval ; Still valid and didn't dispatch?
|
||
report "MP wakeup for no apparent reason"
|
||
jrst noose ; Go try again in any case
|
||
|
||
;; jrst here at MP level when user wants to read from us
|
||
output: report "client output request"
|
||
move a,iotcnt ; how many bytes user wants
|
||
caml a,rrecnt ; more than we have?
|
||
move a,rrecnt ; yeah, just give what's available
|
||
move b,a ; remember how much we are offering
|
||
move c,iotcnt ; save count (timing screw)
|
||
movei y,1 ; pclsr protection (also see bojint handler)
|
||
trnn %fval ; still valid?
|
||
jrst noose ; no, punt
|
||
ifn. a ; if we have something to give
|
||
xct [nop ? .call siot](y) ; do it
|
||
xct [nop ? .lose %lssys](y) ; handle errors
|
||
sub a,b ; count off what we gave to user
|
||
addm a,rrecnt
|
||
endif.
|
||
camn b,c ; gave a different amount than user wanted?
|
||
ifskp. ; yup, have to unblock user
|
||
trne %fval ; don't bother if doesn't care
|
||
.call jobrt0 ; unblock
|
||
nop ; oh well, we tried
|
||
endif.
|
||
jrst noose ; dismiss again
|
||
|
||
;; .CALL SIOT
|
||
siot: setz ? sixbit 'siot' ? movei boj ? rrptr ? setz a
|
||
|
||
|
||
|
||
.scalar rrecs(lrrecs==400) ; biiig buffer
|
||
.scalar qname(64./5)
|
||
.scalar qtype(2),qclass
|
||
|
||
;; jrst here at MP level to read RENMWO filenames, HOSTS3, and setup answer
|
||
query: report "processing new request"
|
||
call mapin ; map in HOSTS3 if needed
|
||
trnn %fval ; might take a while, see if should abort
|
||
jrst noose ; yup
|
||
report "snarfing long filename"
|
||
call snarf ; get long filename from user
|
||
jrst noose ; snarf lost somehow
|
||
trnn %fval
|
||
jrst noose
|
||
report "processing query"
|
||
call parse ; parse funny long filename and lookup in table
|
||
jrst noose ; lost (already JOBERRed), punt
|
||
trnn %fval ; make sure still valid
|
||
jrst noose
|
||
report "JOBRETing from RENMWO"
|
||
.call jobrt0 ; still valid, try to return it to user
|
||
nop ; oh well
|
||
jrst noose ; done in any case
|
||
|
||
badarg: movsi tt,%ebdrg ; meaningless argument
|
||
.call joberr
|
||
ret
|
||
|
||
pagmsk==:0,,776000 ; mask for page field of address
|
||
|
||
.scalar path(100)
|
||
|
||
snarf: setzm path ; paranoia
|
||
skipn xptr ; string pointer in user space
|
||
jrst badarg ; sorry, no sixbit domain names!
|
||
ldb a,[.bp pagmsk,xptr] ; client's page address
|
||
movei b,clntpg ; our page address
|
||
.uset boj,[.ruindex,,c] ; client's job index
|
||
tlo c,400000 ; make into job spec
|
||
syscal corblk,[movei %cbndr ? movei %jself ? b ? c ? a]
|
||
ret ; give up if can't get at least first page
|
||
aos a ? aos b ; try second page in case -long- pathname
|
||
syscal corblk,[movei %cbndr ? movei %jself ? b ? c ? a]
|
||
nop ; not that important
|
||
move a,[440700,,path] ; cons up pathname
|
||
move b,xptr ; get client context pointer
|
||
movei c,clntpg ; page where we mapped it
|
||
dpb c,[.bp pagmsk,b] ; bash in our page number
|
||
hlre c,xptr ; get lh of pointer
|
||
skipn c ; lazy bp?
|
||
hrli b,440700 ; yup, fix it up
|
||
jumpge c,.+3 ; check for aobjn type pointer
|
||
caml c,[-63.] ; ( -1 .ge. x .ge. -63 )
|
||
jrst badarg ; is aobjn pointer, tough noogies
|
||
; got good bp, copy string
|
||
ildb c,b ; get a byte
|
||
idpb c,a ; dump a byte
|
||
jumpn c,.-2 ; keep going till null
|
||
move a,[-2,,clntpg] ; unmap client page(s)
|
||
syscal corblk,[movei ? movei %jself ? a]
|
||
nop ; not that important (I hope!)
|
||
retskp
|
||
|
||
.scalar hstdat ; date of last table gobbled
|
||
.scalar chkdat ; date of last check
|
||
minchk==2*60.*5 ; five minutes (in half sec units)
|
||
|
||
mapin: syscal rqdate,[movem a ? movem b]
|
||
.lose
|
||
move c,a ; current time, hang onto it
|
||
sub a,chkdat ; how long since last check
|
||
jumpl b,.+3 ; clock not set, better check
|
||
caige a,minchk ; long enough wait?
|
||
ret ; nah, we just did that
|
||
movem c,chkdat ; remember time of this check
|
||
syscal open,[movsi .bii ? movei dsk ? [sixbit 'dsk'] ; <
|
||
[sixbit 'HOSTS3'] ? [sixbit '>'] ? [sixbit 'SYSBIN']]
|
||
.lose %lsfil ; Look up creation date of host table
|
||
syscal rfdate,[movei dsk ? movem a] ; Get creation time.
|
||
.lose %lssys
|
||
came a,hstdat ; Compare with time of last file gobbled
|
||
ifskp. ; is same?
|
||
.close dsk, ; yeah, close channel and exit
|
||
ret
|
||
endif.
|
||
movem a,hstdat ; Note new version to map in.
|
||
report "reading new HOSTS3"
|
||
movei a,hstpag
|
||
movei b,dsk
|
||
call netwrk"hstmap ; Map in host table and close channel.
|
||
.lose
|
||
ret ; done
|
||
|
||
|
||
;;; PARSE - Parse the ASCIZ pathname from PATH.
|
||
;;; Skips if pathname appears to be properly formed.
|
||
;;; If non-skip, gives JOBERR with appropriate code.
|
||
|
||
;;; mask for uppercasing single word of ascii
|
||
ucmask: .byte 7 ? 40 ? 40 ? 40 ? 40 ? 40 ? .byte
|
||
|
||
parse: move a,[440700,,path]
|
||
setz b,
|
||
move c,[-1,,":]
|
||
call parnxt ; skip over device name.
|
||
jrst parluz
|
||
setz b, ; skip over query opcode (!!)
|
||
move c,[-1,,";]
|
||
call parnxt ; find query opcode.
|
||
jrst parluz
|
||
move b,[440700,,qclass]
|
||
move c,[-1,,";]
|
||
setzm qclass
|
||
call parnxt ; find class token.
|
||
jrst parluz
|
||
move b,[440700,,qtype]
|
||
setzm qtype
|
||
call parnxt ; find type token.
|
||
jrst parluz
|
||
move b,[440700,,qname]
|
||
setzb c,qname
|
||
call parnxt ; find qname
|
||
.lose ; never happens
|
||
move a,ucmask ; uppercasify
|
||
andcab a,qclass ; all valid names are short...
|
||
came a,[ascii "IN"] ; check two classes we know
|
||
camn a,[ascii "CH"]
|
||
ifskp. ; neither of them, punt
|
||
movsi tt,%ensdr ; bad class
|
||
.call joberr ; give error to user
|
||
nop ; ignore lossage
|
||
ret ; failing return
|
||
endif.
|
||
setzm rrecs ; clear out answer buffer
|
||
move tt,[rrecs,,rrecs+1]
|
||
blt tt,rrecs+lrrecs-1
|
||
setzm rrecnt ; no characters yet
|
||
move tt,[444400,,rrecs] ; bp for output routine
|
||
movem tt,rrptr
|
||
move a,ucmask ; uppercasify
|
||
andcab a,qtype ; all valid types also short
|
||
camn a,[ascii "A"] ; dispatch on valid qtypes
|
||
jrst qt.a
|
||
camn a,[ascii "PTR"]
|
||
jrst qt.ptr
|
||
camn a,[ascii "HINFO"]
|
||
jrst qt.hin
|
||
movsi tt,%ensdr ; bad qtype
|
||
.call joberr ; give error to user
|
||
nop ; ignore lossage
|
||
ret ; failing return
|
||
|
||
parluz: movsi tt,%ebdfn ; Here if pathname seems to
|
||
.call joberr ; be malformed (illegal file name).
|
||
nop ; give error to user
|
||
ret ; and return failure
|
||
|
||
;;; PARNXT gets the next token from A into B.
|
||
;;; RH C is break char, LH C is -1 to ignore spaces.
|
||
|
||
parnxt: do.
|
||
ildb t,a ; get char.
|
||
cain t,(c) ; if delimiter return win
|
||
exit.
|
||
jumpe t,r ; if null, return lose
|
||
cain t,40 ; if space and we're suppose to skip spaces
|
||
jumpl c,top. ; then do so
|
||
skipe b ; if b nonzero bp
|
||
idpb t,b ; copy chars
|
||
loop. ; next
|
||
enddo.
|
||
setz t, ; ascizify
|
||
skipe b
|
||
idpb t,b
|
||
retskp
|
||
|
||
;; here for PTR rr fake
|
||
qt.ptr: move a,qclass ; which type of foo-ADDR are we lookinf for?
|
||
came a,[ascii "CH"] ; Chaosnet?
|
||
tdza x,x ; no (IN: x=0)
|
||
movei x,1 ; yes (CH: x=1)
|
||
move t,[440700,,qname] ; find length of name
|
||
call strlen
|
||
move a,t ; save that
|
||
move b,[440700,,[asciz ".IN-ADDR.ARPA"] ; trailer string
|
||
440700,,[asciz ".CH-ADDR.MIT.EDU"]](x)
|
||
move t,b ; get its length
|
||
call strlen
|
||
sub a,t ; get difference
|
||
ifg. a ; better be something left!
|
||
IFN $$KA10,[
|
||
move t,[440700,,qname]
|
||
ibp t
|
||
sojg a, .-1
|
||
move a,t
|
||
]
|
||
IFE $$KA10,[
|
||
adjbp a,[440700,,qname] ; point at where trailer should be
|
||
]
|
||
call strcmp ; strings match?
|
||
anskp. ; yup
|
||
setz t, ; tie off string
|
||
idpb t,a
|
||
call @[nin.in ? nin.ch](x) ;call appropriate number parser
|
||
anskp. ; if that wins we have host number in B
|
||
else. ; address spec bogus somehow
|
||
movsi tt,%ebdfn ; bad filename
|
||
trne %fval ; don't bother jobreting if not valid
|
||
.call joberr ; still valid, punt the luser
|
||
nop ; oh well
|
||
ret ; return failure
|
||
endif.
|
||
call netwrk"hstsrc ; look up the host
|
||
ifskp. ; did that win?
|
||
hrli a,440700 ; yup, make bp
|
||
move tt,[-lrrecs,,rrecs]
|
||
call outstr ; dump string to output buffer
|
||
retskp ; return win
|
||
else. ; hstsrc failed
|
||
movsi tt,%ensfl ; name error
|
||
trne %fval ; if still valid
|
||
.call joberr ; try to punt the user
|
||
nop ; oh well
|
||
ret ; return lose
|
||
endif. ; bye bye
|
||
|
||
rrovfl: .lose ; here if we overflow rrecs
|
||
|
||
;; routine to dump string in A down AOBJN pointer in TT
|
||
outstr: saveac [a,b,t] ; dont' trash acs we use
|
||
move t,a ; find out length
|
||
call strlen
|
||
movem t,(tt) ; store length
|
||
addm t,rrecnt ; here too
|
||
aos rrecnt ; (count the length word in user buffer)
|
||
aobjp tt,rrovfl
|
||
do. ; copy all bytes
|
||
ildb b,a
|
||
movem b,(tt)
|
||
aobjp tt,rrovfl ; crap out if overflow buffer
|
||
sojg t,top.
|
||
enddo. ; if we make it here we won
|
||
ret
|
||
|
||
;; here for name to address lookups
|
||
qt.a: move a,[440700,,qname]
|
||
call netwrk"hstlook ; find the name
|
||
ifskp. ; found it
|
||
move b,a ; get SITE entry
|
||
call netwrk"hstsrc
|
||
anskp. ; never happens, we hope
|
||
move e,netwrk"stradr(d) ; get ADDRESS table entry
|
||
move a,qclass ; figure out what kind of address we want
|
||
came a,[ascii "CH"] ; chaos?
|
||
skipa a,[tlne b,(netwrk"ne%unt)] ; no, want Unternet bit OFF
|
||
move a,[tlnn b,(netwrk"ne%unt)] ; yes, want Unternet bit ON
|
||
move tt,[-lrrecs,,rrecs]
|
||
do. ; loop over all addresses
|
||
move b,hsttab+netwrk"addadr(e)
|
||
xct a ; is this address a winner?
|
||
ifskp. ; yup
|
||
movem b,(tt) ; store it for client
|
||
aos rrecnt ; count it
|
||
aobjp tt,endlp. ; exit loop if ran out of buffer
|
||
endif.
|
||
hrrz e,hsttab+netwrk"adrcdr(e)
|
||
jumpn e,top. ; CDR to next address
|
||
enddo.
|
||
skipn rrecnt ; now, did we get anything?
|
||
anskp. ; damned well better have
|
||
retskp ; yeah, we won
|
||
else. ; lost somewhere along the line
|
||
movsi tt,%ensfl ; make it NAME ERROR
|
||
trne %fval ; (this isn't correct if just aren't any
|
||
.call joberr ; addresses for this class and name, but
|
||
nop ; nobody cares right now anyway...)
|
||
ret
|
||
endif.
|
||
|
||
;; here to look up HINFO data
|
||
qt.hin: move a,[440700,,qname]
|
||
call netwrk"hstlook
|
||
ifskp.
|
||
move b,a
|
||
call netwrk"hstsrc
|
||
anskp. ; machine and opsys info
|
||
move e,netwrk"stlsys(d)
|
||
move tt,[-lrrecs,,rrecs]
|
||
ifxn. e,<0,,-1>
|
||
move a,[440700,,hsttab]
|
||
addi a,(e) ; dump machine type if exists
|
||
call outstr
|
||
else. ; no string present
|
||
setzm (tt) ; fake zero length string
|
||
aos rrecnt
|
||
aobjp tt,rrovfl
|
||
endif.
|
||
movss e ; now handle opsys
|
||
ifxn. e,<0,,-1> ; same drill
|
||
move a,[440700,,hsttab]
|
||
addi a,(e)
|
||
call outstr
|
||
else.
|
||
setzm (tt)
|
||
aos rrecnt
|
||
aobjp tt,rrovfl
|
||
endif.
|
||
retskp ; if we made it here we won
|
||
else.
|
||
movsi tt,%ensfl ; name error, i guess
|
||
trne %fval
|
||
.call joberr
|
||
nop
|
||
ret
|
||
endif.
|
||
|
||
;; count length of an asciz string in T, return length in T
|
||
strlen: saveac [a,b]
|
||
move a,t
|
||
setz t,
|
||
do.
|
||
ildb b,a
|
||
skipe b
|
||
aoja t,top.
|
||
enddo.
|
||
ret
|
||
|
||
;; compare two strings, skip iff eq. smashes nothing
|
||
strcmp: saveac [a,b,c,d]
|
||
do.
|
||
ildb c,a
|
||
ildb d,b
|
||
andi c,137
|
||
andi d,137
|
||
came c,d
|
||
ret
|
||
jumpn c,top.
|
||
enddo.
|
||
retskp
|
||
|
||
;; parse a number from string in A. radix in C. value returned in T.
|
||
;; TT contains character that caused us to stop.
|
||
nin: setz t,
|
||
do.
|
||
ildb tt,a
|
||
cail tt,"0
|
||
caile tt,"9
|
||
ret
|
||
imul t,c
|
||
addi t,-"0(tt)
|
||
loop.
|
||
enddo.
|
||
|
||
;; address parsers. value returned in B. skips iff ok.
|
||
|
||
;; read a chaosnet address number (just a single octal number)
|
||
nin.ch: move a,[440700,,qname] ; where the string is
|
||
movei c,8. ; octal
|
||
call nin ; read it
|
||
jumpn tt,r ; better have ended with null
|
||
jumple t,r ; and be a reasonable number
|
||
cail t,177777
|
||
ret
|
||
hrli t,40700 ; add Unternet constant
|
||
move b,t ; save result
|
||
retskp ; won
|
||
|
||
;; read an internet address number in reverse format (yum!)
|
||
nin.in: move a,[440700,,qname] ; where the string lives
|
||
setz b, ; no address yet
|
||
movei c,10. ; decimal
|
||
irp foo,,[".,".,".,0]
|
||
call nin
|
||
jumpl t,r
|
||
caig t,377
|
||
caie tt,foo
|
||
ret
|
||
dpb t,[<<.irpcnt_15.>+001000>,,b]
|
||
termin
|
||
retskp
|
||
|
||
tsint:
|
||
loc 42
|
||
-ltsint,,tsint
|
||
loc tsint
|
||
intacs,,p
|
||
0 ? 1_boj ? %piioc ? 1_boj ? bojint
|
||
ltsint==:.-tsint
|
||
|
||
intacs==:400002+t_6 ; 3 things plus T and TT
|
||
|
||
;;; .CALL DISMIS: Dismiss an interrupt
|
||
dismis: setz
|
||
sixbit /dismis/
|
||
movsi intacs
|
||
setz p
|
||
|
||
|
||
;;; Handle interrupt on the BOJ channel
|
||
bojint: report "BOJ interrupt"
|
||
trz %fiot\%fsiot\%frwo\%fval
|
||
setz y, ; (see OUTPUT routine)
|
||
move tt,[-largs,,args]
|
||
.call jobcal
|
||
jrst disint
|
||
tlne t,%jgcls ; .close ?
|
||
seto t, ; yeah, fake the offset
|
||
call @caltbl(t) ; dispatch to handler
|
||
disint: .call dismis ; back to MP level
|
||
.lose %lssys
|
||
jrst disint
|
||
|
||
close ; .close (fake offset -1)
|
||
caltbl: offset -.
|
||
%joopn:: caldie ; .open (?)
|
||
%joiot:: iot ; .iot
|
||
%jolnk:: caldie ; mlink (?)
|
||
%jorst:: calwtd ; .reset
|
||
%jorch:: caldie ; .rchst
|
||
%joacc:: calwtd ; .access
|
||
%jornm:: caldie ; .fdele (delete or rename) (?)
|
||
%jorwo:: renmwo ; .fdele (renmwo)
|
||
%jocal:: caldie ; .call
|
||
offset 0
|
||
|
||
caldie: .lose
|
||
|
||
close: report "CLOSE"
|
||
tro %fclos ; set a flag
|
||
ret ; and dismis
|
||
|
||
iot: report "IOT"
|
||
tlnn t,%jgsio
|
||
troa %fiot
|
||
tro %fsiot
|
||
ret
|
||
|
||
renmwo: report "RENMWO"
|
||
tro %frwo
|
||
ret
|
||
|
||
calwtd: report "%EBDDV"
|
||
movsi tt,%ebddv
|
||
.call joberr
|
||
nop
|
||
ret
|
||
|
||
;;; .CALL JOBCAL: Get system call and arguments
|
||
;;; TT (arg): aobjn to args area
|
||
;;; T (val): opcode
|
||
jobcal: setz
|
||
sixbit /jobcal/
|
||
movei boj
|
||
move tt
|
||
setzm t
|
||
|
||
;;; .CALL JOBRET: Return values from system call
|
||
;;; TT (arg): aobjn to values
|
||
jobret: setz
|
||
sixbit /jobret/
|
||
movei boj
|
||
movei 1
|
||
setz tt
|
||
|
||
;;; .CALL JOBRT0: Return no values from system call
|
||
jobrt0: setz
|
||
sixbit /jobret/
|
||
movei boj
|
||
setzi 1
|
||
|
||
;;; .CALL JOBERR: Return error from system call
|
||
;;; TT (arg): <error code>,,0
|
||
joberr: setz
|
||
sixbit /jobret/
|
||
movei boj
|
||
setz tt
|
||
|
||
;;; .CALL JOBIOC: Cause IOC error
|
||
;;; T (arg): error code
|
||
jobioc: setz
|
||
sixbit /jobioc/
|
||
movei boj
|
||
setz t
|
||
|
||
constants
|
||
variables
|
||
|
||
oargs:: ;; Arguments provided to initial OPEN, MLINK, DELETE or RENAME
|
||
oxfn1: 0 ; OX... Second set of filenames
|
||
ofn1: 0 ; O... First set of filenames
|
||
ofn2: 0
|
||
odir: 0
|
||
odev: 0
|
||
oxfn2::
|
||
omode: 0 ; 18 bit open mode in right half
|
||
oxdir: 0
|
||
optr: 0 ; String arguments if given.
|
||
oxptr: 0
|
||
loargs==:.-oargs
|
||
|
||
args:: ;; Arguments provided to subsequent calls
|
||
iotcnt:: ; IOT byte count
|
||
calnam: 0 ; .CALL sixbit name
|
||
calbts: 0 ; .CALL control bits
|
||
callen: 0 ; .CALL argument count
|
||
arg1: 0 ; .CALL arg 1
|
||
arg2: 0 ; .CALL arg 2
|
||
arg3: 0 ; .CALL arg 3
|
||
arg4: 0 ; .CALL arg 4
|
||
arg5: 0 ; .CALL arg 5
|
||
xptr:: ; RENMWO string argument
|
||
arg6: 0 ; .CALL arg 6
|
||
largs==:.-args
|
||
|
||
ffpage==:<.+1777>_-12 ; First free page
|
||
|
||
clntpg==:ffpage ; where to map user pages
|
||
|
||
hstpag==:ffpage+2
|
||
hsttab=:hstpag_12 ; where to map host table
|
||
|
||
end go
|