Ultrix-3.1/sys/mdec/rauboot.s
/ SCCSID: @(#)rauboot.s 3.0 4/21/86
/
//////////////////////////////////////////////////////////////////////
/ Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. /
/ All Rights Reserved. /
/ Reference "/usr/src/COPYRIGHT" for applicable restrictions. /
//////////////////////////////////////////////////////////////////////
/
/ ULTRIX-11 Block Zero Bootstrap for MSCP Disks
/
/ UDA50 - RA60/RA80/RA81
/ RQDX1 - RX50/RD51/RD52
/ RC25 - RC25/RCF25
/
/ The a.out header must be stripped off (makefile does it).
/ Can boot from any unit.
/ On entry boot leaves:
/ r0 = unit #
/ r1 = aip register address
/
/ ****** MSCP BOOTSTRAP ANOMALIES ******
/
/ 2. On any data or initialization error, the boot will hang on a branch
/ self instruction instead of restarting the boot.
/ WHY - was it only RDRX and not UDA also, in old uboots?
/
/ ***************************************
/
/ Fred Canter
/
/ disk boot program to load and transfer
/ to a unix entry
/ ****** CONSTANTS FOR FILE SYSTEM LOGICAL BLOCK SIZE ******
/
/ For 512 byte logical blocks:
/ CLSIZE= 1, NDIRIN= 10., INOFF= 15., IGSHFT= -3, IGMASK1= !17777, IGMASK2= !7
/ For 1024 byte logical blocks:
/ CLSIZE= 2, NDIRIN= 4., INOFF= 31., IGSHFT= -4, IGMASK1= !7777, IGMASK2= !17
/
CLSIZE = 2. / Physical disk blocks per logical block (cluster)
CLSHFT = 1. / Shift to multiply by CLSIZE (doubles block number)
BSIZE = 512.*CLSIZE / Logical block size (512 or 1024 bytes)
INOSIZ = 64. / Size of an inode in bytes
NDIRIN = 4. / Number of direct inode addresses (10 or 4)
ADDROFF = 12. / Offset of first address in inode
INOPB = BSIZE\/INOSIZ / Number of inodes per logical block (8 or 16)
INOFF = 31. / Inode offset (INOPB * (SUPERB+1)) - 1 (15 or 31)
BC = 512.*CLSIZE / Byte count for disk transfers
IGSHFT = -4 / Adjust for NDIRIN in iget (-3 or -4)
IGMASK1 = !7777 / " " " " (!17777 or 7777)
IGMASK2 = !17 / " " " " (!7 or !17)
/
/ **********************************************************
nop = 240
s1 = 4000
go = 1
core = 28.
.. = [core*2048.]-512.
/ establish sp and check if running below
/ intended origin, if so, copy
/ program up to 'core' K words.
start:
nop / DEC boot block standard
br 1f / "
1:
mov $..,sp
clr r4
mov sp,r5
cmp pc,r5
bhis 2f
1:
mov (r4)+,(r5)+
cmp r5,$end
blo 1b
jmp (sp)
/ Clear core to make things clean,
/ has the pleasent side effect of initializing the MSCP
/ communications area and message packets to zero.
2:
clr (r4)+
cmp r4,sp
blo 2b
/ MSCP controller initialization
mov r0,bdunit / save unit # booted from
mov r1,udaip / save aip register address
clr (r1)+ / start uda init sequence
/ move pointer to udasa register
mov $s1,r5 / set uda state test bit to step 1
mov $1f,r4 / address of init seq table
br 2f / branch around table
1:
100000 / UDA_ERR, init step 1
ring / address of ringbase
0 / hi ringbase address
go / UDA go bit
2:
tst (r1) / error ?
bmi . / yes, hang - can't restart !!!
bit r5,(r1) / current step done ?
beq 2b / no
mov (r4)+,(r1) / yes, load next step info from table
asl r5 / change state test bit to next step
bpl 2b / if all steps not done, go back
/ r5 now = 100000, UDA_OWN bit
mov $36.,cmdhdr / command packet length
/ don't set response packet length,
/ little shakey but it works.
mov r0,udacmd+4. / load unit number
mov $11,udacmd+8. / on-line command opcode
mov $ring,r2 / initialize cmd/rsp ring
mov $udarsp,(r2)+ / address of response packet
mov r5,(r2)+ / set UDA owner
mov $udacmd,(r2)+ / address of command packet
mov r5,(r2)+ / set UDA owner
mov -2(r1),r0 / start UDA polling
3:
tst ring+2 / wait for response, UDA_OWN goes to zero
bmi 3b
/ Pass boot device type ID and unit number to Boot:
mov udarsp+28.,bdmtil / media type ID lo
mov udarsp+30.,bdmtih / media type ID hi
br rstrt1
rstart: / restart here if file not found
movb $'.,names+4 / change to boot.bu if boot can't be loaded
movb $'b,names+5
movb $'u,names+6
rstrt1:
mov $buf,r0 / clean up for restart
6:
clr (r0)+
cmp r0,sp
blo 6b
/ now start reading the inodes
/ starting at the root and
/ going through directories
mov $names,r1
mov $2,r0
1:
clr bno
jsr pc,iget
tstb (r1)
beq 1f
2:
jsr pc,rmblk
br rstart
mov $buf,r2
3:
mov r1,r3
mov r2,r4
add $16.,r2
tst (r4)+
beq 5f
4:
cmpb (r3)+,(r4)+
bne 5f
cmp r4,r2 /tstb (r3)
blo 4b /bne 4b
mov -16.(r2),r0
add $14.,r1
br 1b
5:
cmp r2,$buf+BSIZE
blo 3b
br 2b
/ read file into core until
/ a mapping error, (no disk address)
1:
clr r1
1:
jsr pc,rmblk
br 1f
mov $buf,r2
2:
mov (r2)+,(r1)+
cmp r2,$buf+BSIZE
blo 2b
br 1b
/ load boot device type info into r0 -> r4
/ relocate core around
/ assembler header
1:
mov bdunit,r0 / unit number
mov $2,r1 / boot device type code 2 = RA (MSCP)
mov bdmtil,r2 / media type ID
mov bdmtih,r3
mov udaip,r4 / MSCP controller CSR address
clr r5
/ cmp (r5),$407 / boot will always have the a.out header
/ bne 2f / but, it will not always be 0407!
1:
mov 20(r5),(r5)+
cmp r5,sp
blo 1b
/ enter program
2:
clr pc
/ get the inode specified in r0
iget:
add $INOFF,r0
mov r0,r5
ash $IGSHFT,r0
bic $IGMASK1,r0
mov r0,dno
clr r0
jsr pc,rblk
bic $IGMASK2,r5
mul $INOSIZ,r5
add $buf,r5
mov $inod,r4
1:
mov (r5)+,(r4)+
cmp r4,$inod+INOSIZ
blo 1b
rts pc
/ read a mapped block
/ offset in file is in bno.
/ skip if success, no skip if fail
/ the algorithm only handles a single
/ indirect block. that means that
/ files longer than NDIRIN+128 blocks cannot
/ be loaded.
rmblk:
add $2,(sp)
mov bno,r0
cmp r0,$NDIRIN
blt 1f
mov $NDIRIN,r0
1:
mov r0,-(sp)
asl r0
add (sp)+,r0
add $addr+1,r0
movb (r0)+,dno
movb (r0)+,dno+1
movb -3(r0),r0
bne 1f
tst dno
beq 2f
1:
jsr pc,rblk
mov bno,r0
inc bno
sub $NDIRIN,r0
blt 1f
ash $2,r0
mov buf+2(r0),dno
mov buf(r0),r0
bne rblk
tst dno
bne rblk
2:
sub $2,(sp)
1:
rts pc
/ MSCP DISK driver
/ low order address in dno,
/ high order address in r0
rblk:
mov r1,-(sp)
mov dno,r1
.if CLSIZE-1
ashc $CLSHFT,r0 / double blk number if 1K filsys
.endif
/ mov $36.,cmdhdr / length of command packet
mov $41,udacmd+8. / read opcode
mov $BC,udacmd+12. / byte count
mov $buf,udacmd+16. / buffer descriptor
mov r1,udacmd+28. / block number low
mov (sp)+,r1
mov r0,udacmd+30. / block number hi
mov $100000,ring+2 / set UDA owner of response
mov $100000,ring+6 / set UDA owner of command
mov *udaip,r0 / start UDA polling
1:
tst ring+2 / wait for response
bmi 1b
tstb udarsp+10. / does returned status = SUCCESS ?
beq 2f / yes, return
jmp rstart / no, error (try boot.bu)
2:
rts pc
/ . b u (try boot.bu if boot can't be loaded)
names: <boot\0\0\0\0\0\0\0\0\0\0\0>
end:
udaip = ..-256.-BSIZE
cmdint = udaip+2.
rspint = cmdint+2.
ring = rspint+2.
rsphdr = ring+8.
udarsp = rsphdr+4.
cmdhdr = udarsp+48.
udacmd = cmdhdr+4.
bdunit = udacmd+48.
bdmtil = bdunit+2.
bdmtih = bdmtil+2.
buf = bdmtih+2.
inod = buf+BSIZE
addr = inod+ADDROFF
bno = inod+INOSIZ
dno = bno+2.