-- ProcessorHeadDLion.mesa
-- Last Edited by: Taft, February 27, 1983 3:40 pm
DIRECTORY
Checksum USING [ComputeChecksumProc],
DeviceCleanup USING [Perform, Reason],
DLionInputOutput,
Environment USING [Byte, PageCount],
Frame USING [GetReturnFrame, GetReturnLink, MyLocalFrame],
HeadStartChain USING [],
Inline USING [BITOR, COPY, HighHalf, LongCOPY, LowHalf],
MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber],
MicrocodeVersion USING [VersionResult],
MiscAlpha USING [aCHKSUM, aTEXTBLT],
Mopcodes USING [zMISC],
PilotMP USING [cPowerOff],
PrincOps USING [ControlLink, FrameHandle, StateVector],
ProcessInternal USING [DisableInterrupts],
ProcessorFace USING [gmtEpoch, GreenwichMeanTime, ProcessorID, SetMP],
SDDefs USING [SD, sUnimplemented],
SoftwareTextBlt USING [TextBlt],
System USING [gmtEpoch],
TrapSupport USING [BumpPC, OpTrapTable, opTrapTable];
ProcessorHeadDLion: PROGRAM
IMPORTS Checksum, DeviceCleanup, Frame, Inline, ProcessInternal, ProcessorFace,
SoftwareTextBlt, TrapSupport
EXPORTS DLionInputOutput, HeadStartChain, MicrocodeBooting, ProcessorFace
SHARES Checksum, ProcessorFace =
BEGIN
-- DLionInputOutput
IOPage: PUBLIC LONG POINTER ← LOOPHOLE[LONG[177400B]];
ProcessorCSBOffset: CARDINAL = 127B; -- 57X
ProcessorCSB: TYPE = MACHINE DEPENDENT RECORD [
data2(0): WORD,
data1(1): WORD,
data0(2): WORD,
command(3): ProcessorCommand];
ProcessorCommand: TYPE = MACHINE DEPENDENT RECORD [
busy(0:0..0): BOOLEAN ← TRUE,
op(0:1..15): ProcessorOperation];
ProcessorOperation: TYPE = MACHINE DEPENDENT {
setTOD(1), readTOD(2), readPID(3), boot(4), (32767)};
TimeOfDayOffset: CARDINAL = 320B; -- 0D0X
TimeOfDayClock: TYPE = MACHINE DEPENDENT RECORD [
valid(0): WORD, -- 0 => invalid, 177777B => valid
time(1): LONG CARDINAL,
lowCheck(3): CARDINAL];
-- Initialization
-- This is exported BOTH to ProcessorFace and to HeadStartChain.
-- Consequently it must not do anything besides cause a start trap on the first call.
Start: PUBLIC PROC = { -- By now start trap has occurred and main-body code has run--};
-- Processor ID
processorID: PUBLIC ProcessorFace.ProcessorID ← GetProcessorID[];
GetProcessorID: PROC RETURNS [ProcessorFace.ProcessorID] =
BEGIN
pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset;
WHILE pCSB.command.busy DO NULL ENDLOOP;
pCSB.command ← [op: readPID];
WHILE pCSB.command.busy DO NULL ENDLOOP;
RETURN[[pCSB.data0, pCSB.data1, pCSB.data2]];
END;
-- Real memory configuration
dedicatedRealMemory: PUBLIC Environment.PageCount ←
DLionInputOutput.reservedPageCount;
-- Virtual memory layout (not yet implemented)
-- GreenwichMeanTime
GreenwichMeanTime: TYPE = ProcessorFace.GreenwichMeanTime;
gmtEpoch: GreenwichMeanTime = ProcessorFace.gmtEpoch;
GetGreenwichMeanTime: PUBLIC PROC RETURNS [gmt: GreenwichMeanTime] =
BEGIN
tod: LONG POINTER TO TimeOfDayClock = IOPage + TimeOfDayOffset;
IF tod.valid = 0 THEN RETURN[gmtEpoch];
DO
gmt ← tod.time;
IF Inline.LowHalf[gmt] = tod.lowCheck THEN EXIT;
ENDLOOP;
RETURN
END;
SetGreenwichMeanTime: PUBLIC PROC [gmt: GreenwichMeanTime] =
BEGIN
pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset;
tod: LONG POINTER TO TimeOfDayClock = IOPage + TimeOfDayOffset;
WHILE pCSB.command.busy DO NULL ENDLOOP;
pCSB.data2 ← Inline.LowHalf[gmt];
pCSB.data1 ← Inline.HighHalf[gmt];
pCSB.command ← [op: setTOD];
tod.valid ← 0;
WHILE pCSB.command.busy DO NULL ENDLOOP;
WHILE tod.valid = 0 DO NULL ENDLOOP;
RETURN
END;
-- Interval time
microsecondsPerHundredPulses: PUBLIC CARDINAL ← 2878;
-- Naked notifies
cvTimeoutMask: WORD = 100000B; -- DLion microcode assumes level 0
reservedNakedNotifyMask: PUBLIC WORD ← cvTimeoutMask;
-- Condition variable time
millisecondsPerTick: PUBLIC CARDINAL ← 52;
InitializeCVTimeouts: PROC =
BEGIN
DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[177753B]];
DIW↑ ← Inline.BITOR[DIW↑, cvTimeoutMask];
END;
-- Booting and power control
BootButton: PUBLIC PROC =
BEGIN
pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset;
ProcessInternal.DisableInterrupts[];
WHILE pCSB.command.busy DO NULL ENDLOOP;
pCSB.command ← [op: boot];
DO ENDLOOP;
END;
PowerOff: PUBLIC PROCEDURE =
BEGIN
-- NOTE: This code depends on the greenwich mean time clock running
-- with interrupts disabled and devices turned off.
ProcessInternal.DisableInterrupts[];
DeviceCleanup.Perform[turnOff];
ProcessorFace.SetMP[PilotMP.cPowerOff];
DO
-- forever
IF (GetGreenwichMeanTime[] - ProcessorFace.gmtEpoch)
>= (gmtAutomaticPowerOn - ProcessorFace.gmtEpoch)
AND (~externalEventRequired OR ExternalEvent[]) THEN BootButton[]
ENDLOOP
END;
gmtAutomaticPowerOn: ProcessorFace.GreenwichMeanTime;
externalEventRequired: BOOLEAN;
ExternalEvent: PROCEDURE RETURNS [BOOLEAN] = {RETURN[FALSE]};
SetAutomaticPowerOn: PUBLIC PROCEDURE [
gmt: ProcessorFace.GreenwichMeanTime, externalEvent: BOOLEAN] =
BEGIN gmtAutomaticPowerOn ← gmt; externalEventRequired ← externalEvent; END;
ResetAutomaticPowerOn: PUBLIC PROCEDURE =
{gmtAutomaticPowerOn ← ProcessorFace.gmtEpoch - 1}; -- infinity
-- MicrocodeBooting; degenerate implementation for now
BootSpecificMicrocode: PUBLIC PROCEDURE [bfn: MicrocodeBooting.BootFileNumber] =
BEGIN
BootButton[];
END;
GetBootFileNumber: PUBLIC PROCEDURE [type: MicrocodeBooting.MicrocodeType]
RETURNS [bfn: MicrocodeBooting.BootFileNumber] =
BEGIN
RETURN[MicrocodeBooting.nullBootFileNumber];
END;
-- TrapSupport.
UnimplementedInstruction: ERROR = CODE;
Unimplemented: PROCEDURE =
BEGIN
v: MACHINE DEPENDENT RECORD [a, b: UNSPECIFIED, state: PrincOps.StateVector];
v.state ← STATE;
ERROR UnimplementedInstruction;
END;
trapTable: TrapSupport.OpTrapTable ←
[ALL[LOOPHOLE[Unimplemented]], ALL[LOOPHOLE[Unimplemented]]];
-- Software assist for microcode
-- assumes return link is a frame, and has been started.
-- This trap procedure is called only if the Cedar TrapSupport microcode is NOT present.
-- If the microcode IS present, it calls the appropriate trap routine directly.
UnimplementedTrap: PROC =
BEGIN
l: PrincOps.ControlLink;
code: LONG POINTER TO PACKED ARRAY [0..0) OF Environment.Byte;
opcode: [0..400B);
state: PrincOps.StateVector;
state ← STATE;
state.source ← l ← Frame.GetReturnLink[];
code ← LOOPHOLE[l.frame.accesslink.code.longbase];
opcode ← code[l.frame.pc];
state.dest ← IF opcode # Mopcodes.zMISC THEN TrapSupport.opTrapTable.main[opcode]
ELSE TrapSupport.opTrapTable.misc[code[l.frame.pc+1]];
-- If handler is fixed-frame, manually plant the return link.
-- (Microcode does that for traps, but not for ordinary XFERs to frames.)
IF ~state.dest.proc THEN state.dest.frame.returnlink ← l;
RETURN WITH state; -- Flush my frame and transfer to real trap handler
END;
-- Handler for TEXTBLT trap.
-- The opcode actually takes a pile of arguments and returns a pile of results.
-- The trap handler is defined strangely in order to avoid needless pushing and popping.
TEXTBLTTrap: PROC =
BEGIN
-- TEXTBLT is a minimal-stack instruction, so no need to save state vector.
TextBlt: PROC = LOOPHOLE[SoftwareTextBlt.TextBlt];
TrapSupport.BumpPC[2];
TextBlt[];
END;
-- Trap support for Cedar-related opcodes
LocalBlkZ: PROC [count: CARDINAL] =
BEGIN
state: PrincOps.StateVector;
p: POINTER;
state ← STATE;
TrapSupport.BumpPC[2];
IF count#0 THEN
BEGIN
p ← @(Frame.GetReturnFrame[].local[0]);
p↑ ← 0;
IF count#1 THEN Inline.COPY[from: p, to: p+1, nwords: count-1];
END;
state.dest.frame ← Frame.GetReturnFrame[];
RETURN WITH state;
END;
LongBlkZ: PROC [p: LONG POINTER, count: CARDINAL] RETURNS [resultP: LONG POINTER] =
BEGIN
state: PrincOps.StateVector;
state ← STATE;
TrapSupport.BumpPC[2];
IF count#0 THEN
BEGIN
p↑ ← 0;
IF count#1 THEN Inline.LongCOPY[from: p, to: p+1, nwords: count-1];
END;
resultP ← p;
state.dest.frame ← Frame.MyLocalFrame[];
TRANSFER WITH state;
END;
UVersion: PROC RETURNS [MicrocodeVersion.VersionResult] =
BEGIN
TrapSupport.BumpPC[2];
RETURN [[
machineType: dandelion, majorVersion: 0, unused: 0,
floatingPoint: FALSE, cedar: FALSE, releaseDate: System.gmtEpoch/86400]];
END;
ComputeChecksum: PRIVATE PROC [cs, nWords: CARDINAL, p: LONG POINTER]
RETURNS [CARDINAL] = {RETURN[Checksum.ComputeChecksumProc[cs, nWords, p]]};
-- Main body code
InitializeCVTimeouts[];
SDDefs.SD[SDDefs.sUnimplemented] ← UnimplementedTrap;
SDDefs.SD[137B] ← @trapTable;
TrapSupport.opTrapTable.misc[MiscAlpha.aTEXTBLT] ← LOOPHOLE[TEXTBLTTrap];
TrapSupport.opTrapTable.misc[MiscAlpha.aCHKSUM] ← LOOPHOLE[ComputeChecksum];
TrapSupport.opTrapTable.misc[100B] ← LOOPHOLE[LocalBlkZ];
TrapSupport.opTrapTable.misc[102B] ← LOOPHOLE[LongBlkZ];
TrapSupport.opTrapTable.misc[104B] ← LOOPHOLE[UVersion];
END.
LOG
August 5, 1980 10:28 AM Forrest Created file.
August 12, 1980 10:41 AM McJones Added dedicatedRealMemory.
September 18, 1980 1:26 PM Sandman Changed cvTimeoutMask, millisecondsPerTick for new PSB format.
October 2, 1980 2:43 PM Forrest Changed microsecondsPerHundredPulses to 2878 from 2880.
October 3, 1980 5:26 PM Forrest Moved in unimplemented trap.
November 10, 1980 4:10 PM Forrest Added memory allocation junk.
January 23, 1981 approx Gobbel ?
February 6, 1981 12:04 PM Knutsen Make compatible with new PrincOps.
August 27, 1982 9:38 am Taft Add TrapSupport, MicrocodeBooting, MicrocodeVersion, etc.
February 27, 1983 2:31 pm Taft Export HeadStartChain.Start; absorb TrapSupportImpl