-- 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