--- /dev/null
+/ init -- process control initialization
+
+mount = 21.
+
+ sys intr; 0 / turn off interrupts
+ sys quit; 0
+ cmp csw,$73700 / single user?
+ bne 1f / no
+help:
+ clr r0 / yes
+ sys close / close current read
+ mov $1,r0 / and write
+ sys close / files
+ sys open; ctty; 0 / open control tty
+ sys open; ctty; 1 / for read and write
+ sys exec; shell; shellp / execute shell
+ br help / keep trying
+1:
+ mov $'0,r1 / prepare to change
+1 :
+ movb r1,tapx+8 / mode of dec tape drive x, where
+ sys chmod; tapx; 17 / x=0 to 7, to read/write by owner or
+ inc r1 / non-owner mode
+ cmp r1,$'8 / finished?
+ blo 1b / no
+ sys mount; rk0; usr / yes, root file on mounted rko5
+ / disk ls /usr
+ sys creat; utmp; 16 / truncate /tmp/utmp
+ sys close / close it
+ movb $'x,zero+8. / put identifier in output buffer
+ jsr pc,wtmprec / go to write accting info
+ mov $itab,r1 / address of table to r1
+
+/ create shell processes
+
+1:
+ mov (r1)+,r0 / 'x, x=0, 1... to r0
+ beq 1f / branch if table end
+ movb r0,ttyx+8 / put symbol in ttyx
+ jsr pc,dfork / go to make new init for this ttyx
+ mov r0,(r1)+ / save child id in word offer '0, '1,...etc.
+ br 1b / set up next child
+
+/ wait for process to die
+
+1:
+ sys wait / wait for user to terminate process
+ mov $itab,r1 / initialize for search
+
+/ search for process id
+
+2:
+ tst (r1)+ / bump r1 to child id location
+ beq 1b / ? something silly
+ cmp r0,(r1)+ / which process has terminated
+ bne 2b / not this one
+
+/ take name out of utmp
+
+ sub $4, r1 / process is found, point x' to 'x
+ / for it
+ mov r1,-(sp) / save address on stack
+ mov (r1),r1 / move 'x to r1
+ sub $'0,r1 / remove zone bits from character
+ asl r1 / generate proper
+ asl r1 / offset
+ asl r1 / for
+ asl r1 / seek
+ mov r1,0f / move it to offset loc for seek
+ mov $zero,r1
+2:
+ clr (r1)+ / ccear-
+ cmp r1,$zero+16. / output buffer
+ blo 2b / area
+ sys open; utmp; 1 / open file for writing
+ bes 2f / if can't open, create user anyway
+ mov r0,r1 / save file desc
+ sys seek; 0:..; 0 / move to proper pointer position
+ mov r1,r0 / not required
+ sys write; zero; 16. / zero this position in
+ mov r1,r0 / restore file descriptor
+ sys close / close file
+
+/ re-create user process
+
+2:
+ mov (sp)+,r1 / restore 'x to r1
+ mov (r1)+,r0 / move it to r0
+ movb r0,ttyx+8 / get correct ttyx
+ movb r0,zero+8 / move identifier to output buffer
+ jsr pc,wtmprec / go to write accting into
+ jsr pc,dfork / fork
+ mov r0,(r1)+ / save id of child
+ br 1b / go to wait for next process end
+
+dfork:
+ mov r1,r2
+ sub $itab+2,r2 / left over
+ asl r2 / from previous
+ asl r2 / version of code
+ mov r2,offset
+ sys fork
+ br 1f / to new copy of init
+ bes dfork / try again
+ rts pc / return
+1 :
+ sys quit; 0 / new init turns off
+ sys intr; 0 / interrupts
+ sys chown; ttyx; 0 / change owner to super user
+ sys chmod; ttyx; 15 / changemode to read/write owner,
+ / write non-owner
+ sys open; ttyx; 0 / open this ttyx for reading
+ / and wait until someone calls
+ bes help1 / branch if trouble
+ sys open; ttyx; 1 / open this ttyx for writing after
+ / user call
+ bes help1 / branch if trouble
+ sys exec; getty; gettyp / getty types <login> and
+ / executes login which logs user
+ / in and executes sh-
+ sys exit / HELP!
+
+help1:
+ jmp help / trouble
+
+wtmprec:
+ sys time / get time
+ mov ac,zero+10. / more to output
+ mov mq,zero+12. / buffer
+ sys open; wtmp; 1 / open accounting file
+ bes 2f
+ mov r0,r2 / save file descriptor
+ sys seek; 0; 2 / move pointer to end of file
+ mov r2,r0 / not required
+ sys write; zero; 16. / write accting info
+ mov r2,r0 / restore file descriptor
+ sys close / close file
+2:
+ rts pc
+
+ctty: </dev/tty\0>
+shell: </bin/sh\0>
+shellm: <-\0>
+tapx: </dev/tapx\0>
+rk0: </dev/rk0\0>
+utmp: </tmp/utmp\0>
+wtmp: </tmp/wtmp\0>
+ttyx: </dev/ttyx\0>
+getty: </etc/getty\0>
+usr: </usr\0>
+ .even
+
+shellp: shellm
+ 0
+gettyp: getty
+ 0
+itab:
+ '0; ..
+ '1; ..
+ '2; ..
+ '3; ..
+ '4; ..
+ '5; ..
+ '6; ..
+ '7; ..
+ 0
+
+offset: .=.+2
+zero: .=.+8; .=.+6; .=.+2
--- /dev/null
+/ sh -- command interpreter
+ mov sp,r5
+ mov r5,shellarg / save orig sp in shellarg
+ cmpb *2(r5),$'- / was this sh calleZd by init or loginx~
+ bne 2f / no
+ sys intr; 0 / yes, turn off interrupts
+ sys quit; 0
+2:
+ sys getuid / who is user
+ tst r0 / is it superuser
+ bne 2f / no
+ movb $'#,at / yes, set new prompt symbol
+2:
+ cmp (r5),$1 / tty input?
+ ble newline / yes, call with '-(or with no command
+ / file name)
+ clr r0 / no, set ttv
+ sys close / close it
+ mov 4(r5),0f / get new file name
+ sys open; 0:..; 0 / open it
+ bec 1f / branch if no error
+ jsr r5,error / error in file name
+ <Input not found\n\0>; .even
+ sys exit
+1:
+ clr at / clear prompt character, if reading non-tty
+ / input file
+newline:
+ tst at / is there a prompt symbol
+ beq newcom / no
+ mov $1,r0 / yes
+ sys write; at; 2. / print prompt
+newcom:
+ mov shellarg,sp /
+ mov $parbuf,r3 / initialize command list area
+ mov $parp,r4 / initialize command list pointers
+ clr infile / initialize alternate input
+ clr outfile / initialize alternate output
+ clr glflag / initialize global flag
+newarg:
+ jsr pc,blank / squeeze out leading blanks
+ jsr r5,delim / is new character a ; \n or &
+ br 2f / yes
+ mov r3,-(sp) / no, push arg pointer onto stack
+ cmp r0,$'< / new input file?
+ bne 1f / no
+ mov (sp),infile / yes, save arg pointer
+ clr (sp) / clear pointer
+ br 3f
+1:
+ cmp r0,$'> / new output file?
+ bne newchar / no
+ mov (sp),outfile / yes, save arg pointer
+ clr (sp) / clear pointer
+ br 3f
+newchar:
+ cmp $' ,r0 / is character a blank
+ beq 1f / branch if it is (blank as arg separator)
+ cmp $'\n+200,r0 / treat \n preceded by \
+ beq 1f / as blank
+ jsr pc,putc / put this character in parbuf list
+3:
+ jsr pc,getc / get next character
+ jsr r5,delim / is char a ; \n or &,
+ br 1f / yes
+ br newchar / no, start new character tests
+1:
+ clrb (r3)+ / end name with \0 when read blank, or
+ / delim
+ mov (sp)+,(r4)+ / move arg ptr to parp location
+ bne 1f / if (sp)=0, in file or out file points to arg
+ tst -(r4) / so ignore dummy (0), in pointer list
+1:
+ jsr r5,delim / is char a ; \n or &.
+ br 2f / yes
+ br newarg / no, start newarg processing
+2:
+ clr (r4) / \n, &, or ; takes to here (end of arg list)
+ / after 'delim' call
+ mov r0,-(sp) / save delimter in stack
+ jsr pc,docom / go to exec command in parbuf
+ cmpb (sp),$'& / get a new command without wait?
+ beq newcom / yes
+ tst r1 / was chdir just executed or line ended with
+ / ampersand?
+ beq 2f / yes
+1:
+ sys wait / no, wait for new process to terminate
+ / command executed)
+ bcs 2f / no, children not previously waited for
+ cmp r0,r1 / is this my child
+ bne 1b
+2:
+ cmp (sp),$'\n / was delimiter a new line
+ beq newline / yes
+ br newcom / no, pick up next command
+docom:
+ sub $parp,r4 / out arg count in r4
+ bne 1f / any arguments?
+ clr r1 / no, line ended with ampersand
+ rts pc / return from call
+1:
+ jsr r5,chcom; qchdir / is command chdir?
+ br 2f / command not chdir
+ cmp r4,$4 / prepare to exec chdir, 4=arg count x 2
+ beq 3f
+ jsr r5,error / go to print error
+ <Arg count\n\0>; .even
+ br 4f
+3:
+ mov parp+2,0f / more directory name to sys coll
+ sys chdir; 0:0 / exec chdir
+ bec 4f / no error exit
+ jsr r5,error / go to print error
+ <Bad directory\n\0>; .even / this diagnostic
+4:
+ clr r1 / set r1 to zero to dkip wait
+ rts pc / and return
+2:
+ jsr r5,chcom; glogin / is command login?
+ br 2f / not loqin, go to fork
+ sys exec; parbuf; parp / exec login
+ sys exec; binpb; parp / or /bin/login
+2: / no error return??
+ sys fork / generate sh child process for command
+ br newproc / exec command with new process
+ bec 1f / no error exit, old orocess
+ jsr r5,error / go to print error
+ <Try again\n\0>; .even / this diaonostic
+ jmp newline / and return for next try
+1:
+ mov r0,r1 / save id of child sh
+ rts pc / return to "jsr pc, docom" call in parent sh
+
+error:
+ movb (r5)+,och / pick up diagnostic character
+ beq 1f / 0 is end of line
+ mov $1,r0 / set for tty output
+ sys write; och; 1 / print it
+ br error / continue to get characters
+1:
+ inc r5 / inc r5 to point to return
+ bic $1,r5 / make it even
+ clr r0 / set for input
+ rts r5
+
+ sys seek; 0; 2 / exit from runcom. skip to end of
+ / input file
+chcom: / has no effect if tty input
+ mov (r5)+,r1 / glogin gchdir r1, bump r5
+ mov $parbuf,r2 / command address r2 'login'
+1:
+ movb (r1)+,r0 / is this command 'chdir'
+ cmpb (r2)+,r0 / compare command name byte with 'login'
+ / or 'chdir'
+ bne 1f / doesn't compare
+ tst r0 / is this
+ bne 1b / end of names
+ tst (r5)+ / yes, bump r5 again to execute login
+ / chdir
+1:
+ rts r5 / no, return to exec command
+
+putc:
+ cmp r0,$'' / single quote?
+ beq 1f / yes
+ cmp r0,$'" / double quote
+ beq 1f / yes
+ bic $!177,r0 / no, remove 200, if present
+ movb r0,(r3)+ / store character in parbuf
+ rts pc
+1:
+ mov r0,-(sp) / push quote mark onto stack
+1:
+ jsr pc,getc / get a quoted character
+ cmp r0,$'\n / is it end or line
+ bne 2f / no
+ jsr r5,error / yes, indicate missing quote mark
+ <"' imbalance\n\0>; .even
+ jmp newline / ask for new line
+2:
+ cmp r0,(sp) / is this closing quote mark
+ beq 1f / yes
+ bic $!177,r0 / no, strip off 200 if present
+ movb r0,(r3)+ / store quoted character in parbuf
+ br 1b / continue
+1:
+ tst (sp)+ / pop quote mark off stack
+ rts pc / return
+
+/ thp`e new process
+
+newproc:
+ mov infile,0f / move pointer to new file name
+ beq 1f / branch if no alternate read file given
+ tstb *0f
+ beq 3f / branch if no file name miven
+ clr r0 / set tty input file name
+ sys close / close it
+ sys open; 0:..; 0 / open new input file for reading
+ bcc 1f / branch if input file ok
+3:
+ jsr r5,error / file not ok, print error
+ <Input file\n\0>; .even / this diagnostic
+ sys exit / terminate this process and make parent sh
+1:
+ mov outfile,r2 / more pointer to new file name
+ beq 1f / branch if no alternate write file
+ cmpb (r2),$'> / is > at beqinninrg of file name?
+ bne 4f / branch if it isn't
+ inc r2 / yes, increment pointer
+ mov r2,0f
+ sys open; 0:..; 1 / open file for writing
+ bec 3f / if no error
+4:
+ mov r2,0f
+ sys creat; 0:..; 17 / create new file with this name
+ bec 3f / branch if no error
+2:
+ jsr r5,error
+ <Output file\n\0>; .even
+ sys exit
+3:
+ sys close / close the new write file
+ mov r2,0f / move new name to open
+ mov $1,r0 / set ttv file name
+ sys close / close it
+ sys open; 0:..; 1 / open new output file, it now has
+ / file descriptor 1
+ sys seek; 0; 2 / set pointer to current end of file
+1:
+ tst glflag / was *, ? or [ encountered?
+ bne 1f / yes
+ sys exec; parbuf; parp / no, execute this commend
+ sys exec; binpb; parp / or /bin/this command
+2:
+ sys stat; binpb; inbuf / if can't execute does it
+ / exist?
+ bes 2f / branch if it doesn't
+ mov $shell,parp-2 / does exist, not executable
+ mov $binpb,parp / so it must be
+ sys exec; shell; parp-2 / a command file, get it with
+ / sh /bin/x (if x name of file)
+2:
+ jsr r5,error / a return for exec is the diagnostic
+ <No command\n\0>; .even
+ sys exit
+1:
+ mov $glob,parp-2 / prepare to process *,?
+ sys exec; glob; parp-2 / execute modified command
+ br 2b
+
+delim:
+ cmp r0,$'\n / is character a newline
+ beq 1f
+ cmp r0,$'& / is it &
+ beq 1f / yes
+ cmp r0,$'; / is it ;
+ beq 1f / yes
+ cmp r0,$'? / is it ?
+ beq 3f
+ cmp r0,$'* / is it *
+ beq 3f
+ cmp r0,$'[ / is it beginning of character string
+ / (for glob)
+ bne 2f
+3:
+ inc glflag / ? or * or [ set flag
+2:
+ tst (r5)+ / bump to process all except \n,;,&
+1:
+ rts r5
+
+blank:
+ jsr pc,getc / get next character
+ cmp $' ,r0 / leading blanks
+ beq blank / yes, 'squeeze out'
+ cmp r0,$200+'\n / new-line preceded by \ is translated
+ beq blank / into blank
+ rts pc
+getc:
+ tst param / are we substituting for $n
+ bne 2f/ yes
+ mov inbufp,r1 / no, move normal input pointer to r1
+ cmp r1,einbuf / end of input line?
+ bne 1f / no
+ jsr pc,getbuf / yes, put next console line in buffer
+ br getc
+1:
+ movb (r1)+,r0 / move byte from input buffer to r0
+ mov r1,inbufp / increment routine
+ bis escap,r0 / if last character was \ this adds
+ / 200 to current character
+ clr escap / clear, so escap normally zero
+ cmp r0,$'\\ / note that \\ is equal \ in as
+ beq 1f
+ cmp r0,$'$ / is it $
+ beq 3f / yes
+ rts pc / no
+1:
+ mov $200,escap / mark presence of \ in command line
+ br getc / get next character
+2:
+ movb *param,r0 / pick up substitution character put in
+ / r0
+ beq 1f / if end of substitution arg, branch
+ inc param / if not end, set for next character
+ rts pc / return as though character in ro is normal
+ / input
+1:
+ clr param / unset substitution pointer
+ br getc / get next char in normal input
+3:
+ jsr pc,getc / get digit after $
+ sub $'0,r0 / strip off zone bits
+ cmp r0,$9. / compare with digit 9
+ blos 1f / less than or equal 9
+ mov $9.,r0 / if larger than 9, force 9
+1:
+ mov shellarg,r1 / get pointer to stack for
+ / this call of shell
+ inc r0 / digit +1
+ cmp r0,(r1) / is it less than # of args in this call
+ bge getc / no, ignore it. so this $n is not replaced
+ asl r0 / yes, multiply by 2 (to skip words)
+ add r1,r0 / form pointer to arg pointer (-2)
+ mov 2(r0),param / move arg pointer to param
+ br getc / go to get substitution arg for $n
+getbuf:
+ mov $inbuf,r0 / move input buffer address
+ mov r0,inbufp / to input buffer pointer
+ mov r0,einbuf / and initialize pointer to end of
+ / character string
+ dec r0 / decrement pointer so can utilize normal
+ / 100p starting at 1f
+ mov r0,0f / initialize address for reading 1st char
+1:
+ inc 0f / this routine filles inbuf with line from
+ / console - if there is cnc
+ clr r0 / set for tty input
+ sys read; 0:0; 1 / read next char into inbuf
+ bcs xit1 / error exit
+ tst r0 / a zero input is end of file
+ beq xit1 / exit
+ inc einbuf / eventually einbuf points to \n
+ / (+1) of this line
+ cmp 0b,$inbuf+256. / have we exceeded input buffer size
+ bhis xit1 / if so, exit assume some sort of binary
+ cmpb *0b,$'\n / end of line?
+ bne 1b / no, go to get next char
+ rts pc / yes, return
+
+xit1:
+ sys exit
+
+quest:
+ <?\n>
+
+at:
+ <@ >
+
+qchdir:
+ <chdir\0>
+glogin:
+ <login\0>
+shell:
+ </bin/sh\0>
+glob:
+ </etc/glob\0>
+binpb:
+ </bin/>
+parbuf: .=.+1000.
+ .even
+param: .=.+2
+glflag: .=.+2
+infile: .=.+2
+outfile:.=.+2
+ .=.+2 / room for glob
+parp: .=.+200.
+inbuf: .=.+256.
+escap: .=.+2
+inbufp: .=.+2
+einbuf: .=.+2
+och: .=.+2
+shellarg:.=.+2
+
--- /dev/null
+/ u0 -- unix
+
+cold = 0
+orig = 0 . / orig = 0. relocatable
+
+rkda = 177412 / disk address reg rk03/rk11
+rkds = 177400 / driv status reg rk03/rk11
+rkcs = 177404 / control status reg rk03/rk11
+rcsr = 174000 / receiver status reg dc-11
+rcbr = 174002 / receiver buffer reg dc-11
+tcsr = 174004 / xmtr status reg dc-11
+tcbr = 174006 / xmtr buffer reg dc-11
+tcst = 177340 / dec tape control status tc11/tu56
+tccm = 177342 / dec tape command reg tc11/tu56
+tcwc = 177344 / word count tc11/tu56
+tcba = 177346 / bus addr tc11/tu56
+tcdt = 177350 / data reg tc11/tu56
+dcs = 177460 / drum control status rf11/rs11
+dae = 177470 / drum address extension rf11/rs11
+lks = 177546 / clock status reg kw11-l
+prs = 177550 / papertape reader status pc11
+prb = 177552 / buffer pc11
+pps = 177554 / punch status pc11
+ppb = 177556 / punch buffer pc11
+/lps = 177514 line printer status (future)
+/lpb = 177516 line printer buffer (future)
+tks = 177560 / console read status asr-33
+tkb = 177562 / read buffer asr-33
+tps = 177564 / punch status asr-33
+tpb = 177566 / punch buffer asr-33
+ps = 177776 / processor status
+
+fpsym = 0 / define fpsym even though we cannot use it
+.. = 0 . / ensure a.out starts at location 0, not 040000
+
+halt = 0
+wait = 1
+rti = 2
+
+nproc = 16. / number of processes
+nfiles = 50.
+ntty = 8+1
+nbuf = 6
+ .if cold / ignored if cold = 0
+nbuf = 2
+.endif
+
+core = orig+40000 / specifies beginning of user's core
+ecore = core+40000 / specifies end of user's core (4096 words)
+
+/ 4;4 init by copy
+/ unkni;0 " error
+/ fpsym;0 " illg in tr
+ unkni;0 / trace and trap (see Sec. B.1 page )
+ unkni;0 / trap
+ panic;0 / pwr
+ rtssym;0 / emt
+ sysent;0 / sys
+ . = orig+60
+ ttyi;240 / interrupt vector tty in ; processor level 5
+ ttyo;240 / interrupt vector tty out
+ ppti;240 / punch papertape in
+ ppto;240 / punch papertape out
+ clock;340 / clock interrupt vector ; processor level 7
+ . = orig+200
+/ lpto; 240 line printer interrupt ; processor level 5 (future)
+ . = orig+204
+ drum;300 / drum interrupt ; processor level 6
+ . = orig+214
+ tape;300 / dec tape interrupt
+ disk;300 / rk03 interrupt
+ . = orig+300
+ 0*4+trcv; 240; 0*4+txmt; 240 / dc11 input,output interrupt vectors
+ 1*4+trcv; 240; 1*4+txmt; 240
+ 2*4+trcv; 240; 2*4+txmt; 240
+ 3*4+trcv; 240; 3*4+txmt; 240
+ 4*4+trcv; 240; 4*4+txmt; 240
+ 5*4+trcv; 240; 5*4+txmt; 240
+ 6*4+trcv; 240; 6*4+txmt; 240
+ 7*4+trcv; 240; 7*4+txmt; 240
+
+ . = orig+400
+/ copy in transfer vectors
+
+ mov $ecore,sp / put pointer to ecore in the stack pointer
+ jsr r0,copyz; 0; 14 / clear locations 0 to 14 in core
+ mov $4,r0
+ clr r1
+ mov r0,(r1)+ / put value of 4 into location 0
+ mov r0,(r1)+ / put value of 4 into location 2
+ mov $unkni,(r1)+ / put value of unkni into location 4;
+ / time out, bus error
+ clr (r1)+ / put value of 0 into location 6
+ mov $fpsym,(r1)+ / put value of fpsym into location 10
+ clr (r1)+ / put value of 0 into location 12
+/ clear core
+ .if cold / ignored if cold = 0
+ halt / halt before initializing rf file system; user has
+ / last chance to reconsider
+ .endif
+
+ jsr r0,copyz; systm; ecore / clear locations systm to ecore
+ mov $s.chrgt+2,clockp / intialize clockp
+/ allocate tty buffers; see H.0 for description
+ mov $buffer,r0
+ mov $tty+6,r1
+1:
+ mov r0,(r1)
+ add $140.,r0 / tty buffers are 140. bytes long
+ add $8,r1
+ cmp r1,$tty+[ntty*8] / has a buffer been assigned for each tty
+ blo 1b
+
+/ allocate disk buffers; see H.0 for description
+
+ mov $bufp,r1
+1:
+ mov r0,(r1)+
+ add $8,r0
+ mov r0,-2(r0) / bus address
+ mov $-256.,-4(r0) / word count
+ add $512.,r0 / buffer space
+ cmp r1,$bufp+nbuf+nbuf
+ blo 1b
+ mov $sb0,(r1)+ / I/O queue entry drum
+ mov $sb1,(r1)+ / I/O queue entry disk (mounted device)
+ mov $swp,(r1)+ / I/O queue entry core image being swapped
+ mov $[systm-inode]\/2,sb0+4 / sets up initial buffers per
+ / format given in
+ mov $systm,sb0+6 / memory map
+ mov $-512.,sb1+4
+ mov $_mount,sb1+6
+ mov $user,swp+6
+
+/ set devices to interrupt
+
+ mov $100,*$lks / put 100 into clock status register;
+ / enables clock interrupt
+
+/ set up time out subroutines
+
+ mov $touts,r0
+ mov $startty,(r0)+ / if toutt = 0 call startty
+ mov $pptito,(r0)+ / if toutt+1 = 0 call pptito
+ tst (r0)+ / add 2 to r0
+ mov $ntty-1,r1
+1 :
+ mov $xmtto,(r0)+ / if toutt+2 thru toutt+2+ntty=0 call xmtto
+ dec r1
+ bne 1b
+
+/ free all character blocks; see H.0 for description
+
+ mov $510.,r2
+ mov $-1,r1
+1:
+ jsr r0,put
+ sub $2,r2
+ bgt 1b
+
+/ set up drum swap addresses; see H.0 for description
+
+ mov $1024.-64.,r1 / highest drum address; high 64 blks allocated
+ / to UNIX
+ mov $p.dska,r2 / p.dska contains disk addresses for processes
+1 :
+ sub $33.,r1 / 33 blocks per process, allows 16K per process
+ mov r1,(r2)+
+ cmp r2,$p.dska+nproc+nproc
+ bne 1b
+
+/ free rest of drum
+
+ .if cold
+ mov $128.,systm / initialize word 1 of drum superblock image;
+ / number of bytes in free storage map=128.
+ mov $64.,systm+2+128. / init. wd 66. of superblock image; # of
+ / bytes in i-node map=64.
+1:
+ dec r1 / r1=687.,...,34.
+ jsr r0,free / free block 'r1', i.e., set bit 'r1' in free
+ / storage map in core
+ cmp r1,$34. / first drum address not in i list
+ bgt 1b / if block 34 has been freed, zero i list
+
+/ zero i list
+
+1:
+ dec r1 / r1=33.,...,1
+ jsr r0,clear / zero block 'r1' on fixed head disk
+ tst r1
+ bgt 1b / if blocks 33,...,1 have all been zeroed, done.
+ .endif
+
+/ make current program a user
+
+ mov $41.,r0 / rootdir set to 41 and never changed
+ mov r0,rootdir / rootdir is i-number of root directory
+ mov r0,u.cdir / u.cdir is i-number of process current directory
+ mov $1,r0
+ movb r0,u.uno / set process table index for this process to 1
+ mov r0,mpid / initialize mpid to 1
+ mov r0,p.pid / p.pid identifies process
+ movb r0,p.stat / process status = 1 i.e., active
+ / = 0 free
+ .if cold / = 2 waiting for a child to die
+ / = 3 terminated but not yet waited
+ / for
+
+/ initialize inodes for special files (inodes 1 to 40.)
+
+ mov $40.,r1 / set r1=i-node-number 40.
+1:
+ jsr r0,iget / read i-node 'r1' from disk into inode area of
+ / core and write modified inode out (if any)
+ mov $100017,i.flgs / set flags in core image of inode to indi-
+ / cate allocated, read (owner, non-owner),
+ / write (owner, non-owner)
+ movb $1,i.nlks / set no. of links = 1
+ movb $1,i.uid / set user id of owner = 1
+ jsr r0,setimod / set imod=1 to indicate i-node modified, also
+ / stuff time of modification into i-node
+ dec r1 / next i-node no. = present i-node no.-1
+ bgt 1b / has i-node 1 been initialized; no, branch
+
+/ initialize i-nodes r1.,...,47. and write the root device, binary, etc.,
+/ directories onto fixed head disk. user temporary, initialization prog.
+
+ mov $idata,r0 / r0=base addr. of assembled directories.
+ mov $u.off,u.fofp / pointer to u.off in u.fofp (holds file
+ / offset)
+1:
+ mov (r0)+,r1/r1=41.,...,47; "0" in the assembled directory
+ / header signals last
+ beq 1f / assembled directory has been written onto drum
+ jsr r0,imap / locate the inode map bit for i-node 'r1'
+ bisb mq,(r2) / set the bit to indicate the i-node is not
+ / available
+ jsr r0,iget / read inode 'r1' from disk into inode area of
+ / core and write modified i-node on drum (if any)
+ mov (r0)+,i.flgs / set flags in core image of inode from
+ / assembled directories header
+ movb (r0)+,i.nlks / set no. of links from header
+ movb (r0)+,i.uid / set user id of owner from header
+ jsr r0,setimod / set imod=1 to indicate inode modified; also,
+ / stuff time of modification into i-node
+ mov (r0)+,u.count / set byte count for write call equal to
+ / size of directory
+ mov r0,u.base / set buffer address for write to top of directory
+ clr u.off / clear file offset used in 'seek' and 'tell'
+ add u.count,r0 / r0 points to the header of the next directory
+ jsr r0,writei / write the directory and i-node onto drum
+ br 1b / do next directory
+ .endif
+
+/ next 2 instructions not executed during cold boot.
+ bis $2000,sb0 / sb0 I/O queue entry for superblock on drum;
+ / set bit 10 to 1
+ jsr r0,ppoke / read drum superblock
+1:
+ tstb sb0+1 / has I/O request been honored (for drum)?
+ bne 1b / no, continue to idle.
+1:
+ decb sysflg / mormally sysflag=0, indicates executing in system
+ sys exec; 2f; 1f / generates trap interrupt; trap vector =
+ / sysent; 0
+ br panic / execute file/etc/init
+
+1:
+ 2f;0
+2:
+ </etc/init\0> / UNIX looks for strings term, noted by nul\0
+
+panic:
+ clr ps
+1:
+ dec $0
+ bne 1b
+ dec $5
+ bne 1b
+ jmp *$173700 / rom loader address
+rtssym:
+ mov r0,-(sp)
+ mov r1,-(sp)
+ mov 4(sp),r0
+ mov -(r0),r0
+ bic $!7,r0
+ asl r0
+ jmp *1f(r0)
+1:
+ 0f;1f;2f;3f;4f;5f;badrts;7f
+0:
+ mov 2(sp),r0
+ br 1f
+2:
+ mov r2,r1
+ br 1f
+3:
+ mov r3,r1
+ br 1f
+4:
+ mov r4,r1
+ br 1f
+5:
+ mov r5,r1
+ br 1f
+7:
+ mov 8.(sp),r1
+1:
+ cmp r1,$core
+ blo badrts
+ cmp r1,$ecore
+ bhis badrts
+ bit $1,r1
+ bne badrts
+ tst (r1)
+ beq badrts
+ add $1f,r0
+ mov r0,4(sp)
+ mov (sp)+,r1
+ mov (sp)+,r0
+ rti
+1:
+ rts r0
+ rts r1
+ rts r2
+ rts r3
+ rts r4
+ rts r5
+ rts sp
+ rts pc
+
+badrts:
+ mov (sp)+,r1
+ mov (sp)+,r0
+rpsym:
+ jmp unkni
+
+ .if cold
+
+idata:
+
+/ root
+
+ 41.
+ 140016
+ .byte 7,1
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 41.
+ <.\0\0\0\0\0\0\0>
+ 42.
+ <dev\0\0\0\0\0>
+ 43.
+ <bin\0\0\0\0\0>
+ 44.
+ <etc\0\0\0\0\0>
+ 45.
+ <usr\0\0\0\0\0>
+ 46.
+ <tmp\0\0\0\0\0>
+9:
+
+/ device directory
+
+ 42.
+ 140016
+ .byte 2,1
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 42.
+ <.\0\0\0\0\0\0\0>
+ 01.
+ <tty\0\0\0\0\0>
+ 02.
+ <ppt\0\0\0\0\0>
+ 03.
+ <mem\0\0\0\0\0>
+ 04.
+ <rf0\0\0\0\0\0>
+ 05.
+ <rk0\0\0\0\0\0>
+ 06.
+ <tap0\0\0\0\0>
+ 07.
+ <tap1\0\0\0\0>
+ 08.
+ <tap2\0\0\0\0>
+ 09.
+ <tap3\0\0\0\0>
+ 10.
+ <tap4\0\0\0\0>
+ 11.
+ <tap5\0\0\0\0>
+ 12.
+ <tap6\0\0\0\0>
+ 13.
+ <tap7\0\0\0\0>
+ 14.
+ <tty0\0\0\0\0>
+ 15.
+ <tty1\0\0\0\0>
+ 16.
+ <tty2\0\0\0\0>
+ 17.
+ <tty3\0\0\0\0>
+ 18.
+ <tty4\0\0\0\0>
+ 19.
+ <tty5\0\0\0\0>
+ 20.
+ <tty6\0\0\0\0>
+ 21.
+ <tty7\0\0\0\0>
+ 22.
+ <lpr\0\0\0\0\0>
+ 01.
+ <tty8\0\0\0\0> / really tty
+9:
+
+/ binary directory
+
+ 43.
+ 140016
+ .byte 2,3
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 43.
+ <.\0\0\0\0\0\0\0>
+9:
+
+/ etcetra directory
+
+ 44.
+ 140016
+ .byte 2,3
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 44.
+ <.\0\0\0\0\0\0\0>
+ 47.
+ <init\0\0\0\0>
+9:
+
+/ user directory
+
+ 45.
+ 140016
+ .byte 2,1
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 45.
+ <.\0\0\0\0\0\0\0>
+9:
+
+/ temporary directory
+
+ 46.
+ 140017
+ .byte 2,1
+ 9f-.-2
+ 41.
+ <..\0\0\0\0\0\0>
+ 46.
+ <.\0\0\0\0\0\0\0>
+9:
+
+/ initialization program
+
+ 47.
+ 100036
+ .byte 1,3
+ 9f-.-2
+8:
+ sys break; 0
+ sys open; 6f-8b+core; 0
+ mov r0,r1
+ sys seek; 65.; 0
+1:
+ mov r1,r0
+ sys read; 9f-8b+core; 512.
+ mov 9f,r5 / size
+ beq 1f
+ sys creat; 9f-8b+core+4; 0
+ mov r0,r2
+ movb 9f+2,0f
+ sys chmod; 9f-8b+core+4; 0:..
+ movb 9f+3,0f
+ sys chown; 9f-8b+core+4; 0:..
+2:
+ tst r5
+ beq 2f
+ mov r1,r0
+ sys read; 9f-8b+core; 512.
+ mov $512.,0f
+ cmp r5,$512.
+ bhi 3f
+ mov r5,0f
+3:
+ mov r2,r0
+ sys write; 9f-8b+core; 0:..
+ sub r0,r5
+ br 2b
+2:
+ mov r2,r0
+ sys close
+ br 1b
+1:
+ mov r1,r0
+ sys close
+ sys exec; 5f-8b+core; 4f-8b+core
+ sys exit
+4:
+ 5f-8b+core; 0
+5:
+ </etc/init\0>
+6:
+ </dev/tap0\0>
+ .even
+9:
+
+/ end of initialization data
+
+ 0
+
+ .endif
+
--- /dev/null
+/ u1 -- unix
+
+unkni: / used for all system calls
+sysent:
+ incb sysflg / indicate a system routine is
+ beq 1f / in progress
+ jmp panic / called if trap inside system
+1:
+ mov $s.syst+2,clockp
+ mov r0,-(sp) / save user registers
+ mov sp,u.r0 / pointer to bottom of users stack in u.r0
+ mov r1,-(sp)
+ mov r2,-(sp)
+ mov r3,-(sp)
+ mov r4,-(sp)
+ mov r5,-(sp)
+ mov ac,-(sp) / "accumulator" register for extended
+ / arithmetic unit
+ mov mq,-(sp) / "multiplier quotient" register for the
+ / extended arithmetic unit
+ mov sc,-(sp) / "step count" register for the extended
+ / arithmetic unit
+ mov sp,u.sp / u.sp points to top of users stack
+ mov 18.(sp),r0 / store pc in r0
+ mov -(r0),r0 / sys inst in r0 10400xxx
+ sub $sys,r0 / get xxx code
+ asl r0 / multiply by 2 to jump indirect in bytes
+ cmp r0,$2f-1f / limit of table (35) exceeded
+ bhis badsys / yes, bad system call
+ bic $341,20.(sp) / set users processor priority to 0 and clear
+ / carry bit
+ jmp *1f(r0) / jump indirect thru table of addresses
+ / to proper system routine.
+1:
+ sysrele / 0
+ sysexit / 1
+ sysfork / 2
+ sysread / 3
+ syswrite / 4
+ sysopen / 5
+ sysclose / 6
+ syswait / 7
+ syscreat / 8
+ syslink / 9
+ sysunlink / 10
+ sysexec / 11
+ syschdir / 12
+ systime / 13
+ sysmkdir / 14
+ syschmod / 15
+ syschown / 16
+ sysbreak / 17
+ sysstat / 18
+ sysseek / 19
+ systell / 20
+ sysmount / 21
+ sysumount / 22
+ syssetuid / 23
+ sysgetuid / 24
+ sysstime / 25
+ sysquit / 26
+ sysintr / 27
+ sysfstat / 28
+ sysemt / 29
+ sysmdate / 30
+ sysstty / 31
+ sysgtty / 32
+ sysilgins / 33
+2:
+
+error:
+ mov u.sp,r1
+ bis $1,20.(r1) / set c bit in processor status word below
+ / users stack
+
+sysret:
+ tstb u.bsys / is a process about to be terminated because
+ bne sysexit / of an error? yes, go to sysexit
+ mov u.sp,sp / no point stack to users stack
+ clr r1 / zero r1 to check last mentioned i-node
+ jsr r0,iget / if last mentioned i-node has been modified
+ / it is written out
+ tstb smod / has the super block been modified
+ beq 1f / no, 1f
+ clrb smod / yes, clear smod
+ bis $1000,sb0 / set write bit in I/O queue for super block
+ / output
+ jsr r0,ppoke / write out modified super block to disk
+1:
+ tstb mmod / has the super block for the dismountable file
+ / system
+ beq 1f / been modified? no, 1f
+ clrb mmod / yes, clear mmod
+ movb mntd,sb1 / set the I/O queue
+ bis $1000,sb1 / set write bit in I/O queue for detached sb
+ jsr r0,ppoke / write it out to its device
+1:
+ tstb uquant / is the time quantum 0?
+ bne 1f / no, don't swap it out
+
+sysrele:
+ jsr r0,tswap / yes, swap it out
+1:
+ mov (sp)+,sc / restore user registers
+ mov (sp)+,mq
+ mov (sp)+,ac
+ mov (sp)+,r5
+ mov (sp)+,r4
+ mov (sp)+,r3
+ mov (sp)+,r2
+ mov (sp)+,r1
+ mov (sp)+,r0
+ mov $s.chrgt+2,clockp
+ decb sysflg / turn system flag off
+ jsr r0,isintr / is there an interrupt from the user
+ br intract / yes, output gets flushed, take interrupt
+ / action
+ rti / no return from interrupt
+
+badsys:
+ incb u.bsys / turn on the user's bad-system flag
+ mov $3f,u.namep / point u.namep to "core\0\0"
+ jsr r0,namei / get the i-number for the core image file
+ br 1f / error
+ neg r1 / negate the i-number to open the core image file
+ / for writing
+ jsr r0,iopen / open the core image file
+ jsr r0,itrunc / free all associated blocks
+ br 2f
+1:
+ mov $17,r1 / put i-node mode (17) in r1
+ jsr r0,maknod / make an i-node
+ mov u.dirbuf,r1 / put i-nodes number in r1
+2:
+ mov $core,u.base / move address core to u.base
+ mov $ecore-core,u.count / put the byte count in u.count
+ mov $u.off,u.fofp / more user offset to u.fofp
+ clr u.off / clear user offset
+ jsr r0,writei / write out the core image to the user
+ mov $user,u.base / pt. u.base to user
+ mov $64.,u.count / u.count = 64
+ jsr r0,writei / write out all the user parameters
+ neg r1 / make i-number positive
+ jsr r0,iclose / close the core image file
+ br sysexit /
+3:
+ <core\0\0>
+
+sysexit: / terminate process
+ clr u.intr / clear interrupt control word
+ clr r1 / clear r1
+1: / r1 has file descriptor (index to u.fp list) Search the whole list
+ jsr r0,fclose / close all files the process opened
+ br .+2 / ignore error return
+ inc r1 / increment file descriptor
+ cmp r1,$10. / end of u.fp list?
+ blt 1b / no, go back
+ movb u.uno,r1 / yes, move dying process's number to r1
+ clrb p.stat-1(r1) / free the process
+ asl r1 / use r1 for index into the below tables
+ mov p.pid-2(r1),r3 / move dying process's name to r3
+ mov p.ppid-2(r1),r4 / move its parents name to r4
+ clr r2
+ clr r5 / initialize reg
+1: / find children of this dying process, if they are zombies, free them
+ add $2,r2 / search parent process table for dying process's name
+ cmp p.ppid-2(r2),r3 / found it?
+ bne 3f / no
+ asr r2 / yes, it is a parent
+ cmpb p.stat-1(r2),$3 / is the child of this dying process a
+ / zombie
+ bne 2f / no
+ clrb p.stat-1(r2) / yes, free the child process
+2:
+ asl r2
+3: / search the process name table for the dying process's parent
+ cmp p.pid-2(r2),r4 / found it?
+ bne 3f / no
+ mov r2,r5 / yes, put index to p.pid table (parents
+ / process # x2) in r5
+3:
+ cmp r2,$nproc+nproc / has whole table been searched?
+ blt 1b / no, go back
+ mov r5,r1 / yes, r1 now has parents process # x2
+ beq 2f / no parent has been found. The process just dies
+ asr r1 / set up index to p.stat
+ movb p.stat-1(r1),r2 / move status of parent to r2
+ beq 2f / if its been freed, 2f
+ cmp r2,$3 / is parent a zombie?
+ beq 2f / yes, 2f
+ movb u.uno,r3 / move dying process's number to r3
+ movb $3,p.stat-1(r3) / make the process a zombie
+ cmp r2,$2 / is the parent waiting for this child to die
+ bne 2f / yes, notify parent not to wait any more
+ decb p.stat-1(r1) / awaken it by putting it (parent)
+ mov $runq+4,r2 / on the runq
+ jsr r0, putlu
+2: / the process dies
+ clrb u.uno / put zero as the process number, so "swap" will
+ jsr r0,swap / overwrite process with another process
+ 0 / and thereby kill it; halt?
+
+intract: / interrupt action
+ cmp *(sp),$rti / are you in a clock interrupt?
+ bne 1f / no, 1f
+ cmp (sp)+,(sp)+ / pop clock pointer
+1: / now in user area
+ mov r1,-(sp) / save r1
+ mov u.ttyp,r1 / pointer to tty buffer in control-to r1
+ cmpb 6(r1),$177 / is the interrupt char equal to "del"
+ beq 1f / yes, 1f
+ clrb 6(r1) / no, clear the byte (must be a quit character)
+ mov (sp)+,r1 / restore r1
+ clr u.quit / clear quit flag
+ bis $20,2(sp) / set trace for quit (sets t bit of ps-trace trap)
+ rti / return from interrupt
+1: / interrupt char = del
+ clrb 6(r1) / clear the interrupt byte in the buffer
+ mov (sp)+,r1 / restore r1
+ cmp u.intr,$core / should control be transferred to loc core?
+ blo 1f
+ jmp *u.intr / user to do rti yes, transfer to loc core
+1:
+ sys 1 / exit
+
+syswait: / wait for a process to die
+ movb u.uno,r1 / put parents process number in r1
+ asl r1 / x2 to get index into p.pid table
+ mov p.pid-2(r1),r1 / get the name of this process
+ clr r2
+ clr r3 / initialize reg 3
+1:
+ add $2,r2 / use r2 for index into p.ppid table / search table
+ / of parent processes for this process name
+ cmp p.ppid-2(r2),r1 / r2 will contain the childs process number
+ bne 3f / branch if no match of parent process name
+ inc r3 / yes, a match, r3 indicates number of children
+ asr r2 / r2/2 to get index to p.stat table
+ cmpb p.stat-1(r2),$3 / is the child process a zombie?
+ bne 2f / no, skip it
+ clrb p.stat-1(r2) / yes, free it
+ asl r2 / r2x2 to get index into p.pid table
+ mov p.pid-2(r2),*u.r0 / put childs process name in (u.r0)
+ br sysret1 / return cause child is dead
+2:
+ asl r2 / r2x2 to get index into p.ppid table
+3:
+ cmp r2,$nproc+nproc / have all processes been checked?
+ blt 1b / no, continue search
+ tst r3 / one gets here if there are no children or children
+ / that are still active
+ beq error1 / there are no children, error
+ movb u.uno,r1 / there are children so put parent process number
+ / in r1
+ incb p.stat-1(r1) / it is waiting for other children to die
+ jsr r0,swap / swap it out, because it's waiting
+ br syswait / wait on next process
+
+error1:
+ jmp error / see 'error' routine
+sysret1:
+ jmp sysret / see 'sysret' routine
+
+sysfork: / create a new process
+ clr r1
+1: / search p.stat table for unused process number
+ inc r1
+ tstb p.stat-1(r1) / is process active, unused, dead
+ beq 1f / it's unused so branch
+ cmp r1,$nproc / all processes checked
+ blt 1b / no, branch back
+ add $2,18.(sp) / add 2 to pc when trap occured, points
+ / to old process return
+ br error1 / no room for a new process
+1:
+ movb u.uno,-(sp) / save parent process number
+ movb r1,u.uno / set child process number to r1
+ incb p.stat-1(r1) / set p.stat entry for child process to
+ / active status
+ mov u.ttyp,r2 / put pointer to parent process' control tty
+ / buffer in r2
+ beq 2f / branch, if no such tty assigned
+ clrb 6(r2) / clear interrupt character in tty buffer
+2:
+ mov $runq+4,r2
+ jsr r0,putlu / put child process on lowest priority run queue
+ asl r1 / multiply r1 by 2 to get index into p.pid table
+ inc mpid / increment m.pid; get a new process name
+ mov mpid,p.pid-2(r1) / put new process name in child process'
+ / name slot
+ movb (sp),r2 / put parent process number in r2
+ asl r2 / multiply by 2 to get index into below tables
+ mov p.pid-2(r2),r2 / get process name of parent process
+ mov r2,p.ppid-2(r1) / put parent process name in parent
+ / process slot for child
+ mov r2,*u.r0 / put parent process name on stack at location
+ / where r0 was saved
+ mov $sysret1,-(sp) /
+ mov sp,u.usp / contents of sp at the time when user is
+ / swapped out
+ mov $sstack,sp / point sp to swapping stack space
+ jsr r0,wswap / put child process out on drum
+ jsr r0,unpack / unpack user stack
+ mov u.usp,sp / restore user stack pointer
+ tst (sp)+ / bump stack pointer
+ movb (sp)+,u.uno / put parent process number in u.uno
+ mov mpid,*u.r0 / put child process name on stack where r0
+ / was saved
+ add $2,18.(sp) / add 2 to pc on stack; gives parent
+ / process return
+ clr r1
+1: / search u.fp list to find the files opened by the parent process
+ movb u.fp(r1),r2 / get an open file for this process
+ beq 2f / file has not been opened by parent, so branch
+ asl r2 / multiply by 8
+ asl r2 / to get index into fsp table
+ asl r2
+ incb fsp-2(r2) / increment number of processes using file,
+ / because child will now be using this file
+2:
+ inc r1 / get next open file
+ cmp r1,$10. / 10. files is the maximum number which can be
+ / opened
+ blt 1b / check next entry
+ br sysret1
+
+sysread:
+ jsr r0,rw1 / get i-number of file to be read into r1
+ tst r1 / negative i-number?
+ ble error1 / yes, error 1 to read it should be positive
+ jsr r0,readi / read data into core
+ br 1f
+
+syswrite:
+ jsr r0,rw1 / get i-number in r1 of file to write
+ tst r1 / positive i-number ?
+ bge error1 / yes, error 1 negative i-number means write
+ neg r1 / make it positive
+ jsr r0,writei / write data
+1:
+ mov u.nread,*u.r0 / put no. of bytes transferred into (u.r0)
+ br sysret1
+
+rw1:
+ jsr r0,arg; u.base / get buffer pointer
+ jsr r0,arg; u.count / get no. of characters
+ mov *u.r0,r1 / put file descriptor (index to u.fp table) in r1
+ jsr r0,getf / get i-number of the file in r1
+ rts r0
+
+sysopen:
+ jsr r0,arg2 / get sys args into u.namep and on stack
+ jsr r0,namei / i-number of file in r1
+ br error2 / file not found
+ tst (sp) / is mode = 0 (2nd arg of call; 0 means, open for read)
+ beq 1f / yes, leave i-number positive
+ neg r1 / open for writing so make i-number negative
+1:
+ jsr r0,iopen / open file whose i-number is in r1
+ tst (sp)+ / pop the stack and test the mode
+ beq op1 / is open for read op1
+
+op0:
+ neg r1 / make i-number positive if open for writing
+op1:
+ clr r2 / clear registers
+ clr r3
+1: / scan the list of entries in fsp table
+ tstb u.fp(r2) / test the entry in the u.fp list
+ beq 1f / if byte in list is 0 branch
+ inc r2 / bump r2 so next byte can be checked
+ cmp r2,$10. / reached end of list?
+ blt 1b / no, go back
+ br error2 / yes, error (no files open)
+1:
+ tst fsp(r3) / scan fsp entries
+ beq 1f / if 0 branch
+ add $8.,r3 / add 8 to r3 to bump it to next entry mfsp table
+ cmp r3,$[nfiles*8.] / done scanning
+ blt 1b / no, back
+ br error2 / yes, error
+1: / r2 has index to u.fp list; r3, has index to fsp table
+ mov r1,fsp(r3) / put i-number of open file into next available
+ mov cdev,fsp+2(r3) / entry in fsp table, put # of device in
+ / next word
+ clr fsp+4(r3)
+ clr fsp+6(r3) / clear the next two words
+ asr r3
+ asr r3 / divide by 8 to get number of the fsp entry-1
+ asr r3
+ inc r3 / add 1 to get fsp entry number
+ movb r3,u.fp(r2) / move entry number into next available slot
+ / in u.fp list
+ mov r2,*u.r0 / move index to u.fp list into r0 loc on stack
+ br sysret2
+
+error2:
+ jmp error / see 'error' routine
+sysret2:
+ jmp sysret / see 'sysret' routine
+
+syscreat: / name; mode
+ jsr r0,arg2 / put file name in u.namep put mode on stack
+ jsr r0,namei / get the i-number
+ br 2f / if file doesn't exist 2f
+ neg r1 / if file already exists make i-number negative
+ / (open for writing)
+ jsr r0,iopen /
+ jsr r0,itrunc / truncate to 0 length
+ br op0
+2: / file doesn't exist
+ mov (sp)+,r1 / put the mode in r1
+ bic $!377,r1 / clear upper byte
+ jsr r0,maknod / make an i-node for this file
+ mov u.dirbuf,r1 / put i-number for this new file in r1
+ br op0 / open the file
+
+sysmkdir: / make a directory
+ jsr r0,arg2 / point u.namep to the file name
+ jsr r0,namei / get the i-number
+ br .+4 / if file not found branch around error
+ br error2 / directory already exists (error)
+ tstb u.uid / is user the super user
+ bne error2 / no, not allowed
+ mov (sp)+,r1 / put the mode in r1
+ bic $!317,r1 / all but su and ex
+ bis $40000,r1 / directory flag
+ jsr r0,maknod / make the i-node for the directory
+ br sysret2 /
+
+sysclose: / close the file
+ mov *u.r0,r1 / move index to u.fp list into r1
+ jsr r0,fclose / close the file
+ br error2 / unknown file descriptor
+ br sysret2
+
+sysemt:
+ jsr r0,arg; 30 / put the argument of the sysemt call in loc 30
+ cmp 30,$core / was the argument a lower address than core
+ blo 1f / yes, rtssym
+ cmp 30,$ecore / no, was it higher than "core" and less than
+ / "ecore"
+ blo 2f / yes, sysret2
+1:
+ mov $rtssym,30
+2:
+ br sysret2
+sysilgins: / calculate proper illegal instruction trap address
+ jsr r0,arg; 10 / take address from sysilgins call , put
+ / it in loc 8.,
+ cmp 10,$core / making it the illegal instruction trap address
+ blo 1f / is the address a user core address? yes, go to 2f
+ cmp 10,$ecore
+ blo 2f
+1:
+ mov $fpsym,10 / no, make 'fpsum' the illegal instruction trap
+ / address for the system
+2:
+ br sysret2 / return to the caller via 'sysret'
+
+sysmdate: / change the modification time of a file
+ jsr r0,arg; u.namep / point u.namep to the file name
+ jsr r0,namei / get its i-number
+ br error2 / no, such file
+ jsr r0,iget / get i-node into core
+ cmpb u.uid,i.uid / is user same as owner
+ beq 1f / yes
+ tstb u.uid / no, is user the super user
+ bne error2 / no, error
+1:
+ jsr r0,setimod / fill in modification data, time etc.
+ mov 4(sp),i.mtim / move present time to
+ mov 2(sp),i.mtim+2 / modification time
+ br sysret2
+
+sysstty: / set mode of typewriter; 3 consequtive word arguments
+ jsr r0,_gtty / r1 will have offset to tty block, r2 has source
+ mov r2,-(sp)
+ mov r1,-(sp) / put r1 and r2 on the stack
+1: / flush the clist wait till typewriter is quiescent
+ mov (sp),r1 / restore r1 to tty block offset
+ movb tty+3(r1),0f / put cc offset into getc argument
+ mov $240,*$ps / set processor priority to 5
+ jsr r0,getc; 0:../ put character from clist in r1
+ br .+4 / list empty, skip branch
+ br 1b / get another character until list is empty
+ mov 0b,r1 / move cc offset to r1
+ inc r1 / bump it for output clist
+ tstb cc(r1) / is it 0
+ beq 1f / yes, no characters to output
+ mov r1,0f / no, put offset in sleep arg
+ jsr r0,sleep; 0:.. / put tty output process to sleep
+ br 1b / try to calm it down again
+1:
+ mov (sp)+,r1
+ mov (sp)+,r2 / restore registers
+ mov (r2)+,r3 / put reader control status in r3
+ beq 1f / if 0, 1f
+ mov r3,rcsr(r1) / move r.c. status to reader control status
+ / register
+1:
+ mov (r2)+,r3 / move pointer control status to r3
+ beq 1f / if 0 1f
+ mov r3,tcsr(r1) / move p.c. status to printer control status reg
+1:
+ mov (r2)+,tty+4(r1) / move to flag byte of tty block
+ jmp sysret2 / return to user
+
+sysgtty: / get status of typewriter; 3 consequtive word arguments
+ jsr r0,_gtty / r1 will have offset to tty block, r2 has
+ / destination
+ mov rcsr(r1),(r2)+ / put reader control status in 1st word
+ / of dest
+ mov tcsr(r1),(r2)+ / put printer control status in 2nd word
+ / of dest
+ mov tty+4(r1),(r2)+ / put mode in 3rd word
+ jmp sysret2 / return to user
+
+_gtty:
+ jsr r0,arg; u.off / put first arg in u.off
+ mov *u.r0,r1 / put file descriptor in r1
+ jsr r0,getf / get the i-number of the file
+ tst r1 / is it open for reading
+ bgt 1f / yes
+ neg r1 / no, i-number is negative, so make it positive
+1:
+ sub $14.,r1 / get i-number of tty0
+ cmp r1,$ntty-1 / is there such a typewriter
+ bhis error9 / no, error
+ asl r1 / 0%2
+ asl r1 / 0%4 / yes
+ asl r1 / 0%8 / multiply by 8 so r1 points to tty block
+ mov u.off,r2 / put argument in r2
+ rts r0 / return
--- /dev/null
+/ u2 -- unix
+
+syslink: / name1, name2
+ jsr r0,arg2 / u.namep has 1st arg u.off has 2nd
+ jsr r0,namei / find the i-number associated with the 1st
+ / path name
+ br error9 / cannot be found
+ jsr r0,iget / get the i-node into core
+ mov (sp)+,u.namep / u.namep points to 2nd name
+ mov r1,-(sp) / put i-number of name1 on the stack (a link
+ / to this file is to be created)
+ mov cdev,-(sp) / put i-nodes device on the stack
+ jsr r0,isdir / is it a directory
+ jsr r0,namei / no, get i-number of name2
+ br .+4 / not found so r1-i-number of current directory
+ / ii = i-number of current directory
+ br error9 / file already exists., error
+ cmp (sp)+,cdev / u.dirp now points to end of current directory
+ bne error9
+ mov (sp),u.dirbuf / i-number of name1 into u.dirbuf
+ jsr r0,mkdir / make directory entry for name2 in current
+ /directory
+ mov (sp)+,r1 / r1 has i-number of name1
+ jsr r0,iget / get i-node into core
+ incb i.nlks / add 1 to its number of links
+ jsr r0,setimod / set the i-node modified flag
+
+sysret9:
+ jmp sysret / see 'sysret' routine
+error9:
+ jmp error / see 'error' routine
+
+isdir: / if the i-node whose i-number is in r1 is a directory there is an
+ / error unless super user made the call
+ tstb u.uid / super user
+ beq 1f / yes, don't care
+ mov ii,-(sp) / put current i-number on stack
+ jsr r0,iget / get i-node into core (i-number in r1)
+ bit $40000,i.flgs / is it a directory
+ bne error9 / yes, error
+ mov (sp)+,r1 / no, put current i-number in r1 (ii)
+ jsr r0,iget / get it back in
+1:
+ rts r0
+
+sysunlink: / name - remove link name
+ jsr r0,arg; u.namep / u.namep points to name
+ jsr r0,namei / find the i-number associated with the path name
+ br error9 / not found
+ mov r1,-(sp) / put its i-number on the stack
+ jsr r0,isdir / is it a directory
+ clr u.dirbuf / no, clear the location that will get written
+ / into the i-number portion of the entry
+ sub $10.,u.off / move u.off back 1 directory entry
+ jsr r0,wdir / free the directory entry
+ mov (sp)+,r1 / get i-number back
+ jsr r0,iget / get i-node
+ jsr r0,setimod / set modified flag
+ decb i.nlks / decrement the number of links
+ bgt sysret9 / if this was not the last link to file return
+ jsr r0,anyi / if it was, see if anyone has it open. Then
+ / free contents of file and destroy it.
+ br sysret9
+
+mkdir:
+ jsr r0,copyz; u.dirbuf+2; u.dirbuf+10. / clear this
+ mov u.namep,r2 / r2 points to name of directory entry
+ mov $u.dirbuf+2,r3 / r3 points to u.dirbuf+2
+1: / put characters in the directory name in u.dirbuf+2 - u.dirbuf+10
+ movb (r2)+,r1 / move character in name to r1
+ beq 1f / if null, done
+ cmp r1,$'/ / is it a "/"?
+ beq error9 / yes, error
+ cmp r3,$u.dirbuf+10. / have we reached the last slot for
+ / a char?
+ beq 1b / yes, go back
+ movb r1,(r3)+ / no, put the char in the u.dirbuf
+ br 1b / get next char
+1:
+ mov u.dirp,u.off / pointer to empty current directory slot to
+ /u.off
+
+wdir:
+ mov $u.dirbuf,u.base / u.base points to created file name
+ mov $10.,u.count / u.count = 10
+ mov ii,r1 / r1 has i-number of current directory
+ jsr r0,access; 1 / get i-node and set its file up for writing
+ jsr r0,writei / write into directory
+ rts r0
+
+sysexec:
+ jsr r0,arg2 / arg0 in u.namep,arg1 on top of stack
+ jsr r0,namei / namei returns i-number of file named in
+ / sysexec call in r1
+ br error9
+ jsr r0,iget / get i-node for file to be executed
+ bit $20,i.flgs / is file executable
+ beq error9
+ jsr r0,iopen / gets i-node for file with i-number given in
+ / r1 (opens file)
+ bit $40,i.flgs / test user id on execution bit
+ beq 1f
+ tstb u.uid / test user id
+ beq 1f / super user
+ movb i.uid,u.uid / put user id of owner of file as process
+ / user id
+1:
+ mov (sp)+,r5 / r5 now contains address of list of pointers to
+ / arguments to be passed
+ mov $1,u.quit / u.quit determines handling of quits;
+ / u.quit = 1 take quit
+ mov $1,u.intr / u.intr determines handling of interrupts;
+ / u.intr = 1 take interrupt
+ mov $rtssym,30 / emt trap vector set to take system routine
+ mov $fpsym,*10 / reserved instruction trap vector set to take
+ / system routine
+ mov $sstack,sp / stack space used during swapping
+ mov r5,-(sp) / save arguments pointer on stack
+ mov $ecore,r5 / r5 has end of core
+ mov $core,r4 / r4 has start of users core
+ mov r4,u.base / u.base has start of users core
+ mov (sp),r2 / move arguments list pointer into r2
+1:
+ tst (r2)+ / argument char = "nul"
+ bne 1b
+ tst -(r2) / decrement r2 by 2; r2 has addr of end of arguent
+ / pointer list
+1: / move arguments to bottom of users core
+ mov -(r2),r3 / (r3) last non zero argument ptr
+ cmp r2,(sp) / is r2 = beginning of argument ptr list
+ blo 1f / branch to 1f when all arguments are moved
+2:
+ tstb (r3)+
+ bne 2b / scan argument for \0 (nul)
+2:
+ movb -(r3),-(r5) / move argument char by char starting at
+ / "ecore"
+ cmp r3,(r2) / moved all characters in this argument
+ bhi 2b / branch 2b if not
+ mov r5,(r4)+ / move r5 into top of users core; r5 has
+ / pointer to nth arg
+ br 1b / string
+1:
+ clrb -(r5)
+ bic $1,r5 / make r5 even, r5 points to last word of argument
+ / strings
+ mov $core,r2
+1: / move argument pointers into core following argument strings
+ cmp r2,r4
+ bhis 1f / branch to 1f when all pointers are moved
+ mov (r2)+,-(r5)
+ br 1b
+1:
+ sub $core,r4 / gives number of arguments *2
+ asr r4 / divide r4 by 2 to calculate the number of args stored
+ mov r4,-(r5) / save number of arguments ahead of the argument
+ / pointers
+ clr -(r5) / popped into ps when rti in sysrele is executed
+ mov $core,-(r5) / popped into pc when rti in sysrele
+ / is executed
+ mov r5,0f / load second copyz argument
+ tst -(r5) / decrement r5
+ mov r5,u.r0 /
+ sub $16.,r5 / skip 8 words
+ mov r5,u.sp / assign user stack pointer value, effectively
+ / zeroes all regs when sysrele is executed
+ jsr r0,copyz; core; 0:0 / zero user's core
+ clr u.break
+ mov r5,sp / point sp to user's stack
+ mov $14,u.count
+ mov $u.off,u.fofp
+ clr u.off / set offset in file to be read to zero
+ jsr r0,readi / read in first six words of user's file, starting
+ / at $core
+ mov sp,r5 / put users stack address in r5
+ sub $core+40.,r5 / subtract $core +40, from r5 (leaves
+ / number of words less 26 available for
+ / program in user core
+ mov r5,u.count /
+
+ / 0407 binary support added may 2008.
+ br 1f
+bsz: 0 / XXX is there a reg that I can use over a call to readi?
+1:
+ cmp core,$407
+ bne e407
+ add $4,u.off / skip last two header words
+ mov $core,r4
+ mov r4,u.base / continue reading at core.
+ mov core+2,r5
+ add core+4,r5 / r5 = text+data size
+ mov core+6,bsz / save bss size, we're going to overwrite core
+ / XXX fix me, I dont quite understand what to do here or
+ / what is done in the similar code below e407:
+ / cmp r5, u.count / see if theres enough room
+ / bgt 1f
+ mov r5,u.count / read text+data into core
+ jsr r0,readi
+ mov u.nread,u.break / break = core + nread + bss
+ add $core,u.break
+ add bsz,u.break
+ jsr r0,iclose
+ br sysret3
+e407:
+ / end 0407 support
+
+ cmp core,$405 / br .+14 is first instruction if file is
+ / standard a.out format
+ bne 1f / branch, if not standard format
+ mov core+2,r5 / put 2nd word of users program in r5; number of
+ / bytes in program text
+ sub $14,r5 / subtract 12
+ cmp r5,u.count /
+ bgt 1f / branch if r5 greater than u.count
+ mov r5,u.count
+ jsr r0,readi / read in rest of user's program text
+ add core+10,u.nread / add size of user data area to u.nread
+ br 2f
+1:
+ jsr r0,readi / read in rest of file
+2:
+ mov u.nread,u.break / set users program break to end of
+ / user code
+ add $core+14,u.break / plus data area
+ jsr r0,iclose / does nothing
+ br sysret3 / return to core image at $core
+
+sysfstat: / set status of open file
+ jsr r0,arg; u.off / put buffer address in u.off
+ mov u.off,-(sp) / put buffer address on the stack
+ mov *u.r0,r1 / put file descriptor in r1
+ jsr r0,getf / get the files i-number
+ tst r1 / is it 0?
+ beq error3 / yes, error
+ bgt 1f / if i-number is negative (open for writing)
+ neg r1 / make it positive, then branch
+ br 1f / to 1f
+
+sysstat: / ; name of file; buffer - get files status
+ jsr r0,arg2 / get the 2 arguments
+ jsr r0,namei / get the i-number for the file
+ br error3 / no such file, error
+1:
+ jsr r0,iget / get the i-node into core
+ mov (sp)+,r3 / move u.off to r3 (points to buffer)
+ mov r1,(r3)+ / put i-number in 1st word of buffer
+ mov $inode,r2 / r2 points to i-node
+1:
+ mov (r2)+,(r3)+ / move rest of i-node to buffer
+ cmp r2,$inode+32 / done?
+ bne 1b / no, go back
+ br sysret3 / return through sysret
+
+error3:
+ jmp error / see 'error' routine
+sysret3:
+ jmp sysret / see 'sysret' routine
+
+getf: / get the device number and the i-number of an open file
+ cmp r1,$10. / user limited to 10 open files
+ bhis error3 / u.fp is table of users open files, index in
+ / fsp table
+ movb u.fp(r1),r1 / r1 contains number of entry in fsp table
+ beq 1f / if its zero return
+ asl r1
+ asl r1 / multiply by 8 to get index into fsp table entry
+ asl r1
+ add $fsp-4,r1 / r1 is pointing at the 3rd word in the fsp entry
+ mov r1,u.fofp / save address of 3rd word in fsp entry in u.fofp
+ mov -(r1),cdev / remove the device number cdev
+ mov -(r1),r1 / and the i-number r1
+1:
+ rts r0
+
+namei:
+ mov u.cdir,r1 / put the i-number of current directory in r1
+ mov u.cdev,cdev / device number for users directory into cdev
+ cmpb *u.namep,$'/ / is first char in file name a /
+ bne 1f
+ inc u.namep / go to next char
+ mov rootdir,r1 / put i-number of rootdirectory in r1
+ clr cdev / clear device number
+1:
+ tstb *u.namep / is the character in file name a nul
+ beq nig / yes, end of file name reached; branch to "nig"
+1:
+ jsr r0,access; 2 / get i-node with i-number r1
+ bit $40000,i.flgs / directory i-node?
+ beq error3 / no, got an error
+ mov i.size,u.dirp / put size of directory in u.dirp
+ clr u.off / u.off is file offset used by user
+ mov $u.off,u.fofp / u.fofp is a pointer to the offset portion
+ / of fsp entry
+2:
+ mov $u.dirbuf,u.base / u.dirbuf holds a file name copied from
+ / a directory
+ mov $10.,u.count / u.count is byte count for reads and writes
+ jsr r0,readi / read 10. bytes of file with i-number (r1);
+ / i.e. read a directory entry
+ tst u.nread
+ ble nib / gives error return
+ tst u.dirbuf /
+ bne 3f / branch when active directory entry (i-node word in
+ / entry non zero)
+ mov u.off,u.dirp
+ sub $10.,u.dirp
+ br 2b
+3:
+ mov u.namep,r2 / u.namep points into a file name string
+ mov $u.dirbuf+2,r3 / points to file name of directory entry
+3:
+ movb (r2)+,r4 / move a character from u.namep string into r4
+ beq 3f / if char is nul, then the last char in string has been
+ / moved
+ cmp r4,$'/ / is char a </>
+ beq 3f
+ cmp r3,$u.dirbuf+10. / have I checked all 8 bytes of file name
+ beq 3b
+ cmpb (r3)+,r4 / compare char in u.namep string to file name
+ / char read from
+ beq 3b / directory; branch if chars match
+ br 2b / file names do not match go to next directory entry
+3:
+ cmp r3,$u.dirbuf+10. / if equal all 8 bytes were matched
+ beq 3f
+ tstb (r3)+ /
+ bne 2b
+3:
+ mov r2,u.namep / u.namep points to char following a / or nul
+ mov u.dirbuf,r1 / move i-node number in directory entry to r1
+ tst r4 / if r4 = 0 the end of file name reached, if r4 = </>
+ / then go to next directory
+ bne 1b
+
+nig:
+ tst (r0)+ / gives non-error return
+nib:
+ rts r0
+
+syschdir: / makes the directory specified in the argument the current
+ / directory
+ jsr r0,arg; u.namep / u.namep points to path name
+ jsr r0,namei / find its i-number
+ br error3
+ jsr r0,access; 2 / get i-node into core
+ bit $40000,i.flgs / is it a directory?
+ beq error3 / no error
+ mov r1,u.cdir / move i-number to users current directory
+ mov cdev,u.cdev / move its device to users current device
+ br sysret3
+
+isown:
+ jsr r0,arg2 / u.namep points to file name
+ jsr r0,namei / get its i-number
+ br error3
+ jsr r0,iget / get i-node into core
+ tstb u.uid / super user?
+ beq 1f / yes, branch
+ cmpb i.uid,u.uid / no, is this the owner of the file
+ beq 1f / yes
+ jmp error3 / no, error
+1:
+ jsr r0,setimod / indicates i-node has been modified
+ mov (sp)+,r2 / mode is put in r2 (u.off put on stack with
+ / 2nd arg)
+ rts r0
+
+syschmod: / name; mode
+ jsr r0,isown / get the i-node and check user status
+ bit $40000,i.flgs / directory?
+ beq 2f / no
+ bic $60,r2 / su & ex / yes, clear set user id and
+ / executable modes
+2:
+ movb r2,i.flgs / move remaining mode to i.flgs
+ br 1f
+
+syschown: / name; owner
+ jsr r0,isown / get the i-node and check user status
+ tstb u.uid / super user
+ beq 2f / yes, 2f
+ bit $40,i.flgs / no, set userid on execution?
+ bne 3f / yes error, could create Trojan Horses
+2:
+ movb r2,i.uid / no, put the new owners id in the i-node
+1:
+ jmp sysret4
+3:
+ jmp error
+
+arg:
+ mov u.sp,r1
+ mov *18.(r1),*(r0)+ / put argument of system call into
+ / argument of arg2
+ add $2,18.(r1) / point pc on stack to next system argument
+ rts r0
+
+arg2:
+ jsr r0,arg; u.namep / u.namep contains value of first arg in
+ / sys call
+ jsr r0,arg; u.off / u.off contains value of second arg in
+ / sys call
+ mov r0,r1 / r0 points to calling routine
+ mov (sp),r0 / put operation code back in r0
+ mov u.off,(sp) / put pointer to second argument on stack
+ jmp (r1) / return to calling routine
+
+systime: / get time of year
+ mov s.time,4(sp)
+ mov s.time+2,2(sp) / put the present time on the stack
+ br sysret4
+
+sysstime: / set time
+ tstb u.uid / is user the super user
+ bne error4 / no, error
+ mov 4(sp),s.time
+ mov 2(sp),s.time+2 / set the system time
+ br sysret4
+
+sysbreak: / set the program break
+ mov u.break,r1 / move users break point to r1
+ cmp r1,$core / is it the same or lower than core?
+ blos 1f / yes, 1f
+ cmp r1,sp / is it the same or higher than the stack?
+ bhis 1f / yes, 1f
+ bit $1,r1 / is it an odd address
+ beq 2f / no, its even
+ clrb (r1)+ / yes, make it even
+2: / clear area between the break point and the stack
+ cmp r1,sp / is it higher or same than the stack
+ bhis 1f / yes, quit
+ clr (r1)+ / clear word
+ br 2b / go back
+1:
+ jsr r0,arg; u.break / put the "address" in u.break (set new
+ / break point)
+ br sysret4 / br sysret
+
+maknod: / r1 contains the mode
+ bis $100000,r1 / allocate flag set
+ mov r1,-(sp) / put mode on stack
+ mov ii,r1 / move current i-number to r1
+ jsr r0,access; 1 / get its i-node into core
+ mov r1,-(sp) / put i-number on stack
+ mov $40.,r1 / r1 = 40
+1: / scan for a free i-node (next 4 instructions)
+ inc r1 / r1 = r1 + 1
+ jsr r0,imap / get byte address and bit position in inode map in
+ / r2 & m
+ bitb mq,(r2) / is the i-node active
+ bne 1b / yes, try the next one
+ bisb mq,(r2) / no, make it active (put a 1 in the bit map)
+ jsr r0,iget / get i-node into core
+ tst i.flgs / is i-node already allocated
+ blt 1b / yes, look for another one
+ mov r1,u.dirbuf / no, put i-number in u.dirbuf
+ mov (sp)+,r1 / get current i-number back
+ jsr r0,iget / get i-node in core
+ jsr r0,mkdir / make a directory entry in current directory
+ mov u.dirbuf,r1 / r1 = new inode number
+ jsr r0,iget / get it into core
+ jsr r0,copyz; inode; inode+32. / 0 it out
+ mov (sp)+,i.flgs / fill flags
+ movb u.uid,i.uid / user id
+ movb $1,i.nlks / 1 link
+ mov s.time,i.ctim / time created
+ mov s.time+2,i.ctim+2 / time modified
+ jsr r0,setimod / set modified flag
+ rts r0 / return
+
+sysseek: / moves read write pointer in an fsp entry
+ jsr r0,seektell / get proper value in u.count
+ add u.base,u.count / add u.base to it
+ mov u.count,*u.fofp / put result into r/w pointer
+ br sysret4
+
+systell: / get the r/w pointer
+ jsr r0,seektell
+ br error4
+
+error4:
+ jmp error / see 'error' routine
+sysret4:
+ jmp sysret / see 'sysret' routine
+
+seektell:
+ jsr r0,arg; u.base / puts offset in u.base
+ jsr r0,arg; u.count / put ptr name in u.count
+ mov *u.r0,r1 / file descriptor in r1 (index in u.fp list)
+ jsr r0,getf / u.fofp points to 3rd word in fsp entry
+ mov r1,-(sp) / r1 has i-number of file, put it on the stack
+ beq error4 / if i-number is 0, not active so error
+ bgt .+4 / if its positive jump
+ neg r1 / if not make it positive
+ jsr r0,iget / get its i-node into core
+ cmp u.count,$1 / is ptr name =1
+ blt 2f / no its zero
+ beq 1f / yes its 1
+ mov i.size,u.count / put number of bytes in file in u.count
+ br 2f
+1: / ptr name =1
+ mov *u.fofp,u.count / put offset in u.count
+2: / ptrname =0
+ mov (sp)+,r1 / i-number on stack r1
+ rts r0
+
+sysintr: / set interrupt handling
+ jsr r0,arg; u.intr / put the argument in u.intr
+ br 1f / go into quit routine
+sysquit:
+ jsr r0,arg; u.quit / put argument in u.quit
+1:
+ mov u.ttyp,r1 / move pointer to control tty buffer to r1
+ beq sysret4 / return to user
+ clrb 6(r1) / clear the interrupt character in the tty buffer
+ br sysret4 / return to user
+
+syssetuid: / set process id
+ movb *u.r0,r1 / move process id (number) to r1
+ cmpb r1,u.ruid / is it equal to the real user id number
+ beq 1f / yes
+ tstb u.uid / no, is current user the super user?
+ bne error4 / no, error
+1:
+ movb r1,u.uid / put process id in u.uid
+ movb r1,u.ruid / put process id in u.ruid
+ br sysret4 / system return
+
+sysgetuid:
+ movb u.ruid,*u.r0 / move the real user id to (u.r0)
+ br sysret4 / systerm return, sysret
+
+fclose:
+ mov r1,-(sp) / put r1 on the stack (it contains the index
+ / to u.fp list)
+ jsr r0,getf / r1 contains i-number, cdev has device =, u.fofp
+ / points to 3rd word of fsp entry
+ tst r1 / is inumber 0?
+ beq 1f / yes, i-node not active so return
+ tst (r0)+ / no, jump over error return
+ mov r1,r2 / move i-number to r2
+ mov (sp),r1 / restore value of r1 from the stack which is
+ / index to u.fp
+ clrb u.fp(r1) / clear that entry in the u.fp list
+ mov u.fofp,r1 / r1 points to 3rd word in fsp entry
+ decb 2(r1) / decrement the number of processes that have opened
+ / the file
+ bge 1f / if all processes haven't closed the file, return
+ mov r2,-(sp) / put r2 on the stack (i-number)
+ clr -4(r1) / clear 1st word of fsp entry
+ tstb 3(r1) / has this file been deleted
+ beq 2f / no, branch
+ mov r2,r1 / yes, put i-number back into r1
+ jsr r0,anyi / free all blocks related to i-number
+ / check if file appears in fsp again
+2:
+ mov (sp)+,r1 / put i-number back into r1
+ jsr r0,iclose / check to see if its a special file
+1:
+ mov (sp)+,r1 / put index to u.fp back into r1
+ rts r0
+
+anyi: / r1 contains an i-number
+ mov $fsp,r2 / move start of fsp table to r2
+1:
+ cmp r1,(r2) / do i-numbers match?
+ beq 1f / yes, 1f
+ neg r1 / no complement r1
+ cmp r1,(r2) / do they match now?
+ beq 1f / yes, transfer
+ / i-numbers do not match
+ add $8,r2 / no, bump to next entry in fsp table
+ cmp r2,$fsp+[nfiles*8] / are we at last entry in the table
+ blt 1b / no, check next entries i-number
+ tst r1 / yes, no match
+ bge .+4
+ neg r1 / make i-number positive
+ jsr r0,imap / get address of allocation bit in the i-map in r2
+ bicb mq,(r2) / clear bit for i-node in the imap
+ jsr r0,itrunc / free all blocks related to i-node
+ clr i.flgs / clear all flags in the i-node
+ rts r0 / return
+1: / i-numbers match
+ incb 7(r2) / increment upper byte of the 4th word
+ rts r0 / in that fsp entry (deleted flag of fsp entry)
--- /dev/null
+/ u3 -- unix
+
+tswap:
+ movb u.uno,r1 / move users process number to r1
+ mov $runq+4,r2 / move lowest priority queue address to r2
+ jsr r0,putlu / create link from last user on Q to u.uno's user
+swap:
+ mov $300,*$ps / processor priority = 6
+ mov $runq,r2 / r2 points to runq table
+1: / search runq table for highest priority process
+ tst (r2)+ / are there any processes to run in this Q entry
+ bne 1f / yes, process 1f
+ cmp r2,$runq+6 / if zero compare address to end of table
+ bne 1b / if not at end, go back
+ jsr r0,idle; s.idlet+2 / wait for interrupt; all queues
+ / are empty
+ br swap
+1:
+ tst -(r2) / restore pointer to right Q entry
+ mov r2,u.pri / set present user to this run queue
+ movb (r2)+,r1 / move 1st process in queue to r1
+ cmpb r1,(r2)+ / is there only 1 process in this Q to be run
+ beq 1f / yes
+ tst -(r2) / no, pt r2 back to this Q entry
+ movb p.link-1(r1),(r2) / move next process in line into
+ / run queue
+ br 2f
+1:
+ clr -(r2) / zero the entry; no processes on the Q
+2: / write out core to appropriate disk area and read in new process if
+ / required
+ clr *$ps / clear processor status
+ cmpb r1,u.uno / is this process the same as the process in core?
+ beq 2f / yes, don't have to swap
+ mov r0,-(sp) / no, write out core; save r0 (address in rout.
+ / that called swap)
+ mov sp,u.usp / save stack pointer
+ mov $sstack,sp / move swap stack pointer to the stack pointer
+ mov r1,-(sp) / put r1 (new process #) on the stack
+ tstb u.uno / is the process # = 0
+ beq 1f / yes, kill process by overwriting
+ jsr r0,wswap / write out core to disk
+1:
+ mov (sp)+,r1 / restore r1 to new process number
+ jsr r0,rswap / read new process into core
+ jsr r0,unpack / unpack the users stack from next to his program
+ / to its normal
+ mov u.usp,sp / location; restore stack pointer to new process
+ / stack
+ mov (sp)+,r0 / put address of where the process that just got
+ / swapped in, left off., i.e., transfer control
+ / to new process
+2:
+ movb $30.,uquant / initialize process time quantum
+ rts r0 / return
+
+wswap:
+ mov *$30,u.emt / determines handling of emts
+ mov *$10,u.ilgins / determines handling of illegal instructions
+ mov u.break,r2 / put process program break address in r2
+ inc r2 / add 1 to it
+ bic $1,r2 / make it even
+ mov r2,u.break / set break to an even location
+ mov u.usp,r3 / put users stack pter at moment of swap in r3
+ cmp r2,$core / is u.break less than $core
+ blos 2f / yes
+ cmp r2,r3 / no, is (u.break) greater than stack pointer
+ bhis 2f / yes
+1:
+ mov (r3)+,(r2)+ / no, pack stack next to users program
+ cmp r3,$ecore / has stack reached end of core
+ bne 1b / no, keep packing
+ br 1f / yes
+2:
+ mov $ecore,r2 / put end of core in r2
+1:
+ sub $user,r2 / get number of bytes to write out (user up
+ / to end of stack gets written out)
+ neg r2 / make it negative
+ asr r2 / change bytes to words (divide by 2)
+ mov r2,swp+4 / word count
+ movb u.uno,r1 / move user process number to r1
+ asl r1 / x2 for index
+ mov r2,p.break-2(r1) / put negative of word count into the
+ / p.break table
+ mov p.dska-2(r1),r1 / move disk address of swap area for
+ / process to r1
+ mov r1,swp+2 / put processes dska address in swp +2 (block
+ / number)
+ bis $1000,swp / set it up to write (set bit 9)
+ jsr r0,ppoke / write process out on swap area of disk
+1:
+ tstb swp+1 / is lt done writing?
+ bne 1b / no, wait
+ rts r0 / yes, return to swap
+
+rswap:
+ asl r1 / process number x2 for index
+ mov p.break-2(r1), swp+4 / word count
+ mov p.dska-2(r1),swp+2 / disk address
+ bis $2000,swp / read
+ jsr r0,ppoke / read it in
+1:
+ tstb swp+1 / done
+ bne 1b / no, wait for bit 15 to clear (inhibit bit)
+ mov u.emt,*$30 / yes move these
+ mov u.ilgins,*$10 / back
+ rts r0 / return
+
+unpack: / move stack back to its normal place
+ mov u.break,r2 / r2 points to end of user program
+
+ cmp r2,$core / at beginning of user program yet?
+ blos 2f / yes, return
+ cmp r2,u.usp / is break_above the "stack pointer before
+ / swapping"
+ bhis 2f / yes, return
+ mov $ecore,r3 / r3 points to end of core
+ add r3,r2
+ sub u.usp,r2 / end of users stack is in r2
+1:
+ mov -(r2),-(r3) / move stack back to its normal place
+ cmp r2,u.break / in core
+ bne 1b
+2:
+ rts r0
+
+putlu: / r1 = user process no.; r2 points to lowest priority queue
+ tstb (r2)+ / is queue empty?
+ beq 1f / yes, branch
+ movb (r2),r3 / no, save the "last user" process number in r3
+ movb r1,p.link-1(r3) / put pointer to user on "last users" link
+ br 2f /
+1:
+ movb r1,-1(r2) / user is only user; put process no. at beginning
+ / and at end
+2:
+ movb r1,(r2) / user process in r1 is now the last entry on
+ / the queue
+ dec r2 / restore r2
+ rts r0
+
+copyz:
+ mov r1,-(sp) / put r1 on stack
+ mov r2,-(sp) / put r2 on stack
+ mov (r0)+,r1
+ mov (r0)+,r2
+1:
+ clr (r1)+ / clear all locations between r1 and r2
+ cmp r1,r2
+ blo 1b
+ mov (sp)+,r2 / restore r2
+ mov (sp)+,r1 / restore r1
+ rts r0
+
+idle:
+ mov *$ps,-(sp) / save ps on stack
+ clr *$ps / clear ps
+ mov clockp,-(sp) / save clockp on stack
+ mov (r0)+,clockp / arg to idle in clockp
+ 1 / wait for interrupt
+ mov (sp)+,clockp / restore clockp, ps
+ mov (sp)+,*$ps
+ rts r0
+
+clear:
+ jsr r0,wslot / get an I/O buffer set bits 9 and 15 in first
+ / word of I/O queue r5 points to first data word
+
+
+ / in buffer
+ mov $256.,r3
+1:
+ clr (r5)+ / zero data word in buffer
+ dec r3
+ bgt 1b / branch until all data words in buffer are zero
+ jsr r0,dskwr / write zeroed buffer area out onto physical
+ / block specified
+ rts r0 / in r1
+
+
--- /dev/null
+/ u4 -- unix
+
+setisp:
+ mov r1,-(sp)
+ mov r2,-(sp)
+ mov r3,-(sp)
+ mov clockp,-(sp)
+ mov $s.syst+2,clockp
+ jmp (r0)
+
+clock: / interrupt from 60 cycle clock
+ mov r0,-(sp) / save r0
+ tst *$lks / restart clock?
+ mov $s.time+2,r0 / increment the time of day
+ inc (r0)
+ bne 1f
+ inc -(r0)
+1:
+ mov clockp,r0 / increment appropriate time category
+ inc (r0)
+ bne 1f
+ inc -(r0)
+1:
+ mov $uquant,r0 / decrement user time quantum
+ decb (r0)
+ bge 1f / if less than 0
+ clrb (r0) / make it 0
+1: / decrement time out counts return now if priority was not 0
+ cmp 4(sp),$200 / ps greater than or equal to 200
+ bge 2f / yes, check time outs
+ tstb (r0) / no, user timed out?
+ bne 1f / no
+ cmpb sysflg,$-1 / yes, are we outside the system?
+ bne 1f / no, 1f
+ mov (sp)+,r0 / yes, put users r0 in r0
+ sys 0 / sysrele
+ rti
+2: / priority is high so just decrement time out counts
+ mov $toutt,r0 / r0 points to beginning of time out table
+2:
+ tstb (r0) / is the time out?
+ beq 3f / yes, 3f (get next entry)
+ decb (r0) / no, decrement the time
+ bne 3f / isit zero now?
+ incb (r0) / yes, increment the time
+3:
+ inc r0 / next entry
+ cmp r0,$touts / end of toutt table?
+ blo 2b / no, check this entry
+ mov (sp)+,r0 / yes, restore r0
+ rti / return from interrupt
+1: / decrement time out counts; if 0 call subroutine
+ mov (sp)+,r0 / restore r0
+ mov $240,*$ps / set processor priority to 5
+ jsr r0,setisp / save registers
+ mov $touts-toutt-1,r0 / set up r0 as index to decrement thru
+ / the table
+1:
+ tstb toutt(r0) / is the time out for this entry
+ beq 2f / yes
+ decb toutt(r0) / no, decrement the time
+ bne 2f / is the time 0, now
+ asl r0 / yes, 2 x r0 to get word index for tout entry
+ jsr r0,*touts(r0) / go to appropriate routine specified in this
+ asr r0 / touts entry; set r0 back to toutt index
+2:
+ dec r0 / set up r0 for next entry
+ bge 1b / finished? , no, go back
+ br retisp / yes, restore registers and do a rti
+ttyi: / console tty input interrupt routine
+ jsr r0,setisp / save reg r1, r2, r3
+ mov *$tkb,r1 / r1 = char in tty reader buffer
+ inc *$tks / set the reader enable bit
+ bic $!177,r1 / clear upper 9 bits of the character (strip off
+ / 8th bit of char)
+ cmp r1,$'a-40 / is character upper case A,..., upper case Z.
+ / note that
+ blt 1f / lower case a is represented by 141, upper case by
+ cmp r1,$'z-40 / 101; and lower case z by 172, upper
+ / case Z by 132.
+ bgt 1f / if not upper case, branch
+ add $40,r1 / if upper case, calculate the representation of its
+ / lower case counter part
+1:
+ cmp r1,$175 / char = "}"? Note: may be quit char (fs)
+ beq 2f / yes 2f
+ cmp r1,$177 / char = "del" ?
+ beq 2f / yes, 2f
+ jsr r0,putc; 0 / put char in r1 on clist entry
+ br 1f
+ movb r1,ttyoch / put char in ttyoch
+ jsr r0,startty / load char in tty output data buffer
+ cmp r1,$4 / r1 = "eot"
+ beq 1f / yes, 1f
+ cmp r1,$12 / r1 = "lf"
+ beq 1f / yes 1f
+ cmpb cc+0,$15. / are there less than 15 chars on the input list
+ blo retisp / yes, return
+1:
+ jsr r0,wakeup; runq; 0 / no, wakeup the input process
+ br retisp / return
+2: / r1 = "}" or "delete" to get here
+ mov tty+[ntty*8]-8+6,r2 / move console tty buffer address to r2
+ beq 2f / if 0, wakeall
+ movb r1,6(r2) / move "}" or del into "interrupt char"
+ / byte of buffer
+2:
+ jsr r0,wakeall / wakeup all sleeping processes
+ br retisp / return
+
+
+wakeall:
+ mov $39.,0f / flll arg2 of wakeup call wlth 39
+1:
+ jsr r0,wakeup; runq+4; 0:.. / wakeup the processes in the
+ dec 0b / wait list; decrement arg2
+ bge 1b / if not done, go back
+ rts r0
+
+ttyo: / console typewriter output interrupt routine
+ jsr r0,setisp / save registers
+ jsr r0,startty / put a char on the console tty output buffer
+ br retisp / restore registers
+
+retisp:
+ mov (sp)+,clockp / pop values before interrupt off the stack
+ mov (sp)+,r3
+ mov (sp)+,r2
+ mov (sp)+,r1
+ mov (sp)+,r0
+ rti / return from interrupt
+
+ppti: / paper tape lnput interrupt routine
+ jsr r0,setisp / save registers
+ movb pptiflg,r1 / place "pptiflg" in r1
+ jmp *1f(r1) / jump to location speclfled by value of "pptiflg"
+1:
+ retisp / file not open
+ 1f / file just opened
+ 2f / file normal
+ retisp / file not closed
+
+1: / file just opened
+ tstb *$prs+1 / is error bit set in prs
+ bge 1f / no
+ jsr r0,pptito / place 10 in toutt entry for ppt input
+ br retisp
+1:
+ movb $4,pptiflg / change "pptiflg" to indicate file "normal"
+2:
+ jsr r0,wakeup; runq+2; 2 / wakeup process for ppt input entry
+ / in wlist
+ tstb *$prs+1 / is error bit set
+ blt 1f / yes
+ mov *$prb,r1 / place contents ppt read buffer in r1
+ jsr r0,putc; 2 / place character in clist area for ppt input
+ br .+2 / temp / if no space in clist character lost
+ cmpb cc+2,$50. / character count in clist area for ppt lnput
+ / greater than or equal to 50
+ bhis retisp / yes
+ inc *$prs / no, set reader enable bit in prs
+ br retisp
+1:
+ movb $6,pptiflg / set pptiflg to 6 to indicate error bit set
+ br retisp
+
+/lpto:
+
+
+/ jsr r0,setisp
+/ jsr r0,starlpt
+/ br retisp
+ppto: / paper tape output interrupt routine
+ jsr r0,setisp / save registers
+ jsr r0,starppt / get next character from clist, and output
+ / if possible
+ br retisp / pop register values from stack
+
+/ starlpt:
+/ cmpb cc+5.,$100.
+/ bhi 1f
+/ jsr r0,wakeup; runq+2; 5
+/1:
+/ tstb *$lps
+/ bge 1f
+/ jsr r0,getc; 5
+/ br 1f
+/ mov r1,*$lpb
+/ br starlpt
+/1:
+/ rts r0
+
+startty: / start or restart console tty output
+ cmpb cc+1,$5.
+ bhi 1f / branch to 1f when character count on tty (? input,
+ / output) list is greater than 5.
+ jsr r0,wakeup; runq+2; 1
+1:
+ tstb *$tps / test console output ready bit
+ bge 2f / branch if ready bit is clear
+ tstb toutt+0 / is toutt for console a zero
+ bne 2f / if not; branch to 2f
+ movb ttyoch,r1 / put character to be output in r1
+ bne 1f
+ jsr r0,getc; 1 / if char is nul, get a char from console
+ / output list
+ br 2f / if console output list is empty, branch to 2f
+1:
+ clrb ttyoch
+ mov r1,*$tpb / put character in console output register
+ cmp r1,$12 / is char a line feed
+ bne 1f
+ movb $15,ttyoch / put a cr in ttyoch
+1:
+ cmp r1,$11 / char = ht
+ bne 1f
+ movb $15.,toutt+0 / set time out to 15 clock tics
+1:
+ cmp r1,$15 / char = cr
+ bne 2f
+ movb $15.,toutt+0 / set time out to 15 clock ticks
+2:
+ rts r0
+pptito: / paper tape input touts subrouting
+ cmpb pptiflg,$2 / does "pptiflg" indicate file just opened
+ bne 1f / no, do nothing pyf
+ movb $10.,toutt+1 / yes, place 10 in tout entry for tty input
+ tstb *$prs+1 / is error bit set
+ blt 1f / yes, return
+ inc *$prs / no, set read enable bit
+1:
+ rts r0
+
+starppt: / start ppt output
+ cmpb cc+3,$10. / is character count for ppt output greater
+ / than 10.
+ bhi 1f / yes, branch
+ jsr r0,wakeup; runq+2; 3 / no, wakeup process in wlist
+ / entry for ppt input
+1:
+ tstb *$pps / is ready bit set in punch status word
+ bge 1f / no, branch
+ jsr r0,getc; 3 / yes, get next char in clist for pptout and
+ / place in r1
+ br 1f / if none, branch
+ mov r1,*$ppb / place character in ppt buffer
+1:
+ rts r0
+
+wakeup: / wakeup processes waiting for an event by linking them to the
+ / queue
+ mov r1,-(sp) / put char on stack
+ mov (r0)+,r2 / r2 points to a queue
+ mov (r0)+,r3 / r3 = wait channel number
+ movb wlist(r3),r1 / r1 contains process number in that wait
+ / channel that was sleeping
+ beq 2f / if 0 return, nothing to wakeup
+ cmp r2,u.pri / is runq greater than or equal to users process
+ / priority
+ bhis 1f / yes, don't set time quantum to zero
+ clrb uquant / time quantum = 0
+1:
+ clrb wlist(r3) / zero wait channel entry
+ jsr r0,putlu / create a link from the last user on the Q
+ / to this process number that got woken
+2:
+ mov (sp)+,r1 / restore r1
+ rts r0
+
+sleep: / wait for event
+ jsr r0,isintr / check to see if interrupt or quit from user
+ br 2f / something happened / yes, his interrupt so return
+ / to user
+ mov (r0)+,r1 / put number of wait channel in r1
+ movb wlist(r1),-(sp) / put old process number in there, on
+ / the stack
+ movb u.uno,wlist(r1) / put process number of process to put
+ / to sleep in there
+ mov cdev,-(sp) / nothing happened in isintr so
+ jsr r0,swap / swap out process that needs to sleep
+ mov (sp)+,cdev / restore device
+ jsr r0,isintr / check for interrupt of new process
+ br 2f / yes, return to new user
+ movb (sp)+,r1 / no, r1 = old process number that was originally
+ / on the wait channel
+ beq 1f / if 0 branch
+ mov $runq+4,r2 / r2 points to lowest priority queue
+ mov $300,*$ps / processor priority = 6
+ jsr r0,putlu / create link to old process number
+ clr *$ps / clear the status; process priority = 0
+1:
+ rts r0 / return
+2:
+ jmp sysret / return to user
+
+isintr:
+ mov r1,-(sp) / put number of wait channel on the stack
+ mov r2,-(sp) / save r2
+ mov u.ttyp,r1 / r1 = pointer to buffer of process control
+ / typewriter
+ beq 1f / if 0, do nothing except skip return
+ movb 6(r1),r1 / put interrupt char in the tty buffer in r1
+ beq 1f / if its 0 do nothing except skip return
+ cmp r1,$177 / is interrupt char = delete?
+ bne 3f / no, so it must be a quit (fs)
+ tst u.intr / yes, value of u.intr determines handling
+ / of interrupts
+ bne 2f / if not 0, 2f. If zero do nothing.
+1:
+ tst (r0)+ / bump r0 past system return (skip)
+4:
+ mov (sp)+,r2 / restore r1 and r2
+ mov (sp)+,r1
+ rts r0
+3: / interrupt char = quit (fs)
+ tst u.quit / value of u.quit determines handling of quits
+ beq 1b / u.quit = 0 means do nothing
+2: / get here because either u.intr <> 0 or u.qult <> O
+ mov $tty+6,r1 / move pointer to tty block into r1
+1: / find process control tty entry in tty block
+ cmp (r1),u.ttyp / is this the process control tty buffer?
+ beq 1f / block found go to 1f
+ add $8,r1 / look at next tty block
+ cmp r1,$tty+[ntty*8]+6 / are we at end of tty blocks
+ blo 1b / no
+ br 4b / no process control tty found so go to 4b
+1:
+ mov $240,*$ps / set processor priority to 5
+ movb -3(r1),0f / load getc call argument; character llst
+ / identifier
+ inc 0f / increment
+1:
+ jsr r0,getc; 0:.. / erase output char list for control
+ br 4b / process tty. This prevents a line of stuff
+ / being typed out after you hit the interrupt
+ / key
+ br 1b
--- /dev/null
+/ u5 -- unix
+
+mget:
+ mov *u.fofp,mq / file offset in mq
+ clr ac / later to be high sig
+ mov $-8,lsh / divide ac/mq by 256.
+ mov mq,r2
+ bit $10000,i.flgs / lg/sm is this a large or small file
+ bne 4f / branch for large file
+ bit $!17,r2
+ bne 3f / branch if r2 greater than or equal to 16
+ bic $!16,r2 / clear all bits but bits 1,2,3
+ mov i.dskp(r2),r1 / r1 has physical block number
+ bne 2f / if physical block num is zero then need a new block
+ / for file
+ jsr r0,alloc / allocate a new block
+ mov r1,i.dskp(r2) / physical block number stored in i-node
+ jsr r0,setimod / set inode modified byte (imod)
+ jsr r0,clear / zero out disk/drum block just allocated
+2:
+ rts r0
+3: / adding on block which changes small file to a large file
+ jsr r0,alloc / allocate a new block for this file; block number
+ /in r1
+ jsr r0,wslot / set up I/O buffer for write, r5 points to first
+ / data word in buffer
+ mov $8.,r3 / next 6 instructions transfer old physical block
+ / pointers
+ mov $i.dskp,r2 / into new indirect block for the new large file
+1:
+ mov (r2),(r5)+
+ clr (r2)+
+ dec r3
+ bgt 1b
+ mov $256.-8.,r3 / clear rest of data buffer
+1:
+ clr (r5)+
+ dec r3
+ bgt 1b
+ jsr r0,dskwr / write new indirect block on disk
+ mov r1,i.dskp / put pointer to indirect block in i-node
+ bis $10000,i.flgs / set large file bit in i.flgs word of i-node
+ jsr r0,setimod / set i-node modified flag
+ br mget
+4: / large file
+ mov $-8,lsh / divide byte number by 256.
+ bic $!776,r2 / zero all bits but 1,2,3,4,5,6,7,8; gives offset
+ / in indirect block
+ mov r2,-(sp) / save on stack
+ mov mq,r2 / calculate offset in i-node for pointer to proper
+ / indirect block
+ bic $!16,r2
+ mov i.dskp(r2),r1
+ bne 2f / if no indirect block exists
+ jsr r0,alloc / allocate a new block
+ mov r1,i.dskp(r2) / put block number of new block in i-node
+ jsr r0,setimod / set i-node modified byte
+ jsr r0,clear / clear new block
+2:
+ jsr r0,dskrd / read in indirect block
+ mov (sp)+,r2 / get offset
+ mov r1,-(sp) / save block number of indirect block on stack
+ add r5,r2 / r5 points to first word in indirect block, r2
+ / points to location of inter
+ mov (r2),r1 / put physical block no of block in file
+ / sought in r1
+ bne 2f / if no block exists
+ jsr r0,alloc / allocate a new block
+ mov r1,(r2) / put new block number into proper location in
+ / indirect block
+ mov (sp)+,r1 / get block number of indirect block
+ mov (r2),-(sp) / save block number of new block
+ jsr r0,wslot
+ jsr r0,dskwr / write newly modified indirect block back out
+ / on disk
+ mov (sp),r1 / restore block number of new block
+ jsr r0,clear / clear new block
+2:
+ tst (sp)+ / bump stack pointer
+ rts r0
+
+alloc:
+ mov r2,-(sp) / save r2, r3 on stack
+ mov r3,-(sp)
+ mov $systm,r2 / start of inode and free storage map for drum
+ tst cdev
+ beq 1f / drum is device
+ mov $_mount,r2 / disk or tape is device, start of inode and free
+ / storage map
+1:
+ mov (r2)+,r1 / first word contains number of bytes in free
+ / storage map
+ asl r1 / multiply r1 by eight gives, number of blocks in device
+ asl r1
+ asl r1
+ mov r1,-(sp) / save # of blocks in device on stack
+ clr r1 / r1 contains bit count of free storage map
+1:
+ mov (r2)+,r3 / word of free storage map in r3
+ bne 1f / branch if any free blocks in this word
+ add $16.,r1
+ cmp r1 ,(sp) / have we examined all free storage bytes
+ blo 1b
+ jmp panic / found no free storage
+1:
+ asr r3 / find a free block
+ bcs 1f / branch when free block found; bit for block k is in
+ / byte k/8 / in bit k (mod 8)
+ inc r1 / increment bit count in bit k (mod8)
+ br 1b
+1:
+ tst (sp)+ / bump sp
+ jsr r0,3f / have found a free block
+ bic r3,(r2) / set bit for this block i.e. assign block
+ br 2f
+
+free:
+ mov r2,-(sp) / save r2, r3
+ mov r3,-(sp)
+ jsr r0,3f / set up bit mask and word no. in free storage map
+ / for block
+ bis r3,(r2) / set free storage block bit; indicates free block
+2:
+ mov (sp)+,r3 / restore r2, r3
+ mov (sp)+,r2
+ tst cdev / cdev = 0, block structured, drum; cdev = 1
+ / mountable device
+ bne 1f
+ incb smod / set super block modified for drum
+ rts r0
+1:
+ incb mmod / set super block modified for mountable device
+ rts r0
+3:
+ mov r1,r2 / block number, k, = 1
+ bic $!7,r2 / clear all bits but 0,1,2; r2 = (k) mod (8)
+ clr r3
+ bisb 2f(r2),r3 / use mask to set bit in r3 corresponding to
+ / (k) mod 8
+ mov r1,r2 / divide block number by 16
+ asr r2
+ asr r2
+ asr r2
+ asr r2
+ bcc 1f / branch if bit 3 in r1 was 0 i.e., bit for block is in
+ / lower half of word
+ swab r3 / swap bytes in r3; bit in upper half of word in free
+ / storage map
+1:
+ asl r2 / multiply block number by 2; r2 = k/8
+ add $systm+2,r2 / address of word of free storage map for drum
+ / with block bit in it
+ tst cdev
+ beq 1f / cdev = 0 indicates device is drum
+ add $_mount-systm,r2 / address of word of free storage map for
+ / mountable device with bit of block to be
+ / freed
+1:
+ rts r0 / return to 'free'
+2:
+ .byte 1,2,4,10,20,40,100,200 / masks for bits 0,...,7
+
+access:
+ jsr r0,iget / read in i-node for current directory (i-number
+ / passed in r1)
+ mov i.flgs,r2
+ cmpb i.uid,u.uid / is user same as owner of file
+ bne 1f / no, then branch
+ asrb r2 / shift owner read write bits into non owner
+ / read/write bits
+ asrb r2
+1:
+ bit r2,(r0)+ / test read-write flags against argument in
+ / access call
+ bne 1f
+ tstb u.uid
+ beq 1f
+ jmp error
+1:
+ rts r0
+
+setimod:
+ movb $1,imod / set current i-node modified bytes
+ mov s.time,i.mtim / put present time into file modified time
+ mov s.time+2,i.mtim+2
+ rts r0
+
+imap: / get the byte that has the allocation bit for the i-number contained
+ / in r1
+ mov $1,mq / put 1 in the mq
+ mov r1,r2 / r2 now has i-number whose byte in the map we
+ / must find
+ sub $41.,r2 / r2 has i-41
+ mov r2,r3 / r3 has i-41
+ bic $!7,r3 / r3 has (i-41) mod 8 to get the bit position
+ mov r3,lsh / move the 1 over (i-41) mod 8 positions to the left
+ / to mask the correct bit
+ asr r2
+ asr r2
+ asr r2 / r2 has (i-41) base 8 of the byte no. from the start of
+ / the map
+ mov r2,-(sp) / put (i-41) base 8 on the stack
+ mov $systm,r2 / r2 points to the in-core image of the super
+ / block for drum
+ tst cdev / is the device the disk
+ beq 1f / yes
+ add $_mount-systm,r2 / for mounted device, r2 points to 1st word
+ / of its super block
+1:
+ add (r2)+,(sp) / get byte address of allocation bit
+ add (sp)+,r2 / ?
+ add $2,r2 / ?
+ rts r0
+
+iget:
+ cmp r1,ii / r1 = i-number of current flle
+ bne 1f
+ cmp idev,cdev / is device number of i-node = current device
+ beq 2f
+1:
+ tstb imod / has i-node of current file been modified i.e.,
+ / imod set
+ beq 1f
+ clrb imod / if it has, we must write the new i-node out on disk
+ mov r1,-(sp)
+ mov cdev,-(sp)
+ mov ii,r1
+ mov idev,cdev
+ jsr r0,icalc; 1
+ mov (sp)+,cdev
+ mov (sp)+,r1
+1:
+ tst r1 / is new i-number non zero
+ beq 2f / branch if r1=0
+ tst cdev / is the current device number non zero (i.e., device
+ / =/ drum)
+ bne 1f / branch 1f cdev =/ 0
+ cmp r1,mnti / mnti is the i-number of the cross devlce
+ / file (root directory of mounted devlce)
+ bne 1f
+ mov mntd,cdev / make mounted device the current device
+ mov rootdir,r1
+1:
+ mov r1,ii
+ mov cdev,idev
+ jsr r0,icalc; 0 / read in i-node ii
+2:
+ mov ii,r1
+ rts r0
+
+icalc: / i-node i is located in block (i+31.)/16. and begins 32.*
+ / (i+31)mod16 bytes from its start
+ add $31.,r1 / add 31. to i-number
+ mov r1,-(sp) / save i+31. on stack
+ asr r1 / divide by 16.
+ asr r1
+ asr r1
+ asr r1 / r1 contains block number of block in which
+ / i-node exists
+ jsr r0,dskrd / read in block containing i-node i.
+ tst (r0)
+ beq 1f / branch to wslot when argument in icalc call = 1
+ jsr r0,wslot / set up data buffer for write (will be same buffer
+ / as dskrd got)
+1:
+ bic $!17,(sp) / zero all but last 4 bits; gives (i+31.) mod 16
+ mov (sp)+,mq / calculate offset in data buffer; 32.*(i+31.)mod16
+ mov $5,lsh / for i-node i.
+ add mq,r5 / r5 points to first word in i-node i.
+ mov $inode,r1 / inode is address of first word of current i-node
+ mov $16.,r3
+ tst (r0)+ / branch to 2 fwhen argument in icalc call = 0
+ beq 2f / r0 now contains proper return address for rts r0
+1:
+ mov (r1)+,(r5)+ / over write old i-node
+ dec r3
+ bgt 1b
+ jsr r0,dskwr / write inode out on device
+ rts r0
+2:
+ mov (r5)+,(r1)+ / read new i-node into "inode" area of core
+ dec r3
+ bgt 2b
+ rts r0
+
+itrunc:
+ jsr r0,iget
+ mov $i.dskp,r2 / address of block pointers in r2
+1:
+ mov (r2)+,r1 / move physical block number into r1
+ beq 5f
+ mov r2,-(sp)
+ bit $10000,i.flgs / test large file bit?
+ beq 4f / if clear, branch
+ mov r1,-(sp) / save block number of indirect block
+ jsr r0,dskrd / read in block, 1st data word pointed to by r5
+ mov $256.,r3 / move word count into r3
+2:
+ mov (r5)+,r1 / put 1st data word in r1; physical block number
+ beq 3f / branch if zero
+ mov r3,-(sp) / save r3, r5 on stack
+ mov r5,-(sp)
+ jsr r0,free / free block in free storage map
+ mov (sp)+,r5
+ mov (sp)+,r3
+3:
+ dec r3 / decrement word count
+ bgt 2b / branch if positive
+ mov (sp)+,r1 / put physical block number of indirect block
+4:
+ jsr r0,free / free indirect block
+ mov (sp)+,r2
+5:
+ cmp r2,$i.dskp+16.
+ bne 1b / branch until all i.dskp entries check
+ bic $10000,i.flgs / clear large file bit
+ clr i.size / zero file size
+ jsr r0,copyz; i.dskp; i.dskp+16. / zero block pointers
+ jsr r0,setimod / set i-node modified flag
+ mov ii,r1
+ rts r0
+
+
--- /dev/null
+/ u6 -- unix
+
+readi:
+ clr u.nread / accumulates number of bytes transmitted
+ tst u.count / is number of bytes to be read greater than 0
+ bgt 1f / yes, branch
+ rts r0 / no, nothing to read; return to caller
+1:
+ mov r1,-(sp) / save i-number on stack
+ cmp r1,$40. / want to read a special file (i-nodes 1,...,40 are
+ / for special files)
+ ble 1f / yes, branch
+ jmp dskr / no, jmp to dskr; read file with i-node number (r1)
+ / starting at byte ((u.fofp)), read in u.count bytes
+1:
+ asl r1 / multiply inode number by 2
+ jmp *1f-2(r1)
+1:
+ rtty / tty; r1=2
+ rppt / ppt; r1=4
+ rmem / mem; r1=6
+ rrf0 / rf0
+ rrk0 / rk0
+ rtap / tap0
+ rtap / tap1
+ rtap / tap2
+ rtap / tap3
+ rtap / tap4
+ rtap / tap5
+ rtap / tap6
+ rtap / tap7
+ rcvt / tty0
+ rcvt / tty1
+ rcvt / tty2
+ rcvt / tty3
+ rcvt / tty4
+ rcvt / tty5
+ rcvt / tty6
+ rcvt / tty7
+ rcrd/ crd
+
+rtty: / read from console tty
+ mov tty+[8*ntty]-8+6,r5 / r5 is the address of the 4th word of
+ / of the control and status block
+ tst 2(r5) / for the console tty; this word points to the console
+ / tty buffer
+ bne 1f / 2nd word of console tty buffer contains number
+ / of chars. Is this number non-zero?
+ jsr r0,canon; ttych / if 0, call 'canon' to get a line
+ / (120 chars.)
+1:
+ tst 2(r5) / is the number of characters zero
+ beq ret1 / yes, return to caller via 'ret1'
+ movb *4(r5),r1 / no, put character in r1
+ inc 4(r5) / 3rd word of console tty buffer points to byte which
+ / contains the next char.
+ dec 2(r5) / decrement the character count
+ jsr r0,passc / move the character to core (user)
+ br 1b / get next character
+
+ret1:
+ jmp ret / return to caller via 'ret'
+
+rppt: / read paper tape
+ jsr r0,pptic / gets next character in clist for ppt input and
+ / places
+ br ret / it in r1; if there 1s no problem with reader, it
+ / also enables read bit in prs
+ jsr r0,passc / place character in users buffer area
+ br rppt
+
+rmem: / transfer characters from memory to a user area of core
+ mov *u.fofp,r1 / save file offset which points to the char to
+ / be transferred to user
+ inc *u.fofp / increment file offset to point to 'next' char in
+ / memory file
+ movb (r1),r1 / get character from memory file, put it in r1
+ jsr r0,passc / move this character to the next byte of the
+ / users core area
+ br rmem / continue
+1:
+rcrd:
+ jmp error / see 'error' routine
+
+dskr:
+ mov (sp),r1 / i-number in r1
+ jsr r0,iget / get i-node (r1) into i-node section of core
+ mov i.size,r2 / file size in bytes in r2
+ sub *u.fofp,r2 / subtract file offset
+ blos ret
+ cmp r2,u.count / are enough bytes left in file to carry out read
+ bhis 1f
+ mov r2,u.count / no, just read to end of file
+1 :
+ jsr r0,mget / returns physical block number of block in file
+ / where offset points
+ jsr r0,dskrd / read in block, r5 points to 1st word of data in
+ / buffer
+ jsr r0,sioreg
+2:
+ movb (r2)+,(r1)+ / move data from buffer into working core
+ / starting at u.base
+ dec r3
+ bne 2b / branch until proper number of bytes are transferred
+ tst u.count / all bytes read off disk
+ bne dskr
+ br ret
+
+passc:
+ movb r1,*u.base / move a character to the next byte of the
+ / users buffer
+ inc u.base / increment the pointer to point to the next byte
+ / in users buffer
+ inc u.nread / increment the number of bytes read
+ dec u.count / decrement the number of bytes to be read
+ bne 1f / any more bytes to read?; yes, branch
+ mov (sp)+,r0 / no, do a non-local return to the caller of
+ / 'readi' by:
+ret: / (1) pop the return address off the stack into r0
+ mov (sp)+,r1 / (2) pop the i-number off the stack into r1
+1:
+ clr *$ps / clear processor status
+ rts r0 / return to address currently on top of stack
+
+writei:
+ clr u.nread / clear the number of bytes transmitted during
+ / read or write calls
+ tst u.count / test the byte count specified by the user
+ bgt 1f / any bytes to output; yes, branch
+ rts r0 / no, return - no writing to do
+1:
+ mov r1 ,-(sp) / save the i-node number on the stack
+ cmp r1,$40. / does the i-node number indicate a special file?
+ bgt dskw / no, branch to standard file output
+ asl r1 / yes, calculate the index into the special file
+ jmp *1f-2(r1) / jump table and jump to the appropriate routine
+1:
+ wtty / tty
+ wppt / ppt
+ wmem / mem
+ wrf0 / rf0
+ wrk0 / rk0
+ wtap / tap0
+ wtap / tap1
+ wtap / tap2
+ wtap / tap3
+ wtap / tap4
+ wtap / tap5
+ wtap / tap6
+ wtap / tap7
+ xmtt / tty0
+ xmtt / tty1
+ xmtt / tty2
+ xmtt / tty3
+ xmtt / tty4
+ xmtt / tty5
+ xmtt / tty6
+ xmtt / tty7
+/ w1pr / lpr
+
+wtty:
+ jsr r0,cpass / get next character from user buffer area; if
+ / none go to return address in syswrite
+ tst r1 / is character = null
+ beq wtty / yes, get next character
+1 :
+ mov $240,*$ps / no, set processor priority to five
+ cmpb cc+1,$20. / is character count for console tty greater
+ / than 20
+ bhis 2f / yes; branch to put process to sleep
+ jsr r0,putc; 1 / find place in freelist to assign to console
+ / tty and
+ br 2f / place character in list; if none available
+ / branch to put process to sleep
+ jsr r0,startty / attempt to output character on tty
+ br wtty
+2:
+ mov r1,-(sp) / place character on stack
+ jsr r0,sleep; 1 / put process to sleep
+ mov (sp)+,r1 / remove character from stack
+ br 1b / try again to place character in clist and output
+
+wppt:
+ jsr r0,cpass / get next character from user buffer area,
+ / if none return to writei's calling routine
+ jsr r0,pptoc / output character on ppt
+ br wppt
+/wlpr:
+/ jsr r0,cpass
+/ cmp r0,$'a
+/ blo 1f
+/ cmp r1,$'z
+/ bhi 1f
+/ sub $40,r1
+/1:
+/ jsr r0,lptoc
+/ br wlpr
+
+wmem: / transfer characters from a user area of core to memory file
+ jsr r0,cpass / get next character from users area of core and
+ / put it in r1
+ mov r1,-(sp) / put character on the stack
+ mov *u.fofp,r1 / save file offset in r1
+ inc *u.fofp / increment file offset to point to next available
+ / location in file
+ movb (sp)+,(r1) / pop char off stack, put in memory loc assigned
+ / to it
+ br wmem / continue
+1:
+ jmp error / ?
+
+dskw: / write routine for non-special files
+ mov (sp),r1 / get an i-node number from the stack into r1
+ jsr r0,iget / write i-node out (if modified), read i-node 'r1'
+ / into i-node area of core
+ mov *u.fofp,r2 / put the file offset [(u.off) or the offset in
+ / the fsp entry for this file] in r2
+ add u.count,r2 / no. of bytes to be written + file offset is
+ / put in r2
+ cmp r2,i.size / is this greater than the present size of
+ / the file?
+ blos 1f / no, branch
+ mov r2,i.size / yes, increase the f11e size to file offset +
+ / no. of data bytes
+ jsr r0,setimod / set imod=1 (i.e., core inode has been
+ / modified), stuff tlme of modification into
+ / core image of i-node
+1:
+ jsr r0,mget / get the block no. in which to write the next data
+ / byte
+ bit *u.fofp,$777 / test the lower 9 bits of the file offset
+ bne 2f / if its non-zero, branch; if zero, file offset = 0,
+ / 512, 1024,...(i.e., start of new block)
+ cmp u.count,$512. / if zero, is there enough data to fill an
+ / entire block? (i.e., no. of
+ bhis 3f / bytes to be written greater than 512.? Yes, branch.
+ / Don't have to read block
+2: / in as no past info. is to be saved (the entire block will be
+ / overwritten).
+ jsr r0,dskrd / no, must retain old info.. Hence, read block 'r1'
+ / into an I/O buffer
+3:
+ jsr r0,wslot / set write and inhibit bits in I/O queue, proc.
+ / status=0, r5 points to 1st word of data
+ jsr r0,sioreg / r3 = no. of bytes of data, r1 = address of data,
+ / r2 points to location in buffer in which to
+ / start writing data
+2:
+ movb (r1 )+,(r2)+ / transfer a byte of data to the I/O buffer
+ dec r3 / decrement no. of bytes to be written
+ bne 2b / have all bytes been transferred? No, branch
+ jsr r0,dskwr / yes, write the block and the i-node
+ tst u.count / any more data to write?
+ bne 1b / yes, branch
+ jmp ret / no, return to the caller via 'ret'
+
+cpass: / get next character from user area of core and put it in r1
+ tst u.count / have all the characters been transferred (i.e.,
+ / u.count, # of chars. left
+ beq 1f / to be transferred = 0?) yes, branch
+ dec u.count / no, decrement u.count
+ movb *u.base,r1 / take the character pointed to by u.base and
+ / put it in r1
+ inc u.nread / increment no. of bytes transferred
+ inc u.base / increment the buffer address to point to the
+ rts r0 / next byte
+1:
+ mov (sp)+,r0 / put return address of calling routine into r0
+ mov (sp)+,r1 / i-number in r1
+ rts r0 / non-local return
+
+sioreg:
+ mov *u.fofp,r2 / file offset (in bytes) is moved to r2
+ mov r2,r3 / and also to r3
+ bis $177000,r3 / set bits 9,...,15. of file offset in r3
+ bic $!777,r2 / calculate file offset mod 512.
+ add r5,r2 / r2 now points to 1st byte in system buffer where
+ / data is to be placed
+ mov u.base,r1 / address of data is in r1
+ neg r3 / 512 - file offset (mod512.) in r3 (i.e., the number
+ / of free bytes in the file block
+ cmp r3,u.count / compare this with the number of data bytes to
+ / be written to the file
+ blos 2f / if less than branch. Use the number of free bytes
+ / in the file block as the number to be written
+ mov u.count,r3 / if greater than, use the number of data bytes
+ / as the number to be written
+2:
+ add r3,u.nread / r3 + number of bytes xmitted during write is
+ / put into u.nread
+ sub r3,u.count / u.count = no. of bytes that still must be
+ / written or read
+ add r3,u.base / u.base points to the 1st of the remaining data
+ / bytes
+ add r3,*u.fofp / new file offset = number of bytes done + old
+ / file offset
+ rts r0
+
--- /dev/null
+/ u7 -- unix
+
+canon:
+ mov r5,r1 / move tty buffer address to r1
+ add $10.,r1 / add 10 to get start of data
+ mov r1,4(r5) / canp = 10(r5) / move buffer addr + 10 to 3rd
+ / word in buffer (char. pointer)
+ clr 2(r5) / ncan / clear 2nd word in buffer, 0 char. count
+1:
+ jsr r0,*(r0) / jump to arg get char off Q of characters, sleep
+ / if none
+ jsr r0,cesc; 100 / test for @ (kill line)
+ br canon / character was @ so start over
+ jsr r0,cesc; 43 / test for # (erase last char. typed)
+ br 1b / character was #, go back
+ cmp r1,$4 / is char eot?
+ beq 1f / yes, reset and return
+ movb r1,*4(r5) / no, move char to address in 3rd word of buffer
+ / (char. pointer)
+ inc 2(r5) / increment 2nd word (char. count)
+ inc 4(r5) / increment 3rd word (char. pointer)
+ cmp r1,$'\n / is char = newline
+ beq 1f / yes, 1f
+ cmp 2(r5),$120. / is byte count greater than or equal to 120
+ bhis 1f / yes, 1f
+ br 1b / no, get another char off the Q
+1: / get here if line is full, a new line has been received or an eot
+ / has been received
+ mov r5,r1 / move buffer address to r1
+ add $10.,r1 / add 10
+ mov r1,4(r5) / canp = 10(r5) / reset char pointer
+ tst (r0)+ / skip over argument
+ rts r0 / return
+
+cesc: / test for erase or kill char
+ cmp r1,(r0)+ / char in r1 = erase or kill character?
+ bne 1f / no, skip return
+ tst 2(r5) / yes, is char. count = 0
+ beq 2f / yes, don't skip return
+ dec 2(r5) / no, decrement char count
+ dec 4(r5) / decrement character pointer
+ cmpb *4(r5),$'\\/ was previous character a "\"
+ bne 2f / no, don't skip
+1:
+ tst (r0)+ / yes, skip
+2:
+ rts r0 / return
+
+ttych: / get characters from Q of characters inputted to tty
+ mov $240,*$ps / set processor priority to 5
+ jsr r0,getc; 0 / takes char. off clist and puts it in r1
+ br 1f / list is empty, go to sleep
+ clr *$ps / clear process priority
+ rts r0 / return
+1: / list is empty
+ mov r5,-(sp) / save r5
+ jsr r0,sleep; 0 / put process to sleep in input wait channel
+ mov (sp)+,r5 / restore r5
+ br ttych / try again
+
+pptic: / paper tape input control
+ mov $240,*$ps / set processor priority to five
+ cmpb cc+2,$30. / is character count for paper tape input in
+ / clist greater than or equal to 30
+ bhis 1f / yes, branch
+ bit *$prs,$104200 / is there either an error, an unread char
+ / in buffer, or reader busy
+ bne 1f / yes, don't enable reader
+ inc *$prs / set reader enable bit
+1:
+ jsr r0,getc; 2 / get next character in clist for ppt input and
+ br 1f / place in r1; if no char in clist for ppt input
+ / branch
+ tst (r0)+ / pop stack so that return will be four locations past
+ / subroutine call
+2:
+ clr *$ps / set process priority equal to zero
+ rts r0 / return
+1:
+ cmpb pptiflg,$6 / does pptiflg indicate file "not closed"
+ beq 2b / yes, return to calling routine at instruction
+ / immediately following jsr
+ jsr r0,sleep; 2 / no, all characters to be read in not yet in
+ / clist, put process to sleep
+ br pptic
+
+pptoc: / paper tape output control
+ mov $240,*$ps / set processor priority to five
+ cmpb cc+3,$50. / is character count for paper tape output in
+ / clist greater than or equal to 50
+ bhis 1f / yes
+ jsr r0,putc; 3 / find place in freelist to assign ppt output
+ / and place
+ br 1f / character in list; if none available branch to put
+ / process to sleep
+ jsr r0,starppt / try to output character
+ clr *$ps / clear processor priority
+ rts r0 / return
+1:
+ mov r1,-(sp) / place character on stack
+ jsr r0,sleep; 3 / put process to sleep
+ mov (sp)+,r1 / place character in r1
+ br pptoc / try again to place character in clist and output
+
+/lptoc: / line printer output control
+/ mov $240,*$ps / set processor priority to five
+/ cmpb cc+5,$200. / is character count for printer greater than or
+ / equal to 200
+/ bhis 1f / yes
+/ jsr r0,putc; 5 / find place in freelist to assign to printer
+ / and place
+
+ br 1f / char in list, if none available branch to put
+ / process to sleep
+/ jsr r0,starlpt / try to output character
+/ clr *$ps / set processor priority = 0
+/ rts r0 / return
+/1:
+/ mov r1,-(sp) / place character on stack
+/ jsr r0,sleep; 5 / put process to sleep
+/ mov (sp)+,r1 / place character on stack
+/ br lptoc
+
+getc: / get a character off character list
+ mov (r0)+,r1 / put argument in getc call in r1 (char list id)
+ jsr r0,get
+ br 1f / empty char list return
+ decb cc(r1) / decrement number of char in char list
+ mov $-1,r1 / load minus 1 in r1
+ jsr r0,put / put char back on free list
+ movb clist-2(r2),r1 / put char in r1
+ tst (r0)+ / bump r0 for non blank char list return
+1:
+ rts r0
+
+putc:
+ mov r1,-(sp) / save char on stack
+ mov $-1,r1 / put free list list id in r1
+ jsr r0,get / take char off free list / clist slot taken
+ / identified by r2
+ br 1f / branch when no chars in free list
+ mov (r0)+,r1 / put putc call arg in r1 (i.e., list identifier)
+ incb cc(r1) / increment character count for list (r1)
+ jsr r0,put / put clist entry on list
+ movb (sp),clist-2(r2) / put character in new entry
+1:
+ tst (r0)+
+ mov (sp)+,r1
+ rts r0
+
+get:
+ movb cf+1(r1),r2 / move current first char offset to r2
+ beq 2f / no characters in char list
+ tst (r0)+ / bump r0, second return
+ cmpb r2,cl+1(r1) / r2 equal to last char offset
+ beq 1f / yes, (i.e., entire char list scanned), branch to 1f
+ bic $!377,r2 / clear bits 8-15 in r2
+ asl r2 / multiply r2 by 2 to get offset in clist
+ movb clist-1(r2),cf+1(r1) / move next char in list pointer to
+ / first char offset ptr
+ br 2f
+1:
+ clrb cf+1(r1) / clear first char clist offset
+ clrb cl+1(r1) / clear last char clist offset
+ bic $!377,r2 / zero top half of r2
+ asl r2 / multiply r2 by 2
+2:
+ rts r0
+
+put:
+ asr r2 / divide r2 by 2; r2 is offset in clist
+ mov r2,-(sp) / save r2 on stack
+ movb cl+1(r1),r2 / move offset of last char in list (r1) into r2
+ beq 1f / offset = 0 then go to 1f (i.e., start a new list)
+ bic $!377,r2 / zero top half of r2
+ asl r2 / multiply offset by 2, r2 now has offset in clist
+ movb (sp),clist-1(r2) / link new list entry to current last
+ / entry in list (r1)
+ br 2f
+1:
+ movb (sp),cf+1(r1) / put new list entry offset into first char
+ / offset of list (r1)
+2:
+ mov (sp)+,r2 / pop stack into r2; offset of new list
+ / entry in r2
+ movb r2,cl+1(r1) / make new list entry the last entry in list
+ / (r1)
+ asl r2 / multiply r2 by 2; r2 has clist offset for new
+ / list entry
+ rts r0
+
+iopen: / open file whose i-number is in r1
+ tst r1 / write or read access?
+ blt 2f / write, go to 2f
+ jsr r0,access; 2 / get inode into core with read access
+ cmp r1,$40. / is it a special file
+ bgt 3f / no. 3f
+ mov r1,-(sp) / yes, figure out
+ asl r1
+ jmp *1f-2(r1) / which one and transfer to it
+1:
+ otty / tty
+ oppt / ppt
+ sret / mem
+ sret / rf0
+ sret / rk0
+ sret / tap0
+ sret / tap1
+ sret / tap2
+ sret / tap3
+ sret / tap4
+ sret / tap5
+ sret / tap6
+ sret / tap7
+ ocvt / tty0
+ ocvt / tty1
+ ocvt / tty2
+ ocvt / tty3
+ ocvt / tty4
+ ocvt / tty5
+ ocvt / tty6
+ ocvt / tty7
+ error / crd
+
+2: / check open write access
+ neg r1 / make inode number positive
+ jsr r0,access; 1 / get inode in 0 core
+ bit $40000,i.flgs / is it a directory?
+ bne 2f / yes, transfer (error)
+ cmp r1,$40. / no, is it a special file?
+ bgt 3f / no, return
+ mov r1,-(sp) / yes
+ asl r1
+ jmp *1f-2(r1) / figure out which special file it is
+ / and transfer
+1:
+ otty / tty
+ leadr / ppt
+ sret / mem
+ sret / rf0
+ sret / rk0
+ sret / tap0
+ sret / tap1
+ sret / tap2
+ sret / tap3
+ sret / tap4
+ sret / tap5
+ sret / tap6
+ sret / tap7
+ ocvt / tty0
+ ocvt / tty1
+ ocvt / tty2
+ ocvt / tty3
+ ocvt / tty4
+ ocvt / tty5
+ ocvt / tty6
+ ocvt / tty7
+/ ejec / lpr
+
+otty: / open console tty for reading or writing
+ mov $100,*$tks / set interrupt enable bit (zero others) in
+ / reader status reg
+ mov $100,*$tps / set interrupt enable bit (zero others) in
+ / punch status reg
+ mov tty+[ntty*8]-8+6,r5 / r5 points to the header of the
+ / console tty buffer
+ incb (r5) / increment the count of processes that opened the
+ / console tty
+ tst u.ttyp / is there a process control tty (i.e., has a tty
+ / buffer header
+ bne sret / address been loaded into u.ttyp yet)? yes, branch
+ mov r5,u.ttyp / no, make the console tty the process control
+ / tty
+ br sret / ?
+
+sret:
+ clr *$ps / set processor priority to zero
+ mov (sp)+,r1 / pop stack to r1
+3:
+ rts r0
+
+oppt: / open paper tape for reading or writing
+ mov $100,*$prs / set reader interrupt enable bit
+ tstb pptiflg / is file already open
+ bne 2f / yes, branch
+1:
+ mov $240,*$ps / no, set processor priority to 5
+ jsr r0,getc; 2 / remove all entries in clist
+ br .+4 / for paper tape input and place in free list
+ br 1b
+ movb $2,pptiflg / set pptiflg to indicate file just open
+ movb $10.,toutt+1 / place 10 in paper tape input tout entry
+ br sret
+2:
+ jmp error / file already open
+
+iclose: / close file whose i-number is in r1
+ tst r1 / test i-number
+ blt 2f / if neg., branch
+ cmp r1,$40. / is it a special file
+ bgt 3b / no, return
+ mov r1,-(sp) / yes, save r1 on stack
+ asl r1
+ jmp *1f-2(r1) / compute jump address and transfer
+1:
+ ctty / tty
+ cppt / ppt
+ sret / mem
+ sret / rf0
+ sret / rk0
+ sret / tap0
+ sret / tap1
+ sret / tap2
+ sret / tap3
+ sret / tap4
+ sret / tap5
+ sret / tap6
+ sret / tap7
+ ccvt / tty0
+ ccvt / tty1
+ ccvt / tty2
+ ccvt / tty3
+ ccvt / tty4
+ ccvt / tty5
+ ccvt / tty6
+ ccvt / tty7
+ error / crd
+
+2: / negative i-number
+ neg r1 / make it positive
+ cmp r1,$40. / is it a special file
+ bgt 3b / no. return
+ mov r1,-(sp)
+ asl r1 / yes. compute jump address and transfer
+ jmp *1f-2(r1)
+1:
+ ctty / tty
+ leadr / ppt
+ sret / mem
+ sret / rf0
+ sret / rk0
+ sret / tap0
+ sret / tap1
+ sret / tap2
+ sret / tap3
+ sret / tap4
+ sret / tap5
+ sret / tap6
+ sret / tap7
+ ccvt / tty0
+ ccvt / tty1
+ ccvt / tty2
+ ccvt / tty3
+ ccvt / tty4
+ ccvt / tty5
+ ccvt / tty6
+ ccvt / tty7
+/ ejec / lpr
+
+ctty: / close console tty
+ mov tty+[ntty*8]-8+6,r5 / point r5 to the console tty buffer
+ decb (r5) / dec number of processes using console tty
+ br sret / return via sret
+
+cppt: / close paper tape
+ clrb pptiflg / set pptiflg to indicate file not open
+1:
+ mov $240,*$ps /set process or priority to 5
+ jsr r0,getc; 2 / remove all ppt input entries from clist
+ / and assign to free list
+ br sret
+ br 1b
+
+/ejec:
+/ mov $100,*$lps / set line printer interrupt enable bit
+/ mov $14,r1 / 'form feed' character in r1 (new page).
+/ jsr r0,lptoc / space the printer to a new page
+/ br sret / return to caller via 'sret'
+
+leadr: / produce paper tape leader
+ mov $100,*$pps / set paper tape punch interrupt enable
+ mov $100.,-(sp) / 101. characters of 'nul' will be output as
+ / leader
+1:
+ clr r1 / r1 contains a 'nul' character
+ jsr r0,pptoc / output the 'nul' character
+ dec (sp)
+ bge 1b / last leader character output? no, branch
+ tst (sp)+ / bump stack pointer
+ br sret / return to caller via 'sret'
+
+sysmount: / mount file system; args special; name
+
+ jsr r0,arg2 / get arguments special and name
+ tst mnti / is the i-number of the cross device file zero?
+ bne errora / no, error
+ jsr r0,getspl / get special files device number in r1
+ mov (sp)+,u.namep / put the name of file to be placed on the
+ / device
+ mov r1,-(sp) / save the device number
+ jsr r0,namei / get the i-number of the file
+ br errora
+ mov r1,mnti / put it in mnti
+1:
+ tstb sb1+1 / is 15th bit of I/O queue entry for dismountable
+ / device set?
+ bne 1b / (inhibit bit) yes, skip writing
+ mov (sp),mntd / no, put the device number in mntd
+ movb (sp),sb1 / put the device number in the lower byte of the
+ / I/O queue entry
+ mov (sp)+,cdev / put device number in cdev
+ bis $2000,sb1 / set the read bit
+ jsr r0,ppoke / read in entire file system
+1:
+ tstb sb1+1 / done reading?
+ bne 1b / no, wait
+ br sysreta / yes
+
+sysumount: / special dismount file system
+ jsr r0,arg; u.namep / point u.namep to special
+ jsr r0,getspl / get the device number in r1
+ cmp r1,mntd / is it equal to the last device mounted?
+ bne errora / no error
+1:
+ tstb sb1+1 / yes, is the device still doing I/O (inhibit
+ / bit set)?
+ bne 1b / yes, wait
+ clr mntd / no, clear these
+ clr mnti
+ br sysreta / return
+
+getspl: / get device number from a special file name
+ jsr r0,namei / get the i-number of the special file
+ br errora / no such file
+ sub $4,r1 / i-number-4 rk=1,tap=2+n
+ ble errora / less than 0? yes, error
+ cmp r1,$9. / greater than 9 tap 7
+ bgt errora / yes, error
+ rts r0 / return with device number in r1
+
+errora:
+ jmp error / see 'error' routine
+
+sysreta:
+ jmp sysret / see 'sysret' routine
+
--- /dev/null
+/ u8 -- unix
+
+rtap: / read from the dec tape
+ asr r1 / divide the i-number by 2
+ sub $4.,r1 / (i-number/2)-4 r1
+ mov r1,cdev / cdev now has device number
+ jsr r0,bread; 578. / read in block thats in *u.fofp
+
+wtap:
+ asr r1 / divide i-number by 2
+ sub $4.,r1 / r1 = i-number minus 4
+ mov r1,cdev / this is used as the device number
+ jsr r0,bwrite; 578. / write block (u.fofp) on dec tape
+ / Maximum
+
+rrk0:
+ mov $1,cdev / set current device to i., disk
+ jsr r0,bread; 4872. / read block from disk (maximum block
+ / number allowed on device is 4872.)
+ / - (u.fofp) contains block number
+
+wrk0:
+ mov $1,cdev / set current device to 1; disk
+ jsr r0,bwrite; 4872. / write block (u.fofp) on disk
+
+rrf0:
+ clr cdev / set current device to 0., fixed head disk
+ jsr r0,bread; 1024. / read block (u.fofp) from fixed head
+ / disk (max. block number allowed on
+ / device is 1024.)
+
+wrf0:
+ clr cdev / set current device to 0., fixed head disk
+ jsr r0,bwrite; 1024. / write block '(u.fofp)' on fixed head
+ / disk
+
+bread: / read a block from a block structured device
+ jsr r0,tstdeve / error on special file I/O (only works on
+ / tape)
+ mov *u.fofp,r1 / move block number to r1
+ mov $2.-cold,-(sp) / "2-cold" to stack
+1:
+ cmp r1,(r0) / is this block # greater than or equal to
+ / maximum block # allowed on device
+ bhis 1f / yes, 1f (error)
+ mov r1,-(sp) / no, put block # on stack
+ jsr r0,preread / read in the block into an I/O buffer
+ mov (sp)+,r1 / return block # to r1
+ inc r1 / bump block # to next consecutive block
+ dec (sp) / "2-1-cold" on stack
+ bgt 1b / 2-1-cold = 0? No, go back and read in next block
+1:
+ tst (sp)+ / yes, pop stack to clear off cold calculation
+ mov *u.fofp,r1 / restore r1 to initial value of the
+ / block #
+ cmp r1,(r0)+ / block # greater than or equal to maximum
+ / block number allowed
+ bhis error10 / yes, error
+ inc *u.fofp / no, *u.fofp has next block number
+ jsr r0,preread / read in the block whose number is in r1
+ bis $40000,(r5) / set bit 14 of the 1st word of the I/O
+ / buffer
+1:
+ bit $22000,(r5) / are 10th and 13th bits set (read bits)
+ beq 1f / no
+ cmp cdev,$1 / disk or drum?
+ ble 2f / yes
+ tstb uquant / is the time quantum = 0?
+ bne 2f / no, 2f
+ mov r5,-(sp) / yes, save r5 (buffer address)
+ jsr r0,sleep; 31. / put process to sleep in channel 31 (tape)
+ mov (sp)+,r5 / restore r5
+ br 1b / go back
+2: / drum or disk
+ jsr r0,idle; s.wait+2 / wait
+ br 1b
+1: / 10th and 13th bits not set
+ bic $40000,(r5) / clear bit 14
+ jsr r0,tstdeve / test device for error (tape)
+ add $8,r5 / r5 points to data in I/O buffer
+ jsr r0,dioreg / do bookkeeping on u.count etc.
+1: / r5 points to beginning of data in I/O buffer, r2 points to beginning
+ / of users data
+ movb (r5)+,(r2)+ / move data from the I/O buffer
+ dec r3 / to the user's area in core starting at u.base
+ bne 1b
+ tst u.count / done
+ beq 1f / yes, return
+ tst -(r0) / no, point r0 to the argument again
+ br bread / read some more
+1:
+ mov (sp)+,r0 / jump to routine that called readi
+ jmp ret
+
+bwrite: / write on block structured device
+ jsr r0,tstdeve / test the device for an error
+ mov *u.fofp,r1 / put the block number in r1
+ cmp r1,(r0)+ / does block number exceed maximum allowable #
+ bhis error10 / yes, error
+ inc *u.fofp / no, increment block number
+ jsr r0,wslot / get an I/O buffer to write into
+ jsr r0,dioreg / do the necessary bookkeeping
+1: / r2 points to the users data; r5 points to the I/O buffers data area
+ movb (r2)+,(r5)+ / ; r3, has the byte count
+ dec r3 / area to the I/O buffer
+ bne 1b
+ jsr r0,dskwr / write it out on the device
+ tst u.count / done
+ beq 1f / yes, 1f
+ tst -(r0) / no, point r0 to the argument of the call
+ br bwrite / go back and write next block
+1:
+ mov (sp)+,r0 / return to routine that called writei
+ jmp ret
+tstdeve: / check whether permanent error has occured on special file
+ / I/O
+ mov cdev,r1 / only works on tape; r1 has device #
+ tstb deverr(r1) / test error bit of device
+ bne 1f / error
+ rts r0 / device okay
+1:
+ clrb deverr(r1) / clear error
+
+error10:
+ jmp error / see 'error' routine
+
+dioreg:
+ mov u.count,r3 / move char count to r3
+ cmp r3,$512. / more than 512. char?
+ blos 1f / no, branch
+ mov $512.,r3 / yes, just take 512.
+1:
+ mov u.base,r2 / put users base in r2
+ add r3,u.nread / add the number to be read to u.nread
+ sub r3,u.count / update count
+ add r3,u.base / update base
+ rts r0 / return
+
+preread:
+ jsr r0,bufaloc / get a free I/O buffer (r1 has block number)
+ br 1f / branch if block already in a I/O buffer
+ bis $2000,(r5) / set read bit (bit 100 in I/O buffer)
+ jsr r0,poke / perform the read
+1:
+ clr *$ps / ps = 0
+ rts r0
+
+dskrd:
+ jsr r0,bufaloc / shuffle off to bufaloc; get a free I/O buffer
+ br 1f
+ bis $2000,(r5) / set bit 10 of word 1 of I/O queue entry
+ / for buffer
+ jsr r0,poke / just assigned in bufaloc, bit 10=1 says read
+1:
+ clr *$ps
+ bit $22000,(r5) / if either bits 10, or 13 are 1; jump to idle
+ beq 1f
+ jsr r0,idle; s.wait+2
+ br 1b
+1:
+ add $8,r5 / r5 points to first word of data in block just read
+ / in
+ rts r0
+
+wslot:
+ jsr r0,bufaloc / get a free I/O buffer; pointer to first
+ br 1f / word in buffer in r5
+1:
+ bit $22000,(r5) / check bits 10, 13 (read, waiting to read)
+ / of I/O queue entry
+ beq 1f / branch if 10, 13 zero (i.e., not reading, or waiting
+ / to read)
+ jsr r0,idle; s.wait+2 / if buffer is reading or writing to read,
+ / idle
+ br 1b / till finished
+1:
+ bis $101000,(r5) / set bits 9, 15 in 1st word of I/O queue
+ / (write, inhibit bits)
+ clr *$ps / clear processor status
+ add $8,r5 / r5 points to first word in data area for this
+ / block
+ rts r0
+
+dskwr:
+ bic $100000,*bufp / clear bit 15 of I/O queue entry at
+ / bottom of queue
+
+ppoke:
+ mov $340,*$ps
+ jsr r0,poke
+ clr *$ps
+ rts r0
+poke:
+ mov r1,-(sp)
+ mov r2,-(sp)
+ mov r3,-(sp)
+ mov $bufp+nbuf+nbuf+6,r2 / r2 points to highest priority I/O
+ / queue pointer
+1:
+ mov -(r2),r1 / r1 points to an I/O queue entry
+ bit $3000,(r1) / test bits 9 and 10 of word 1 of I/O queue
+ / entry
+ beq 2f / branch to 2f if both are clear
+ bit $130000,(r1) / test bits 12, 13, and 15
+ bne 2f / branch if any are set
+ movb (r1),r3 / get device id
+ tstb deverr(r3) / test for errors on this device
+ beq 3f / branch if no errors
+ mov $-1,2(r1) / destroy associativity
+ clrb 1(r1) / do not do I/O
+ br 2f
+3:
+ cmpb r3,$1 / device id = 1; device is disk
+ blt prf / device id = 0; device is drum
+ bgt ptc / device id greater than or equal to 1; device is
+ / dec tape
+ bit $2,active / test disk busy bit
+ bne 2f / branch if bit is set
+ bis $2,active / set disk busy bit
+ mov r1,rkap / rkap points to current I/O queue entry for disk
+ mov 2(r1),mq / put physical block number in mq
+ mov $12.,div / divide physical block number by 12.
+ mov $rkda+2,r3 /
+ mov ac,-(sp) / put remainder from divide on stack; gives
+ / sector number
+ mov $4,lsh / shift quotient 4 bits, to align with cyl and surf
+ / bits in rkda
+ bis mq,(sp) / or mq with sector; gives total disk address
+ br 3f
+prf: / drum
+ bit $1,active / test drum busy bit
+ bne 2f / branch if bit is set
+ bis $1,active / set drum busy bit
+ mov r1,rfap / rfap points to current I/O queue entry for drum
+ mov $dae+2,r3
+ clr -(sp)
+ movb 2(r1),1(sp) / move low byte of physical block number into
+ / high byte of stack
+ clr -(sp) / word
+ movb 3(r1),(sp) / move high byte of physical block number into
+ / low byte of stack
+ mov (sp)+,-(r3) / load dae with high byte of physical block
+ / number
+3:
+ mov (sp)+,-(r3) / load rkda register; load dar register
+ mov 6(r1),-(r3) / load bus address register
+ mov 4(r1),-(r3) / load word count register
+ mov $103,-(sp) / 103 indicates write operation when loaded
+ / in csr
+ bit $2000,(r1) / if bit 10 of word 1 of I/O queue entry is
+ / a one
+ beq 3f / then read operation is indicated
+ mov $105,(sp) / 105 indicates read operation
+3:
+ mov (sp)+,-(r3) / load csr with interrupt enabled, command, go
+ br seta
+ptc: / tape I/O
+ bit $4,active
+ bne 2f
+ mov tccm,r3
+ swab r3
+ bic $!7,r3
+ add $2,r3
+ cmpb r3,(r1)
+ beq 3f
+ movb $1,tccm / stop transport if not same unit
+3:
+ bis $4,active
+ mov r1,tcap
+ mov $20.,tcerrc
+ mov $tape1,tcstate
+ movb (r1),r3 / device
+ sub $2,r3 / now unit
+ swab r3
+ bis $103,r3 / now rbn,for,unit,ie
+ mov r3,tccm
+ seta: / I/O queue bookkeeping; set read/write waiting bits.
+ mov (r1),r3 / move word 1 of I/O queue entry into r3
+ bic $!3000,r3 / clear all bits except 9 and 10
+ bic $3000,(r1) / clear only bits 9 and 10
+ rol r3
+ rol r3
+ rol r3
+ bis r3,(r1) / or old value of bits 9 and 10 with bits 12
+ / and 13
+2:
+ cmp r2,$bufp / test to see if entire I/O queue has been
+ / scanned
+ bhi 1b
+ mov (sp)+,r3
+ mov (sp)+,r2
+ mov (sp)+,r1
+ rts r0
+
+bufaloc:
+ mov r2,-(sp) / save r2 on stack
+ mov $340,*$ps / set processor priority to 7
+1:
+ clr -(sp) / vacant buffer
+ mov $bufp,r2 / bufp contains pointers to I/O queue entrys
+ / in buffer area
+2:
+ mov (r2)+,r5 / move pointer to word 1 of an I/O queue entry
+ / into r5
+ bit $173000,(r5) / lock+keep+active+outstanding
+ bne 3f / branch when any of bits 9,10,12,13,14,15 are set
+ / (i.e., buffer busy)
+ mov r2,(sp) / save pointer to last non-busy buffer found
+ / points to word 2 of I/O queue entry)
+3:
+ cmpb (r5),cdev / is device in I/O queue entry same as current
+ / device
+ bne 3f
+ cmp 2(r5),r1 / is block number in I/O queue entry, same as
+ / current block number
+ bne 3f
+ tst (sp)+ / bump stack pointer
+ br 1f / use this buffer
+3:
+ cmp r2,$bufp+nbuf+nbuf
+ blo 2b / go to 2b if r2 less than bufp+nbuf+nbuf (all
+ / buffers not checked)
+ mov (sp)+,r2 / once all bufs are examined move pointer to
+ / last free block
+ bne 2f / if (sp) is non zero, i.e., if a free buffer is
+ / found branch to 2f
+ jsr r0,idle; s.wait+2 / idle if no free buffers
+ br 1b
+2:
+ tst (r0)+ / skip if warmed over buffer
+1:
+ mov -(r2),r5 / put pointer to word 1 of I/O queue entry in r5
+ movb cdev,(r5) / put current device number in I/O queue entry
+ mov r1,2(r5) / move block number into word 2 of I/O queue
+/ entry
+1:
+ cmp r2,$bufp / bump all entrys in bufp and put latest assigned
+ blos 1f / buffer on the top (this makes if the lowest priority)
+ mov -(r2),2(r2) / job for a particular device
+ br 1b
+1:
+ mov r5,(r2)
+ mov (sp)+,r2 / restore r2
+ rts r0
+
+tape: / dec tape interrupt
+ jsr r0,setisp / save registers and clockp on stack
+ mov tcstate,r3 / put state of dec tape in r3
+ jsr r0,trapt; tccm; tcap; 4 / busy bit
+ mov r3,pc / device control status register
+ / if no errors, go to device state (an address)
+
+taper: / dec tape error
+ dec tcerrc / decrement the number of errors
+ bne 1f / if more than 1 branch
+ movb 1(r2),r3 / r2+1 points to command register upper byte
+ bic $!7,r3 / clear all but bits 8-10 (Unit Selection)
+ incb deverr+2(r3) / set error bit for this tape unit
+ br tape3
+1: / more than 1 error
+ bit $4000,(r2) / direction of tape
+ beq 1f / if forward go to 1f
+ bic $4000,(r2) / reverse, set to forward
+ mov $tape1,tcstate / put tape 1 in the state
+ br 0f
+1: / put tape in reverse
+ bis $4000,(r2) / set tape to reverse direction
+ mov $tape2,tcstate / put tape 2 as the state
+0:
+ bis $4,active / check active bit of tape
+ movb $103,(r2) / set read function and interrupt enable
+ br 4f / go to retisp
+tape1: / read bn forward
+ mov $tcdt,r0 / move address of data register to r0
+ cmp (r0),2(r1) / compare block addresses
+ blt 0b / if lt, keep moving
+ bgt taper / if gt, reverse
+ mov 6(r1),-(r0) / put bus address in tcba
+ mov 4(r1),-(r0) / put word count in tcwc
+ mov $115,-(sp) / put end interrupt enable
+ bit $20000,(r1) / is "waiting to read bit" of I/O queue set?
+ beq 1f / no, 1f
+ mov $105,(sp) / yes, put and interrupt enable
+1:
+ movb (sp)+,(r2) / move function into command register (tccm)
+ bis $4,active / set active bit
+ mov $tape3,tcstate / get ready for I/O transfer
+ br 4f / go to retisp (rti)
+
+tape2: / read bn bakasswards
+ mov tcdt,r0 / r0 has contents of data register
+ add $3,r0 / overshoot
+ cmp r0,2(r1)
+ bgt 0b / if gt keep reading
+ br taper / else reverse
+
+tape3: / I/O transfer
+ bic $30000,(r1) / clear bits 12 and 13 of I/O queue entry
+ jsr r0,poke / do the I/O
+ bit $4,active / still busy see if pick up r-ahead, w-behind
+ bne 1f / yes
+ movb $1,(r2) / no, indicate too bad
+1:
+ jsr r0,wakeup; runq; 31. / wait up
+ br 4f / retisp
+
+drum: / interrupt handler
+ jsr r0,setisp / save r1,r2,r3, and clockp on the stack
+ jsr r0,trapt; dcs; rfap; 1 / check for stray interrupt or
+ / error
+ br 3f / no, error
+ br 2f / error
+
+disk:
+ jsr r0,setisp / save r1,r2,r3, and clockp on the stack
+ jmp *$0f
+0:
+ jsr r0,trapt; rkcs; rkap; 2
+ br 3f / no, errors
+ mov $115,(r2) / drive reset, errbit was set
+ mov $1f,0b-2 / next time jmp *$0f is executed jmp will be
+ / to 1f
+ br 4f
+1:
+ bit $20000,rkcs
+ beq 4f / wait for seek complete
+ mov $0b,0b-2
+ mov rkap,r1
+2:
+ bit $3000,(r1) / are bits 9 or 10 set in the 1st word of
+ / the disk buffer
+ bne 3f / no, branch ignore error if outstanding
+ inc r1
+ asr (r1)
+ asr (r1)
+ asr (r1) / reissue request
+ dec r1
+3:
+ bic $30000,(r1) / clear bits 12 and 13 in 1st word of buffer
+ mov ac,-(sp)
+ mov mq,-(sp) / put these on the stack
+ mov sc,-(sp)
+ jsr r0,poke
+ mov (sp)+,sc
+ mov (sp)+,mq / pop them off stack
+ mov (sp)+,ac
+4:
+ jmp retisp / u4-3
+
+trapt: / r2 points to the
+ mov (r0)+,r2 / device control register
+ mov *(r0)+,r1 / transaction pointer points to buffer
+ tst (sp)+
+ tstb (r2) / is ready bit of dcs set?
+ bge 4b / device still active so branch
+ bit (r0),active / was device busy?
+ beq 4b / no, stray interrupt
+ bic (r0)+,active / yes, set active to zero
+ tst (r2) / test the err(bit is) of dcs
+ bge 2f / if no error jump to 2f
+ tst (r0)+ / skip on error
+ 2:
+ jmp (r0)
--- /dev/null
+/ u9 -- unix
+
+trcv:
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+1:
+ mov r1,-(sp)
+ mov r2,-(sp)
+ mov r3,-(sp)
+ mov clockp,-(sp)
+ mov $s.syst+2,clockp
+ sub $trcv+4,r0 / 0%4 / calculate offset for tty causing
+ asl r0 / 0%8 / this interrupt
+ mov rcsr(r0),r2
+ mov rcbr(r0),r1
+ tst r2
+ blt 1f / error
+ tst tty+6(r0)
+ beq 1f
+ bit $40,r2 / parity
+ bne 3f / branch if set
+ tstb tty+4(r0)
+ blt 4f / 37 parity not allowed
+ br 2f
+3:
+ bitb $100,tty+4(r0)
+ beq 2f / non-37 parity not allowed
+4:
+ bic $!177,r1
+ bit $40,tty+4(r0)
+ bne 3f / raw
+ cmp r1,$177
+ beq 5f
+ cmp r1,$34
+ bne 3f
+5:
+ mov tty+6(r0),r0
+ beq 2f
+ movb r1,6(r0) / interrupt or quit
+ jsr r0,wakeall
+ br 2f
+3:
+ cmp r1,$15 / or
+ bne 3f
+ bit $20,tty+4(r0)
+ beq 3f
+ mov $12,r1
+3:
+ bitb $4,tty+4(r0)
+ beq 3f
+ cmp r1,$'A
+ blo 3f
+ cmp r1,$'Z
+ bhi 3f
+ add $40,r1
+3:
+ movb tty+3(r0),0f
+ jsr r0,putc; 0:.. / put char on input clist
+ br 2f
+ bitb $10,tty+4(r0) / echo
+ bne 4f / branch echo bit set
+ cmp r1,$12
+ bne 3f
+ bitb $20,tty+4(r0) / cr
+ beq 3f
+4:
+ cmp r1,$4 / is char input an eot
+ beq 1f
+ mov r1,-(sp) / put char on stack
+ movb tty+3(r0),0f
+ inc 0f
+ jsr r0,putc; 0:.. / put char just input on output clist
+ br .+2
+ jsr r0,starxmt
+ mov (sp)+,r1
+3:
+ bitb $40,tty+4(r0) / raw
+ bne 1f / branch if raw bit set
+ cmp r1,$12
+ beq 1f
+ movb tty+3(r0),r1
+ cmpb cc(r1),$15.
+ blo 2f
+1:
+ movb tty+3(r0),0f
+ jsr r0,wakeup; runq; 0:.. / call wakeup for process
+2:
+ jmp retisp
+txmt:
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+ jsr r0,1f
+1:
+ mov r1,-(sp)
+ mov r2,-(sp)
+ mov r3,-(sp)
+ mov clockp,-(sp)
+ mov $s.syst+2,clockp
+ sub $txmt+4,r0 / 0%4 / offset in cc
+ asl r0 / 0%8
+ jsr r0,starxmt
+ jmp retisp
+
+xmtto:
+ mov r0,-(sp)
+ mov 2(sp),r0 / 0%2+6
+ sub $6,r0
+ asl r0
+ asl r0 / 0%8
+ jsr r0,starxmt
+ mov (sp)+,r0
+ rts r0
+
+starxmt:
+ mov (sp),r1 / 0%8 r1 contains 8xtty number
+ movb tty+3(r1),r1 / place contents of 4th byte of "tty"
+ / buf in r1 (cc,cf,cl offset)
+ cmpb cc+1(r1),$10. / is char count for tty output greater
+ / than or equal to 10
+ bhi 1f / yes
+ mov r1,0f / no, make offset an arg of "wakeup"
+ inc 0f / increment arg of wakeup
+ jsr r0,wakeup; runq+2; 0:.. / wakeup process identified
+ / by wlist
+1: / entry specified by argument in 0:
+ mov (sp),r1 / 0%8 / r1 contains tty number
+ asr r1
+ asr r1
+ asr r1 / 0%1 r1 contains tty number
+ tstb toutt+3(r1) / is tout entry for tty output = 0
+ bne 1f / no, return to calling routine
+ mov (sp),r2 / yes, place (8xtty number) into r2
+ tstb tcsr(r2) / does tty's tcsr register = 0 (is ready
+ / bit = 0)
+ bge 1f / yes, return to calling routine
+ movb tty+2(r2),r1 / no, place third byte of "tty" buf
+ / into r1 (char left over after lf)
+ clrb tty+2(r2) / clear third byte
+ tst r1 / is third byte = 0
+ bne 3f / no, r1 contains a non nul character
+ movb tty+3(r2),0f / yes, make byte 4 arg of "getc"
+ inc 0f / increment arg to make it tty output list of
+ / clist
+ jsr r0,getc; 0:.. / obtain next character in clist for tty
+ / out and place in r1
+ br 1f / if no entry in clist to be output, return to
+ / calling routine
+3:
+ bic $!177,r1 / zero out bits 7-15 of r1
+ movb partab(r1),r3 / move "partab" entry (identified by
+ / r1) into r3
+ bge 3f / if entry is greater than or equal to 0 (digit
+ / 2, far left digit = 0) branch
+ bisb 200,r1 / if entry is less than 0 add 128 to ASCII
+ / code for char to be output
+ bic $!177,r3 / to make it teletype code and then clear
+ / bits 7-15 of r3
+
+3:
+ mov (sp),r2 / r2 contains 8xtty number
+ bit $4,rcsr(r2) / is carrier present for tty
+ beq starxmt / no carrier flush
+ mov r1,-(sp) / yes, place character to be output on stack
+ cmp r1,$11 / is character "ht"
+ bne 3f / no
+ bitb $2,tty+4(r2) / is tab to space flag for tty set
+ / (bit 1 of byte 5 in "tty" buffer area)
+ beq 3f / no
+ mov $240,(sp) / yes, change character to space
+3:
+ mov (sp)+,tcbr(r2) / place char to be output in tty output
+ / buffer
+ add $tty+1,r2 / place addr of 2nd byte of "tty" buf
+ jmp 1f-2(r3) / area in r2 (which is the column count) and
+ / then
+ incb (r2) / normal / jmp to location determined by digits
+ / 0 and 1 of character's entry in "partab" which
+ / is now in r3
+1: rts r0 / non-printing
+ br 1f / bs
+ br 2f / nl (line feed)
+ br 3f / tab (horizontal tab)
+ br 4f / vert (vertical tab)
+ br 5f / cr
+
+1:
+ decb (r2) / col decrement column count in byte 2 of "tty"
+ / area
+ bge 1f / if count >=0 return to calling routine
+ clrb (r2) / col set column count = 0
+ br 1f
+2:
+ bit $1,r1 / is bit 0 of ASCII char = 1 (char = lf)
+ bne 2f / yes
+ bitb $20,3(r2) / cr flag is bit 4 of 5th byte of "tty"
+ / area = 1
+ beq 2f / no (only lf to be handled)
+ movb $15,1(r2) / place "cr" in 3rd byte of "tty" area
+ / (character leftover after "lf" )
+2:
+ movb (r2),r3 / place present column count in r3
+ beq 1f / return to calling routine if count = 0
+ clrb (r2) / col clear column count
+ asr r3
+ asr r3
+ asr r3
+ asr r3 / delay = col/16
+ add $3,r3 / start to determine tout entry for tty output
+ br 2f
+3:
+ bitb $2,3(r2) / is bit 1 of 5th byte of "tty" area = 1
+ / (tab to space bit set)
+ beq 3f / no
+ incb (r2) / increment column count
+ bitb $7,(r2) / are bits 0, 1 and 2 set at col 0%8
+ beq 1f / no
+ movb $11,1(r2) / yes, place ht in another tab next time
+ br 1f / 3rd byte of tty area (character left over after
+ / "lf")
+3:
+ movb (r2),r3 / place column count in r3
+ bisb $7,(r2) / make bits 0, 1 and 2 of column count = 1
+ incb (r2) / increment column count
+ bis $!7,r3 / clear bits 3-15 of r3
+ neg r3 / delay = dcol start to determine tout entry for
+ / tty out
+ br 2f / by neg r3
+4:
+ mov $176.,r3 / delay = lots start to determine tout entry
+ br 2f
+5:
+ mov $10.,r3 / cr delay 160ms for tn300 start to determine
+ / tout
+ clrb (r2) / set column count = 0 entry
+2:
+ add $5,r3 / time for this char,increment value for tout
+ / entry by 5
+ mov (sp),r2 / 0%8 r2 contains 8xtty number
+ asr r2
+ asr r2
+ asr r2 / 0%1 r2 contains tty number
+ movb r3,toutt+3(r2) / place value for tout entry into tout
+ / table
+1:
+ rts r0 / return
+
+partab: / contains 3 digits for each character; digit 2 is used
+ / to determine if 200 is to added to ASCII code digits 0
+ / and 1 are used to determine value for jump table.
+ .byte 002,202,202,002,202,002,002,202
+ .byte 204,010,006,212,012,214,202,002
+ .byte 202,002,002,202,002,202,202,002
+ .byte 002,202,202,002,202,002,002,202
+ .byte 200,000,000,200,000,200,200,000
+ .byte 000,200,200,000,200,000,000,200
+ .byte 000,200,200,000,200,000,000,200
+ .byte 200,000,000,200,000,200,200,000
+ .byte 200,000,000,200,000,200,200,000
+ .byte 000,200,200,000,200,000,000,200
+ .byte 000,200,200,000,200,000,000,200
+ .byte 200,000,000,200,000,200,200,000
+ .byte 000,200,200,000,200,000,000,200
+ .byte 200,000,000,200,000,200,200,000
+ .byte 200,000,000,200,000,200,200,000
+ .byte 000,200,200,000,200,000,000,202
+
+xmtt:
+ jsr r0,cpass / get next character from user buffer area
+ tst r1 / is character nul
+ beq xmtt / yes, get next character
+1:
+ mov $240,*$ps / set processor priority equal to 5
+ mov (sp),r2 / r2 contains i node number of file
+ asl r2 / 0%2+28 / multlply inode number by 2
+ sub $21.,r2 / 0%2+7 / subtract 21 from 2x inumber to
+ / get cc, cf, cl offset
+ mov r2,0f / make offset arg of putc
+ cmpb cc(r2),$50. / is char count for device greater than
+ / or equal to 50
+ bhis 2f / yes
+ jsr r0,putc; 0:.. / find location in freelist to assign to
+ / device and
+ br 2f / place char in list, if none available branch
+ / to put process to sleep
+ mov r0,-(sp) / place calling routines return address on
+ / stack
+ mov 0b,r0 / place offset into cc, cl and cf tables in r0
+ sub $7,r0 / subtract seven from offset
+ asl r0 / multiply by 2
+ asl r0 / 0%8 / multiply by 2 (r0 contains 8xtty number)
+ jsr r0,starxmt / attempt to output character
+ mov (sp)+,r0 / pop stack
+ br xmtt / get next character
+2:
+ mov r1,-(sp) / place character on stack
+ mov 0b,0f / make offset into cc, cf, cl table arg of
+ / sleep (identifies location in wlist)
+ jsr r0,sleep; 0:.. / put process to sleep
+ mov (sp)+,r1 / remove character from stack
+ br 1b / try again
+
+rcvt: / read tty
+ sub $28.,r1 / 0%2 r1 contains 2xtty number
+ asl r1
+ asl r1 / r1 contains 8xtty number
+ mov r1,-(sp)
+ mov tty+6(r1),r5 / r5 contains address of 4th word in
+ / tty area
+ tst 2(r5) / is char count = 0
+ bne 1f / no
+ bitb $40,tty+4(r1) / raw flag set?
+ beq 2f / no
+ tst -(sp) / yes, decrement sp
+ jsr r0,rcvch / get character from clist
+ tst (sp)+ / increment sp
+ mov (sp)+,r2 / r2 contains 8xtty number
+ bitb $4,rcsr(r2) / is carrier detect bit on
+ beq 3f / no
+ jsr r0,passc / yes, place character in users buffer area
+3:
+ jmp ret
+2:
+ jsr r0,canon; rcvch / process a line of characters in
+ / clist and place results in tty buffer
+ / area
+1:
+ tst (sp)+ / increment sp
+1:
+ tst 2(r5) / is char count for tty buffer = 0
+ beq 1f / yes
+ movb *4(r5),r1 / no, move character pointer to r1
+ inc 4(r5) / increment character pointer
+ dec 2(r5) / decrement character count
+ jsr r0,passc / place character, whose address is in
+ / r1, in
+ br 1b / user buffer area. Then get next character.
+1:
+ jmp ret
+
+rcvch:
+ mov 4(sp),r2 / 0%8 r2 contains 8xtty number
+ mov $4,r1
+ bit r1,rcsr(r2) / is carrier detection bit on
+ bne 1f / yes
+ bic $1,rcsr(r2) / no, clear data terminal ready bit
+ rts r0
+1:
+ movb tty+3(r2),0f / make cc offset arg for "getc"
+ mov $240,*$ps / set processor priority = 5
+ jsr r0,getc; 0:.. / get next character off clist
+ br 2f / clist empty
+ clr *$ps / set processor priority = 0
+ rts r0
+2:
+ mov 0b,0f / make "getc" arg an arg for "sleep"
+ mov r5,-(sp) / save tty buffer address on stack
+ jsr r0,sleep; 0:..
+ mov (sp)+,r5
+ br rcvch
+
+ocvt:
+ sub $28.,r1 / 0%2 calculate tty table offset
+ mov r1 ,r2
+ asl r1 / 0%4
+ asl r1 / 0%8
+ mov r1,-(sp)
+ add $6,r2 / calculate clist id clist offset
+ movb r2,tty+3(r1) / put clist id in tty table
+1:
+ mov (sp),r1
+ bit $4,rcsr(r1) / carrier detect bit set
+ bne 1f / if so, branch
+ mov $511,rcsr(r1) / set ready, speed, interrupt enable,
+ / supervisor transmit
+ movb tty+3(r1),0f / put clist id in sleep argument
+ jsr r0,sleep; 0:..
+ br 1b
+1:
+ mov tty+6(r1),r5 / put tty buffer address in r5
+ tstb (r5) / first byte of tty buffer = 0
+ bne 1f / if not, branch
+ mov $511,rcsr(r1) / set control bits for receiver
+ mov $511,tcsr(r1) / set control bits for transmitter
+ movb $210,tty+4(r1) / put 210 in tty table word 3 / set flags
+1:
+ incb (r5) / inc first byte of tty buffer
+ tst (sp)+
+ tst u.ttyp / is there a process control tty
+ bne 1f / yes, then branch
+ mov r5,u.ttyp / no, make this tty the process control tty
+ br 1f / return
+
+ccvt:
+ sub $28.,r1
+ asl r1 / 0%4
+ asl r1
+ mov tty+6(r1),r5
+ decb (r5)
+1:
+ jmp sret
+
--- /dev/null
+/ ux -- unix
+
+systm:
+
+ .=.+2
+ .=.+128.
+ .=.+2
+ .=.+64.
+ s.time: .=.+4
+ s.syst: .=.+4
+ s.wait: .=.+4
+ s.idlet:.=.+4
+ s.chrgt:.=.+4
+ s.drerr:.=.+2
+inode:
+ i.flgs: .=.+2
+ i.nlks: .=.+1
+ i.uid: .=.+1
+ i.size: .=.+2
+ i.dskp: .=.+16.
+ i.ctim: .=.+4
+ i.mtim: .=.+4
+ . = inode+32.
+_mount: .=.+1024.
+proc:
+ p.pid: .=.+[2*nproc]
+ p.dska: .=.+[2*nproc]
+ p.ppid: .=.+[2*nproc]
+ p.break:.=.+[2*nproc]
+ p.link: .=.+nproc
+ p.stat: .=.+nproc
+tty:
+ . = .+[ntty*8.]
+fsp: .=.+[nfiles*8.]
+bufp: .=.+[nbuf*2]+6
+sb0: .=.+8
+sb1: .=.+8
+swp: .=.+8
+ii: .=.+2
+idev: .=.+2
+cdev: .=.+2
+deverr: .=.+12.
+active: .=.+2
+rfap: .=.+2
+rkap: .=.+2
+tcap: .=.+2
+tcstate:.=.+2
+tcerrc: .=.+2
+mnti: .=.+2
+mntd: .=.+2
+mpid: .=.+2
+clockp: .=.+2
+rootdir:.=.+2
+toutt: .=.+16.; touts: .=.+32.
+runq: .=.+6
+
+wlist: .=.+40.
+cc: .=.+30.
+cf: .=.+31.
+cl: .=.+31.
+clist: .=.+510.
+imod: .=.+1
+smod: .=.+1
+mmod: .=.+1
+uquant: .=.+1
+sysflg: .=.+1
+pptiflg:.=.+1
+ttyoch: .=.+1
+ .even
+ .=.+100.; sstack:
+buffer: .=.+[ntty*140.]
+ .=.+[nbuf*520.]
+
+ . = core-64.
+user:
+ u.sp: .=.+2
+ u.usp: .=.+2
+ u.r0: .=.+2
+ u.cdir: .=.+2
+ u.fp: .=.+10.
+ u.fofp: .=.+2
+ u.dirp: .=.+2
+ u.namep: .=.+2
+ u.off: .=.+2
+ u.base: .=.+2
+ u.count: .=.+2
+ u.nread: .=.+2
+ u.break: .=.+2
+ u.ttyp: .=.+2
+ u.dirbuf:.=.+10.
+ u.pri: .=.+2
+ u.intr: .=.+2
+ u.quit: .=.+2
+ u.emt: .=.+2
+ u.ilgins:.=.+2
+ u.cdev: .=.+2
+ u.uid: .=.+1
+ u.ruid: .=.+1
+ u.bsys: .=.+1
+ u.uno: .=.+1
+. = core
+