PDP7-Unix/sys/s5.s

"** 01-s1.pdf page 28
" s5
	" read/write a process from/to swap space
	" call:
	" AC/ first word of process table
	"   jms dskswap; DSLD bits
dskswap: 0
   cll; als 3			" get process disk address
   dac 9f+t			" save in t0
   jms dsktrans; -64; userdata; 9f+t; dskswap	" read/write user area
   lac 9f+t			" get swap addr back
   tad o20			" advance by 16??
   dac 9f+t			" save
   jms dsktrans; -4096; 4096; 9f+t; dskswap	" read/write user memory
   isz dskswap			" skip bits
   jmp dskswap i		" return
t = t+1

access: 0
   lac i.flags			" get inode flags
   lmq				" save in MQ
   lac u.uid			" get user id
   spa				" negative?
   jmp access i			"  yes: super user, return
   sad i.uid			" compare to file owner
   lrs 2			"  same: shift flags down two
   lacq				" get inode flags back
   and mode			" AND with mode from system call
   sza				" access allowed?
   jmp access i			"  yes: return
   jms error			" no: return error from system call

fassign: 0
   -10				" loop count
   dac 9f+t			" in t0
1:
   lac 9f+t			" get count
   tad d10			" turn into fd
   jms fget			" fetch open file into "fnode"
      jms halt " will not happen
   lac f.flags			" get fnode flags
   sma				" sign bit set (active)?
   jmp 1f			"  no: free
   isz 9f+t			" increment loop count & loop until zero
   jmp 1b
   jmp fassign i
1:
   lac mode			" get mode from system call
   xor o400000			" set sign bit
   dac f.flags			" save in fnode
   lac ii			" get i-number
   dac f.i			" save in fnode
   lac 9f+t
   tad d10			" get fd
   dac u.ac			" return in user AC
   dzm f.badd			" clear file offset in fnode
   jms fput			" copy fnode back into u.ofiles
   isz fassign			" give skip return
   jmp fassign i
t = t+1

	" load fnode (open file entry) from u.ofiles
	" AC/ user fd
	"   jms fget
	"    bad fd
	"   return with fnode set
fget: 0
   jms betwen; d0; d9		" fd 0..9?
      jmp fget i		"  no, return
   cll; mul; 3			" multiply by three
   lacq
"** 01-s1.pdf page 29

   tad ofilesp			" get pointer into u.ofiles
   dac 9f+t			" save in t0
   dac .+2			" save as copy source
   jms copy; ..; fnode; 3	" copy to "fnode"
   isz fget			" give skip return
   jmp fget i

	" copy fnode back to u.ofiles
	" uses temp value set by "fget"
	" (fget and fput calls must be paired)
fput: 0
   lac 9f+t
   dac .+3
   jms copy; fnode; ..; 3
   jmp fput i
t = t+1

	" helper for special device write routines
	" return to caller with next character to write:
	" when done return character count to user.
forall: 0
   lac u.base
   sad u.limit
   jmp 1f			" done
   lac u.base			" get base pointer (again?)
   ral				" rotate MSB into LINK
   lac u.base i			" fetch word via base pointer
   snl				" link set?
   lrs 9			"  no: get low 9 bits
   and o777			" mask to 9 bits
   jmp forall i			" return char
fallr:				" jump here for subsequent characters
   lac u.base			" get base
   add o400000			" advance pointer
   dac u.base			" start from top
   jmp forall+1
1:
   lac u.count
   dac u.ac
   jmp sysexit

	" wait for a condition variable
	" call:
	"   jmr sleep; sfiles+N
sleep: 0
   law ulist-1		" pointer to process table
   dac 8		" in index register
   lac o200000
   lmq			" get 200000 in MQ
1:
   lac u.ulistp i	" get current process status word
   sad 8 i		" compare to next process table entry
   jmp 1f		"  match
   isz 8		" no match: skip other 3 words of process table
   isz 8
   isz 8
   cla; lrs 1		" shift MQ down one
   jmp 1b		" loop
1:
   tad o100000		" mark process not ready
   dac u.ulistp i
   lac sleep i		" get sleep variable pointer
   dac 9f+t
   lac 9f+t i		" get sleep variable contents
   omq			" or in MQ (bit vector of processes waiting)
   dac 9f+t i		" save
   isz sleep		" skip sleep variable pointer
   jmp sleep i
t = t+1

"** 01-s1.pdf page 30

	" look for a free directory entry??
dslot: 0
   dzm di
   skp
1:
   isz di
   lac di
   jms dget			" get directory entry
   lac d.i			" get i number
   sza				" zero (free)?
   jmp 1b			"  no keep looking
   jmp dslot i			" yes: return index

	" called with:
	" AC/ mode
	" name/ file name
icreat: 0
   dac 9f+t			" save mode in t0
   jms dslot
   lac o20			" look for a free inode starting at 17
   dac ii
1:
   isz ii
   lac ii
   jms iget
   lac i.flags
   spa				" "in use" bit bit clear?
   jmp 1b			"  no, guess again
   lac ii
   dac d.i
   jms copy; name; d.name; 4
   isz s.uniq			" get a new unique number
   lac s.uniq
   dac d.uniq			" save in directory entry
   dac i.uniq			" and inode
   lac 9f+t			" get mode
   xor o400000			" set "in use"
   dac i.flags
   lac u.uid			" get user
   dac i.uid			" set owner
   -1
   dac i.nlks			" -1 links?!
   dzm i.size			" empty
   jms copyz; i.dskps; 7	" clear disk block numbers
   jms iput			" write inode
   jms dput			" write directory entry
   jmp icreat i
t = t+1

	" output character to display
dspput: 0
   and o177			" mask to 7 bits
   sna
   jmp i dspput			" discard NUL
   sad o14			" Form Feed?
   jmp 1f			"  yes
   lmq				" save char in MQ
   sad o12			" newline?
   jms dspnl			"  yes
   lac dsploc i			" get display word
   sad o400000			" TRAP?
   jmp dspleft			"  yes (first character)
   omq				" no: or in second character
   dac dsploc i			" save both characters
   isz dsploc			" advance display pointer
   jmp i dspput

"** 01-s1.pdf page 31

1:				" here on form feed
   jms dspinit			" clear display
   jmp dspput i

dspleft:
   lac dsploc			" get display pointer
   sad edspbuf			" end of the buffer?
   jmp 1f			"  yes: light up a button!?
   dac 8			" no: store in index
   lac o400000			" get TRAP instruction
   dac 8 i			" store as next
   cla; llss 18+7		" shift MQ upto "char1" position
   dac dsploc i			" store word with char1
   jmp dspput i

dspnl: 0			" only called once!
   lac dsplno			" get display line number
   sad d33			" 33?
   jmp 1f			"  yes: light a button!
   isz dsplno			" no: increment line number
   jmp dspnl i
1:
   lac o2000			" get bit for push button 7
   wbl				" write button lights
   isz dspput
   jmp dspput i

dspinit: 0
   lac dspbufp3			" get pointer to dspbuf+3
   dac dsploc			" store location
   lac o400000			" display "TRAP" instruction (end of list)
   dac dspbuf+3			" save in buffer
   dzm dsplno			" clear display line number
   jmp dspinit i

	" "move display" (change display buffer pointer)
	" called with new buffer pointer in AC??
movdsp: 0
   iof
   cdf
   dac dspbufp
   -1
   dac .dspb
   ion
   jmp movdsp i

	" fetch user argument from word after "sys" call, return in AC
arg: 0
   lac u.rq+8 i			" fetch word after return PC
   isz u.rq+8			" bump PC
   jmp arg i

	" fetch user pathname argument from pointer word after "sys" call
	" into "name" and look it up (in current working directory)
	" if lookup fails: returns error to user (not caller)
	" if lookup OK: returns with file i-inode read (into "inode")
	"	and i-number in AC
argname: 0
   jms arg			" fetch name pointer
   dac .+2			" save as copy source
   jms copy; ..; name; 4	" copy to "name"
   lac u.cdir			" get CWD
   jms namei; name		" look up file
      jms error			"  failed: return error directly to user
   jmp argname i

	" common code for seek/tell system calls
seektell: 0
   jms arg			" fetch 1st arg after sys
   dac u.base			" save in u.base

"** 01-s1.pdf page 32
   jms arg			" fetch 2nd arg (whence??)
   dac u.limit			" save in u.limit
   jms finac			" fetch fnode & inode for fd in AC
   lac u.limit			" get whence arg back
   sna				" zero?
   jmp seektell i		"  yes, return zero (relative to start)
   sad d1			" one?
   jmp .+3			"  yes: return pos (relative to current)
   lac i.size			" no: return file size (relative to end)
   jmp seektell i
   lac f.badd
   jmp seektell i

	" system call helper
	" fetch system call argument name pointer from after "sys" call
	" read inode; if current user is not owner, return error to user
isown: 0
   jms argname
   jms iget
   lac u.uid			" get user id
   sma				" super user?
   sad i.uid			"  no: does user own file?
   skp				"   yes, or super user
   jms error			"    not super user, not owner: return error
   jmp isown i