|
|
DataMuseum.dkPresents historical artifacts from the history of: RC4000/8000/9000 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about RC4000/8000/9000 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 19200 (0x4b00)
Types: TextFile
Names: »tautoboot «
└─⟦9ccaf6601⟧ Bits:30008165 Bånd med SW8000 kildetekst/release værktøjer
└─⟦2ba378e4a⟧
└─⟦this⟧ »tautoboot «
autoboot=slang list.no xref.no
b.
m. autoboot 88.02.22 15.20.00
m. version 6
; bootloader, rc8000.
; autoload program for load from rc82xx disc, ida801 or fpa.
; the autoload from disc is performed in the following way:
; - the autoload bottom is pressed and released.
; the rc8000 cpu executes a general clear, inserts two channelcommands
; in the core store (an initialize and an input command), initializes
; the basis address of the controller (word 8) and starts the
; channelprogram on the device with io-device number 4 (the disc).
; - first command initiates the disc controller, positions to cylinder zero,
; head zero and sector zero.
; - second command inputs one segment (the bootloader) to first free core
; after the input command.
; - the segment now loaded must start with a continuation of the initial
; channelprogram, which normally consists of a stop command only.
;
; - in case the device 4 does not respond the start channelprogram command,
; the mikroprogram in the cpu now tries to autoload from device number
; 1, which is an IDA801 with a tapestation, but without discs.
; If no responce the mikroprogram tries to autoload from device number 2
; which is the fpa.
; This requires only reinitialisation of the basis address of the con-
; troller table. the channelprogram inserted in core is now started
; on the fpa.
; If device number 4 is a IDA801 controller and the load is from disc,
; the controller saves a coredump on disc 00( disc controller 0 , plug 0).
; Segment 0 on the disc holds information about the location af the
; monitor, the coredump area e.t.c. The dump is terminated by either
; - top of dumparea reached
; - top of core is reached
; - parity error .
; Following this the bootloader is loaded as specified by the address
; and the bytecount of the input command. The IDA801 controller is
; only able to respond on input commands ( 1<8 ); all other commands
; will cause the controller to halt.
;
; version 5: error causing break if memory = 12Mb has been corrected.
; version 5.1: KMD-ÅLB. load only 500 segments (p5);
; Problems with dcm801 and huge memory size.
; version 6: error in version 5. If core size = 12Mb the size would
; be set 192Kb too low.
;
; 89 01 16 7.45 kak max core address reduced to 8.37777772
b.a20,p10
; the channelprogram placed in core after activation of the autoload buttom
; has the format shown below. Part of this channelprogram area does also serve
; as device controller description and as standard status area. the format is:
;
; address contents channelprogram controller desc status area
;
; 8 12-iodev<3
; 10 6<8 initialize
; 12 10 dummy start of chpg
; 14 20 dummy start of st.area
; 16 1<8(256) input interrupt addr
; 18 22 first addr interrupt number
; 20 768 blocklength chpg addr
; 22 word0 ... rem. char. count
; 24 word1 ... curr. status
; 26 word2 ... event status
; 28 word3 ...
; 30 ... ...
; word0,1,2 are the beginning of the first segment loaded. they do at load time
; contain the channelcommand:
; word0 15<8 stop
; word1 .. dummy
; word2 .. dummy
; word3 .. ....
a1 =8.60<1 ; display register
a2 =8.17<1 ; coresize register
a3 =8.57<1 ; interrupt register
a4 =4 ; device number of disc
a5 =2 ; device number of fpa
a6 =8 ; basis of controller table
a7 =12 ; start of controller description
a8 =10 ; start of channelprogram
a9 =20 ; start of standard status area
a10=22 ; first free address after autoload channel program
a11=256 ; interrupt address (contents of word(16))
a12=22 ; interrupt number (contents of word(18))
; user defined parameters:
p0 =+8 ; first sector of monitor area
p1 =+840 ; first sector of coredump area, if p1<0 then no coredump
p2 =21 ; number of sectors per track (head)
p3 =168 ; max size, dumping the core (in segments)
; = max size, loading the monitor + p4 (in segments)
p4 =1024 ; load address of monitor
p5= 500 ; max size loading the monitor (5.1 testversion)
; when loading from fixed media disc with fixed head part, then use
; p0=4+1008, p1=840+1008
; else use
; p0=4 , p1=840
\f
s.b50,m6,n6 w.
k=a10
; channelcommands continuing the init autoload channelprogram:
b0: 15<8 ; stop
0 ; dummy
0 ; dummy
; the following four words are intended for automatic startup area name
; default is: manual startup!
;
; these four words are known(!) by absolute core-address in moncatinit
; they are also known by the 'install'-program!
0, r.4 ; startup name
; device address:
b3: 1<23+a4<3 ; device address of loaddevice
b5: 01 ; +1: load flag: IDA801load: 2, discload: 1, fpaload: 0
; +0: coredump flag: <> 0 parity error, no coredump
b6: 8.77777000 ;
\f
; channelprogram for fpaload of monitor.
b10: 3<8 ; output
b15 ; addr of status byte
1 ; size:=1 char
b11: 1<8+1<7 ; input and continue
b16 ; addr of start byte
1 ; size:=1 char
b12: 1<8 ; input
b13: p4 ; start addr (init: load addr(monitor))
768 ; size:=1 segment
b14: 15<8 ; stop
; dummy
; dummy
b15: 0<16 ; status byte<16:=transfer next block
b16: 0 ; start byte<16
b17: p4 ; top of last loaded segment
b18: 255<16 ; status byte<16:=stop transfer
\f
; channelprogram for discload of monitor:
b20: 2<8 ; seek
b30 ; addr of seek information
6 ; number of chars
b21: 1<8+1 ; input address mark
b35 ; addr mark area
12 ; read one addr mark
b22: 15<8 ; stop
; dummy
; dummy
; position area.
b30: 0<8+0 ; cylinder0, head0
(:p2-1:)<16+0 ; last sector, empty flag
; input area for addr marks.
b35=b10 ; b10: 0,0 ; addr mark area(curr)
b36=b35+4 ; b10+4: 0,0 ; addr mark area(next)
; format of disc.
b31: 0 ; segments per cylinder
b32: p2 ; segments per track
b33: 0 ; screw
b38: p3*768 ; max transfer size
b41: p5*512 ; max load size
; channelprogram used to initialize the
; first 4 words of core
b39: 0<8 ; sense
0 ; addr:= core(0);
12 ; number of chars
b40: 15<8 ; stop
; dummy
; dummy
\f
; discload.
b.i4,j6 w.
m2: al w0 b20 ; discload from RC82XX:
rs w0 a7+0 ; start(chpg):=start(discloadpg);
j0: al w2 b22+6 ; next head:
jl w3 n0 ; execute chpg(top(discchpg));
jl -16 ; error: sysfault(16);
al w0 1 ; ok:
ba w0 b30+1 ;
hs w0 b30+1 ; head:=head+1;
rl w3 b36+0 ;
sh w3 1<8-1 ; if cylinder(next)>0 then
jl j0 ; goto next head;
wm w0 b32 ;
rs w0 b31 ; segments per cylinder:=head*segments per track;
bz w0 b36+2 ;
ls w0 -4 ;
rs w0 b33 ; screw:=sector(next);
;
c.p1
zl w0 b5 ; if no parity error then dump core
se w0 0 ;
jl j1 ;
rl w1 b38 ; load length:=max load length;
al w0 3<8 ;
rs w0 b21+0 ; command:=write;
al w0 0 ; first:=0 (=first byte of core);
ds w1 b21+4 ; size:=load length;
rl w2 i0 ;
jl w3 n1 ; set position(first sector coredump area);
al w2 b22+6 ;
jl w3 n0 ; execute chpg(top(discpg));
am 0 ; ignore the answer
z. ;
m3:
j1: al w0 1<8 ; load monitor:
rs w0 b21+0 ; command:=read;
al w0 p4 ; first:=load addr(monitor);
gg w1 a2 ; load size:
sl w1 (b41) ; min(loadsize, coresize)
rl w1 b41 ;
la w1 b6 ; only transfer full segments
al w2 x1 ;
ls w2 -1 ;
wa w1 4 ;
ds w1 b21+4 ;
rl w2 i1 ;
jl w3 n1 ; set position(first sector of monitor area);
al w2 b22+6 ;
jl w3 n0 ; execute chpg(top(chpg));
jl -64 ; error: sysfault(64);
; ok:
jl m5 ; goto finis;
i0: p1 ;
i1: p0 ;
e. ; end of discload;
\f
; fpaload.
b.i10,j10 w.
m4: ; fpaload
al w0 b10 ; start(chpg):=start(fpaloadpg);
rs w0 a7+0 ;
al w0 0 ;
hs w0 b5+1 ; load flag:=load from fpa;
j0: al w2 b14+6 ; next:
jl w3 n0 ; execute chpg(top(chpg));
jl -4 ; error: sysfault(4);
; ok:
al w1 512 ;
wa w1 b13 ;
rs w1 b13 ; first addr:=first addr+512;
rl w2 b17 ;
j2: sl w2 x1 ; check next:
jl j0 ; if block top>=top transferred then
rl w3 x2 ; goto next;
wa w2 x2 ; size:=word(block top);
rs w2 b17 ; block top:=block top+size;
se w3 0 ; if size<>0 then
jl j2 ; goto check next;
rl w0 b18 ; end:
rs w0 b15 ; status byte:=stop transfer;
rl w0 b14 ;
rs w0 b11 ; insert stopcommand in second command;
al w2 b11+6 ;
jl w3 n0 ; execute chpg(top(chpg);
jl -8 ; error: sysfault(8);
; ok:
jl m5 ; goto finis;
e.
\f
0, r.(:a11-k:)/2+1 ; fill up
0 ; a11: interrupt word
m1: ; load from ida801:
al w0 b21 ; start(chpg) = start(input command)
rs w0 a7+0 ; goto load monitor
jl m3 ;
; start load.
; this block is entered right after load of bootloader.
b.i4,j10 w.
m0: rl w0 a11 ; start load:
se w0 a12 ; wait interrupt;
jl m0 ;
dl w1 a9+2 ; check status:
dl w3 a9+6 ;
se w0 768 ; if status area(0) = channelpgm(5) then
jl j8 ; begin
al w0 2 ;
hs w0 b5+1 ; load type = IDA801
jl j9 ; end
; else
j8: sn w0 b0+6 ; if next chpg command<>top(init chpg)
sl w1 1 ;sew1 0; or rem char count<>0
jl -2 ; or curr status(bit0)<>0
sl w2 0 ; or event status<>0 then
sz w3 (i0);sew3 0; sysfault(2);
jl -2 ;
j9: al w1 0 ;
rl w0 b7 ;
; find core size: do until timeout
j0: wa w1 i1 ; addr = addr +I1
sz w1 (i3) ; if upper limit core then
jl j1 ; max adress to max core register
di w3 x1 ; w3 = (addr)
sx 2.010 ; end
jl j2 ;
sx 2.101 ; if memory parity error (NACK (23))
hs w0 b5 ; or bus parity error (PARITY (21))
jl j0 ; then clear coredump flag
j1: rl w1 i2 ; core size := max
j2: al w1 x1-2 ;
do w0 x1+2 ; for addr = addr step -2 until found do
di w3 x1+2 ; (addr+2) = pattern
sx 2.111 ; w3 = (addr-2)
jl j2 ; if w3 = pattern and no exception then
se w3 (0) ; found = true
jl j2 ; end
gp w1 a2 ; coresize = max address
zl w0 b5 ; if not coredump flag then
al w2 b1 ; clear all core
sn w0 0 ; else
rl w2 b41 ; clear top of core
jl w3 n2 ;
al w0 a7 ; loaddevice = a7 -(contr. base)
ws w0 a6 ;
hs w0 b3+1 ;
zl w0 b5+1 ; if load type = IDA801 then goto idaload
sn w0 2 ;
jl m1 ;
al w0 b39 ; start channelprogram used to initialize the
rs w0 a7+0 ; first four words of core memory
al w2 b40+6 ;
jl w3 n0 ;
am 0 ; ignore the answer
rl w0 a6 ; if device number = 4 then
sn w0 a7-a4<3 ;
jl m2 ; goto discload
jl m4 ; else goto fpaload;
i0: -1-1<23>4 ; status bit4 (blocklength error)
i1: 64<10 ; core module:=64 k words
i2: 8.37777772 ; max core address
i3: 1<23 ; address bit
e.
\f
; finis.
b.j1 w.
m5: ; finis:
al w1 7 ;
j0: al w1 x1-1 ; clear interrupts(0:6);
gp w1 a3 ;
se w1 0 ;
jl j0 ;
zl w0 b5+1 ; enter monitor:
rs w0 p4+2 ; insert loadflag in monitor;
jl p4+6 ; enter monitor in +6;
e.
\f
; execute chpg.
; the procedure starts the channelprogram on the device defined in b3,
; awaits an interrupt for a certain time given by the 'max delay'.
; If not load from IDA801, the procedure
; checks the status delivered in the std status area,
; and returns.
; the procedure return to
; link+0 in case of errors (w0 = error cause)
; link+2 in case of normal termination.
; error cause
; 1 exception when starting the channelprogram
; 2 timeout in waiting for the interrupt
; 3 statuserror, which means
; top(chpg)<>awaited value
; remaining character count<>0
; current status(bit0)<>0
; event status<>0
;
; call return
; w0 - destroyed or error cause
; w1 - destroyed
; w2 top(chpg) destroyed
; w3 link unchanged
b.i4,j4 w.
n0: rs w2 i1 ; execute chpg: save chpg top;
al w1 -1 ;
al w2 -1 ;
rs w2 a11 ; interrupt word:=-1;
ds w2 a9+2 ;
ds w2 a9+6 ; std status area:=-1,-1,-1,-1;
al w0 1 ; 1 == start command for ifp
do (b3) ; start chpg;
sx 2.111 ; if ex<>2.000 then
jl j1 ; goto error1;
al w1 0 ; unit:=time of loop (appr. 12.5 microsec);
j0: al w1 x1+1 ; for time:=unit step unit until max delay do
sn w1 (i0) ; if interrupt then
jl j2 ; goto after interrupt;
sn w2 (a11) ; time expired:
jl j0 ; return to error2;
zl w0 b5+1 ; after interrupt:
sn w0 2 ; if load from IDA801 then
jl x3+2 ; return ok else
dl w1 a9+2 ; RC82XX:
sn w0 (i1) ; if next chpg command<>top(chpg)
se w1 0 ; or rem char count<>0
jl j3 ; or curr status(bit0)<>0
dl w1 a9+6 ; or event status<>0 then
sl w0 0 ; goto error3;
se w1 0 ;
jl j3 ;
jl x3+2 ; ok: return to link+2;
j1: am 1-2 ; error1: errorcause:=1;
j2: am 2-3 ; error2: errorcause:=2;
j3: al w0 3 ; error3: errorcause:=3;
jl x3+0 ; return to link;
i0: 80000000 ; delay: apr. 400 sek
i1: 0 ; top(chpg)
e.
; procedure set position.
; this procedure computes the cylinder, head and sector number from
; the logical segment number.
; the parameters 'segments per cylinder' , 'segments per track'
; and 'screw' is used.
; call: return:
; w0 destroyed
; w1 destroyed
; w2 segmentno destroyed
; w3 link destroyed
b.w.
n1: ld w1 -100 ; set position:
wd w2 b31 ; w2:=cylinder;
wd w1 b32 ; w1:=head;
sz w2 2.1 ; w0:=sector;
wa w0 b33 ; if cylinder odd then
sl w0 (b32) ; sector:=(sector+screw) mod sectors per track;
ws w0 b32 ;
ls w2 8 ;
lo w1 4 ; position1:=cylinder<8+head;
ls w0 16 ; position2:=sector<16+0;
rs w1 b30+0 ;
rs w0 b30+2 ; position:=position0, position1;
jl x3 ; exit: return;
e.
; procedure reset core.
; clear possible parity errors in core.
; note: the last word may not be written
; call: return
; w0 unchanged
; w1 top addr unchanged
; w2 start addr destroyed
; w3 link unchanged
b.w.
n2: ds w0 x2 ; (addr) := w0 ; (addr-2) := w3
al w2 x2+4 ;
sh w2 x1 ;
jl n2 ;
jl x3 ;
e.
b7: 8.52525252 ; check pattern
\f
0, r.(:a10+512-k:)/2-11+1 ; fill up
b.i0 w.
; interrupt stack:
0 ; monitor element: (end status)
i0 ; reg dump
0 ; exception
0 ; escape
m0 ; monitor call
0 ; external interrupt
1<23 ; user element: monitor status
i0 ; reg dump
0 ; exception
0 ; escape
i0: jd -1<11+0 ; last word in first segment: change to monitor mode and goto start load;
b1=k/4*4 ; top(loader)
e.
e. ; end of load segment;
e.
e.
end
▶EOF◀