-- FILE: <JPROG>RamLoad.mesa Last Edited by Mitchell, September 5, 1978 5:58 PM
DIRECTORY
AltoDefs: FROM "AltoDefs" USING[PageNumber, BytesPerPage, BytesPerWord],
InlineDefs: FROM "InlineDefs" USING[BITAND],
NovaOps: FROM "NovaOps" USING[NovaJSR],
PrivateRamDefs: FROM "PrivateRamDefs",
RamDefs: FROM "RamDefs",
SegmentDefs: FROM "SegmentDefs" USING[FileHandle, FileSegmentHandle, NewFile, NewFileSegment, DefaultBase, DefaultPages, GetEndOfFile, Read, OldFileOnly, SwapIn, FileSegmentAddress, ReleaseFile, Unlock, SwapOut, DeleteFileSegment];
RamLoad: PROGRAM IMPORTS sg: SegmentDefs EXPORTS RamDefs =
BEGIN OPEN RamDefs, PrivateRamDefs; -- module body
LoadRamAndBoot: PUBLIC PROCEDURE[m: MuImage, boot: BOOLEAN] RETURNS [constDiffs: CARDINAL] =
-- loads the ram from the MuImage, checks the constants and returns number of constant mismatches. If boot=TRUE, also does a silent boot: first, a silent boot is done to guarantee that the machine is in ground state (everything running in ROM0 - ok for Mesa?) and then, after loading the ram image, another silent boot is done as specified in the blv field of the MuImage.
BEGIN --LoadRamAndBoot
muCode: ARRAY [0..2) OF MicroCode ←-- to be loaded at loc 0
[
[r: 0, aluF: Bus, bs: ReadR, f1: SwMode, f2: Noop, loadT: no, loadLM: no, next: 1],
[r: 0, aluF: Bus, bs: ReadR, f1: Noop, f2: Noop, loadT: no, loadLM: no, next: EmSTART]
];
resetToProm: RamImage = DESCRIPTOR[muCode];
IF NOT RamExists[] THEN RETURN[177777B];
IF boot THEN
BEGIN
WriteRam[0, resetToProm];
SilentBoot[BootLocusVector[177776B]];-- blv value to reset to ROM0
END;
constDiffs ← CheckConstants[DESCRIPTOR[m.constVector]];
WriteRam[0, DESCRIPTOR[m.ramVector]];-- load the ram
IF boot THEN SilentBoot[m.blv];-- start it running wherever the MuImage specifies
END; --LoadRamAndBoot
NoEtherNetBoard: PUBLIC ERROR = CODE;
SilentBoot: PUBLIC PROCEDURE[blv: BootLocusVector] =
-- check to see that a silent boot is possible (I.e., that Alto has an EtherNet board), sets boot locus vector and does the StartIO to cause a silent boot.
BEGIN --SilentBoot
IF InlineDefs.BITAND[StartIO[0], 77777B]=77777B THEN ERROR NoEtherNetBoard;
SetBootLocusVector[blv];
[]←StartIO[100000B];-- boot it.
END; --SilentBoot
SetBootLocusVector: PROCEDURE[blv: BootLocusVector] =
-- Removes part of the code in the Ram (so be sure no task is running in the ram before doing this or the Alto will be zapped), writes some microcode into the same place and jumps to it to set the boot locus vector and then puts the previous ram contents back. A subsequent StartIO can be used to do a silent boot (see, e.g., LoadRamAndBoot above).
BEGIN --SetBootLocusVector
muCode: ARRAY [0..4) OF MicroCode ←-- microcode to go at loc 1000B
[
[r: 0, aluF: Bus, bs: ReadR, f1: Task, f2: Noop, loadT: no, loadLM: no, next: 1001B],
[r: 3--AC0--, aluF: Bus, bs: ReadR, f1: RmrGets, f2: Noop, loadT: no, loadLM: no, next: 1002B],
[r: 0, aluF: Bus, bs: ReadR, f1: SwMode, f2: Noop, loadT: no, loadLM: no, next: 1003B],
[r: 0, aluF: Bus, bs: ReadR, f1: Noop, f2: Noop, loadT: no, loadLM: no, next: EmSTART]
];
ldBLV: RamImage = DESCRIPTOR[muCode];
sv: ARRAY [0..4) OF MicroCode;
svDesc: RamImage = DESCRIPTOR[sv];
ReadRam[1000B, svDesc];-- save part of the ram
WriteRam[1000B, ldBLV];
[]←JumpToRam[1000B, blv];-- execute the code and give it the blv parameter
WriteRam[1000B, svDesc];-- put saved ram contents back
END; --SetBootLocusVector
CheckConstants: PROCEDURE[c: ConstantImage] RETURNS [constDiffs: CARDINAL] =
BEGIN --CheckConstants
muCode: ARRAY [0..2) OF MicroCode ←
[
[r: 0, aluF: Bus, bs: 0, f1: SwMode, f2: ReadConst, loadT: no, loadLM: yes, next: 1001B],
[r: 3--ACO--, aluF: Bus, bs: RGets, f1: Noop, f2: Noop, loadT: no, loadLM: no, next: EmSTART]
];
readConsti: RamImage ← DESCRIPTOR[muCode];
old: ARRAY [0..2) OF MicroCode;
descOld: RamImage = DESCRIPTOR[old];
i, const: CARDINAL;
ibits: MACHINE DEPENDENT RECORD[blank: [0..377B], high5: [0..37B], low3: [0..7B]];
constDiffs ← 0;
ReadRam[1000B, descOld];-- salt what is in RAM away
FOR i IN [1..maxConstAddr]
DO
ibits ← LOOPHOLE[i];-- to look at bits of i
readConsti[0].r ← ibits.high5;-- compile high-order microcode word
readConsti[0].bs ← ibits.low3;-- r,bs fields used to address constant memory
WriteRam[1000B, readConsti];
const ← JumpToRam[1000B, 0];
IF c[i]#const AND c[i]#0 THEN constDiffs ← constDiffs+1;
ENDLOOP;
WriteRam[1000B, descOld];-- restore RAM contents
END; --CheckConstants
RamExists: PROCEDURE RETURNS [BOOLEAN] =
-- Returns TRUE if Ram attached, FALSE if not.
BEGIN --RamExists
sv, y: ARRAY [0..1) OF MicroCode;
test: ARRAY [0..1) OF MicroCode ←
[[r: 31, aluF: undefAlu1, bs: ReadR, f1: Noop, f2: taskSpec5, loadT: no, loadLM: no, next: 525B]];
svDesc: RamImage ← DESCRIPTOR[sv];
yDesc: RamImage ← DESCRIPTOR[y];
testDesc: RamImage ← DESCRIPTOR[test];
ReadRam[774B, svDesc];-- save Ram word
WriteRam[774B, testDesc]; ReadRam[774B, yDesc];
WriteRam[774B, svDesc];-- restore Ram word
RETURN[ y[0]=test[0] ];
END; --RamExists
RamWord: TYPE = MACHINE DEPENDENT RECORD [high, low: CARDINAL];
ReadRam: PROCEDURE[a: MicroAddress, v: RamImage] =
-- Read Ram words beginning at location a; LENGTH[v] RamWords are read into v.
BEGIN --ReadRam
code: ARRAY [0..3) OF CARDINAL ←-- reads RAM half-word (16 bits) addressed by AC0 into AC0
[
105000B,-- MOV 0,1
061011B,-- RDRAM
001400B-- JMP 0,3
];
selectHighWord: CARDINAL = 2000B;-- to select high-order 16 bits of a RAM word
high, low: CARDINAL;
i: CARDINAL;
FOR i IN [0..LENGTH[v])
DO
high ← NovaOps.NovaJSR[JSR, BASE[code], a+i+selectHighWord];
low ← NovaOps.NovaJSR[JSR, BASE[code], a+i];
v[i] ← LOOPHOLE[RamWord[high: high, low: low], MicroCode];
ENDLOOP;
END; --ReadRam
WriteRam: PROCEDURE[a: MicroAddress, v: RamImage] =
-- Beginning at Ram location a, write LENGTH[v] RamWords into the Ram. The loop to do this is written entirely in Nova code so that it can operate even if the microcode being loaded temporarily clobbers Mesa microcode (as is the case when using XMesa on wide-bodied Altos).
BEGIN --WriteRam
code: ARRAY [0..14) OF CARDINAL ←
[
111000B,--MOV0,2;move ptr to parameter record to indexable register
55003B,-- STA3,3,2; save return address in parameter record
25001B,-- LDA1,1,2;load ram address
35002B,-- LOOP:LDA3,2,2;get @v[i]
21400B,-- LDA0,0,3;load v[i].high into ac0 for wrtram
35401B,-- LDA3,1,3;load v[i].low into ac3 for wrtram
061012B,-- WRTRAM
125420B,-- INCZ1,1; increment the ram address
11002B,-- ISZ2,2; increment the vector address twice
11002B,-- ISZ2,2
15000B,-- DSZ0,2; decrement count and check if done
770B,-- JMPLOOP; nope, go around again
35003B,-- LDA3,3,2; finished, load the return address
1400B-- JMP0,3; return
];
acs: MACHINE DEPENDENT RECORD[n, ramAddr, vecAddr, svAc3: UNSPECIFIED];
acs ← [n: LENGTH[v], ramAddr: a, vecAddr:BASE[v], svAc3: NIL]; -- prepare parameters for Alto code
[] ← NovaOps.NovaJSR[JSR, BASE[code], @acs];
END; --WriteRam
JumpToRam: PROCEDURE[ac1: MicroAddress, ac0: UNSPECIFIED] RETURNS[fromAc0: CARDINAL] =
-- Jump to the Ram location given by ac1, passing ac0 in Alto AC0.
BEGIN --JumpToRam
code: ARRAY [0..5) OF CARDINAL ←
[
111000B,-- MOV 0,2
021000B,-- LDA 0,0,2
025001B,-- LDA 1,1,2
061010B,-- JMPRAM
001400B-- JMP 0,3
];
acs: MACHINE DEPENDENT RECORD[ac0: UNSPECIFIED, ac1: CARDINAL --MicroAddress--]
← [ac0, ac1];
fromAc0 ← NovaOps.NovaJSR[JSR, BASE[code], @acs];
END; --JumpToRam
StartIO: PUBLIC PROCEDURE[ac0: UNSPECIFIED] RETURNS [fromAc0: CARDINAL] =
-- Do an SIO with ac0 passed in the Alto AC0.
BEGIN --StartIO
code: ARRAY [0..2) OF CARDINAL ←
[
061004B,-- SIO
001400B-- JMP 0,3
];
fromAc0NovaOps.NovaJSR[JSR,BASE[code], ac0];
END; --StartIO
muFH: sg.FileHandle ← NIL;
muSeg: sg.FileSegmentHandle ← NIL;
checkConstVec: ARRAY [1..13] OF CARDINAL = -- what first constants in a Packed Mu file should be
[1, 2, 177776B, 177777B, 177777B, 17B, 177777B, 3, 4, 5, 6, 7, 10B];
MuFileAlreadyOpen: PUBLIC ERROR = CODE;
SuspiciousPackedMuFile: PUBLIC ERROR = CODE;
ReadPackedMuFile: PUBLIC PROCEDURE[name: STRING] RETURNS[theImage: MuImage] =
-- Read and swap in a Packed Mu file and check it to increase our confidence that it is a valid MuImage as prepared by the program PackMu.Run.
BEGIN OPEN sg; --ReadPackedMuFile
lastPage: AltoDefs.PageNumber;
lastByteCount: [0..AltoDefs.BytesPerPage];
i: CARDINAL;
IF muFH # NIL THEN ERROR MuFileAlreadyOpen;
theImage←NIL;
muFH ← NewFile[name: name, access: Read, version: OldFileOnly];
BEGIN
[page: lastPage, byte: lastByteCount] ← GetEndOfFile[muFH];
IF lastPage#12B THEN GOTO FileLooksBad;
IF lastByteCount MOD AltoDefs.BytesPerWord # 0 THEN GOTO FileLooksBad;
muSeg ← NewFileSegment[file: muFH, base: DefaultBase, pages: DefaultPages, access: Read];
SwapIn[muSeg];
theImage ← FileSegmentAddress[muSeg];
FOR i IN [1..13] DO IF checkConstVec[i]#theImage.constVector[i] THEN GOTO FileLooksBad; ENDLOOP;
EXITS
FileLooksBad =>
BEGIN
ReleaseMuImage[theImage];
ERROR SuspiciousPackedMuFile;
END;
END;
END; --ReadPackedMuFile
ReleaseMuImage: PUBLIC PROCEDURE[theImage: MuImage] =
-- Release the FileHandle for the current packed MuImage. IF muSeg#NIL, then swap it out first and get rid of the segment. Then release the file.
BEGIN OPEN sg; --ReleaseMuImage
IF muSeg=NIL THEN
BEGIN
IF theImage#NIL THEN ERROR;
ReleaseFile[muFH];
END
ELSE
BEGIN
Unlock[muSeg]; SwapOut[muSeg];
DeleteFileSegment[muSeg];
muSeg ← NIL;
END;
muFH←NIL;
END; --ReleaseMuImage
-- I N I T I A L I Z A T I O N
END. -- RamLoad
MODULE HISTORY
Initial: Mitchell, May 13, 1977 1:40 PM
reason: written to be part of Mesa/Juniper code for running the Trident disks.
Compilation started: May 15, 1977 3:17 PM
Compile1, 2, and 3: numerous small syntactic errors, including incorrect usage of comment convention. A single syntax error seems to cause large number of messages about names and variables being undeclared in later phases of the compiler.
Compile4,5: one too many "]"s. forgot BEGIN following a THEN and had one too many ENDs.
Compile6: forgot to declare MicroAddress, maxConstAddr. one too few values in two constructors; forgot that JumpToRam and StartIO both return values and had to put []← in two places.
Compile7: Compiler bug in pass 5; signal=164353B, message = 177777B
Compilation attempts suspended: May 15, 1977 5:07 PM
reason: Added routines to ReadPackedMuFile, ReleasePackedMuFile, and small test driver
Compilation started: May 15, 1977 7:08 PM
Compile1: extra ; in a declaration
Compile2: missplaced global declaration in mainline test section; had to add something to take result from LoadRamAndBoot and print it also. Misspelled checkConstVec
Compile3: forgot that StartIO returned a value; perhaps a naming scheme would help me to remember: e.g., two procedures, StartIO and StartIOVal for when a value is needed.
Compiled Correctly: May 18, 1977 10:55 PM
Changed by: Mitchell, May 18, 1977 12:56 PM
reason: First attempt to run RamLoad on Alto II with 2K PROM caused a break to 1; simplified Mesa code in ReadRam in an attempt to be able to set more breakpoints and get my hands on the problem.
Compilation started: May 18, 1977 12:57 PM
Compiled Correctly: May 18, 1977 1:00 PM
Changed by: Mitchell, May 23, 1977 10:38 AM
reason: Was able to get program working, but with two kinds of unsettling behavior. It sometimes would still dive off to never-never land, and it always finds a large number of mismatches in the constant rom. To attack this, I have defined the record type MicroCode to allow me to have more confidence in the octal microcode in this program, and I have added some code to rpint the constants that don’t match.
Compilation started: May 23, 1977 10:41 AM
Compile1: forgot to delete some old RamWord constructors after replacing them with MicroCode constructors.
Compile2: mistake in ibits in CheckConstants; record was too long.
Compiled Correctly: May 23, 1977 11:17 AM
Changed by: Mitchell, May 23, 1977 2:52 PM
reason: Had JMP 1,3 instead of JMP 0,3 in all the nova code
Compilation started: May 23, 1977 2:52 PM
Compiled Correctly: May 23, 1977 2:56 PM
Changed by: Mitchell, May 24, 1977 1:07 PM
reason: Repackaged RamLoad; moved type declarations and some procedure definitions to RamDefs; moved test driver to a separate file, TestRamLoad.
Compilation started: May 24, 1977 1:08 PM
compile1: forgot a ; after OPEN RamDefs attached to module begin as part of removing the type definitions.
Compiled Correctly: May 24, 1977 1:20 PM
Changed by: Mitchell, July 12, 1977 1:41 PM
reason: Changed to use DBOSS interfacing conventions and changed StartIO so that it no longer returns a value.
Compilation started: July 12, 1977 1:44 PM
compile1: July 12, 1977 2:00 PM Change to StartIO was a mistake because an SIO does return a value if the enthernet board is present, SIO 0 will return the network address of the Alto. Changed it here and will have to change it back in RamDefs also. Forgot to include MesaDefs; misspelled RamDefs as Ramdefs in one place.
compile2: July 12, 1977 2:11 PM Used mesa. instead of MesaDefs. in two places where types were needed; forgot the StartIO component in the constructor for me.
Compiled Correctly: July 12, 1977 2:16 PM
Changed by: Mitchell, September 9, 1977 11:40 AM
reason: Convert from dboss to Mesa 3.0
Compilation started: September 9, 1977 2:14 PM
Compiled Correctly: September 9, 1977 2:16 PM
Changed by: Mitchell, June 14, 1978 3:41 PM Convert to Mesa 4.0
Changed by: Mitchell, September 5, 1978 5:59 PM Made WriteRam loop all Nova code so that ram could be loaded without invoking Mesa microcode. This is necessary for using the XMesa system with wide-bodied Altos.
Changed by: Mitchell, DateTime Reason