Interdata_v6/usr/source/boot/uboot.s
*
* Unix bootstrap loader
*
* N.B. Must be assembled with SQUEZ to make it relocatable
*
bootaddr equ y'20000' must be >top of loaded program
*
i.addr equ x'78' 10 console input address
i.cmd2 equ x'79' a3 console init cmd
d.addr equ x'7a' c7 disc address
* x'7b' unused
c.addr equ x'7c' b6 disc controller
s.addr equ x'7d' f0 selch address
os.ext equ x'7e' 0000 OS file extension (for LSU) or console def'n
*
LARGE equ 19 large file bit in inode flags
MAGIC equ x'107' a.out magic number
EOL equ x'0d' carriage return
PROMPT equ c'?'
PAUSE equ c'-' flag to go into wait state after loading
WAITPSW equ x'8000' wait-state psw
*
ret equ 15
ret1 equ 14
work equ 13
offset equ 12
count equ 11
bno equ 10
inode equ 09
char equ 08
cyl equ 07
sector equ 06
dev equ 05
disc equ 04
cntrl equ 03
selch equ 02
core equ 01
*
low equ * loaded into low core by LSU
org low+x'60'
b start(0,0)
org low+x'80'
*
start equ *
li 1,bootaddr relocation address
lis 2,0 start at low core
rloop lm 8,0(2) move 8 words
stm 8,0(1,2)
ahi 2,8*adc increment core address
cli 2,high all moved?
bl rloop no - continue
b go-low(1) execute relocated code
*
go equ *
lh work,os.ext OS file extension 0?
bz lsu yes - assume loaded by LSU
sth work,i.addr no - OS extension is really console def
lsu equ *
lm 14,i.addr save lowcore data
stm 14,lowsave
lb selch,s.addr
lb cntrl,c.addr
lb disc,d.addr
la work,buf set up disc read buffer addresses
st work,bufs
ahi work,511
st work,bufe
lis char,0
lhi count,names-ind+12
zeroout st char,ind(count) clear indirect blocks & filename
sis count,4
bnm zeroout
*
lhi char,PROMPT ask user for filename
bal ret1,putc
lis count,0
nxtchr1 bal ret,getc read a character from console
bz lookup returns 0 at end of line
chi char,PAUSE flag to pause after loading?
bne nopause no - continue
li work,WAITPSW set wait bit
st work,ps.start in start psw
b nxtchr1
nopause equ *
stb char,names(count) set in filename
ais count,1
b nxtchr1 note no test for overflow
*
lookup equ *
lis inode,1 read inode for root directory
bal ret,iget
nxtdblk bal ret1,rblk read directory block
bz start start over if end of directory
la count,buf
cmpnext lis offset,12
lh inode,0(count) directory entry used?
bz nextent no - look at next
nxtchr2 lh char,2(offset,count) compare names
clh char,names(offset)
bne nextent not equal - look at next entry
sis offset,2
bnm nxtchr2
b gotinod right name - go read it in
nextent ahi count,16 next directory entry
la work,buf+512
cr count,work
bl cmpnext
b nxtdblk
*
gotinod equ *
bal ret,iget read inode for file
lis core,0
nxtsblk st core,bufs read block into core
ai core,511
st core,bufe
bal ret1,rblk
bz reloc
ais core,1
b nxtsblk
*
reloc equ *
l char,x'0' check first word
clhi char,MAGIC a.out file?
bne finish no - done
lis count,0 yes - relocate to get rid of header
mvsys l char,32(count)
st char,0(count)
ais count,4
cr count,core
bl mvsys
finish equ *
lm 14,lowsave restore lowcore data
stm 14,i.addr
lpsw ps.start go to start address in loaded file
*
* Read inode and indirect blocks
*
iget equ *
ahi inode,15 find block containing inode
lr sector,inode
srls sector,3 (inode+15)/8
bal ret1,rblka read block
ni inode,7 find offset of inode in block
slls inode,6 (inode+15) mod 8
stm 6,regsave save work regs
lm 6,buf(inode) copy inode info from buffer
stm 6,inod (up to addr[7])
lm 6,regsave restore work regs
*
la bno,addr small file: block addresses in addr
li work,LARGE test for large file
tbt work,inod
bzr ret
la core,ind large file - read indirect blocks
nxtind bal ret1,rblk
bz finind
li count,508 move indirect block
mvind l char,buf(count)
st char,0(core,count)
sis count,4
bnm mvind
ahi core,512
b nxtind
finind la bno,ind large file: block addresses in ind
br ret
*
* Console read and write routines
*
getc equ *
lb dev,i.addr console input address
oc dev,i.cmd2 initialize
oc dev,t.read start terminal read
getwait ssr dev,work wait for busy == 0
bc getwait
rdr dev,char read char from terminal buffer
nhi char,x'7f' clear parity bit
clhi char,c'A' check for alpha
bl notran
clhi char,c'Z'
bp notran
ohi char,x'20' alpha - translate to lowercase
notran bal ret1,putc echo character back
clhi char,EOL end of line?
bner ret no - return (cond. code nonzero)
lr ret1,ret
lis char,x'0a' echo extra linefeed
*
putc equ *
lb dev,i.addr console output address
ais dev,1
oc dev,t.write start terminal writing
wdr dev,char write the character
putwait ssr dev,work wait for busy == 0
bc putwait
br ret1
*
* Read a disc block
*
rblk equ *
l sector,0(bno) next block number
bzr ret1
ais bno,4
rblka equ *
dh sector,f24 get cylinder address
slls sector,1 get sector address
clhi sector,24 correct head?
bl wselch1 yes - start read
ais sector,8 else set head 0
wselch1 ssr selch,work wait for selch busy == 0
btc s.busy,wselch1
wcntrl1 ssr cntrl,work check controller status
bfc c.idle,wcntrl1 wait for idle == 1
btc c.err,*
wdisc1 ssr disc,work check disc status
btc d.nrsrw,wdisc1 wait for no arm motion
btc d.err,*
whr disc,cyl cylinder address to disc
oc disc,d.seek start seek
wcntrl2 ssr cntrl,work sense controller status
bfc c.idle,wcntrl2 wait for idle == 1
wdisc2 ssr disc,work sense disc status
btc d.nrsrw,wdisc2 wait for no arm motion
btc d.err,*
oc selch,s.stop stop selch
wd selch,bufs+1 start address to selch
wh selch,bufs+2
wd selch,bufe+1 end address to selch
wh selch,bufe+2
whr disc,cyl cylinder to disc (again)
wdr cntrl,sector sector to controller
oc cntrl,c.read start controller reading
oc selch,s.read start selch reading
wselch2 ssr selch,work sense selch status
btc s.busy,wselch2 wait for busy == 0
oc selch,s.stop stop selch
wcntrl3 ssr cntrl,work check controller status
bfc c.idle,wcntrl3 wait for idle == 0
btc c.err,*
br ret1 (cond code must be nonzero)
*
s.busy equ 8 selector channel busy
c.idle equ 2 disc controller idle
c.err equ 5 disc controller error
d.nrsrw equ 8 disc not-ready-to-seek-read-or-write
d.err equ 7 disc error
*
align 8
ps.start dc 0,y'60' psw to start loaded program
f24 dc h'24' sectors per track
d.seek db x'c2' disarm+seek
c.read db x'01' read
s.stop db x'48' stop + extended address read
s.read db x'70' extended address read + read + go
t.write db x'a3'
t.read db x'a1'
align adc
high equ * highest location for relocate
*
bufs equ *
bufe equ bufs+4
lowsave equ bufe+4
regsave equ 8+lowsave
buf equ 10*adc+regsave
inod equ buf+512
mode equ inod
addr equ 3*adc+inod
ind equ 11*adc+inod
names equ 8*512+ind
end