<> <> <> <> <> <> DIRECTORY Basics USING [ BITOR, HighHalf, LowHalf ], Checksum USING [ComputeChecksumProc], DeviceCleanup USING [Await, Item, Perform, Reason], DLionInputOutput, MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], MPCodes USING [powerOff], PrincOps USING [aCHKSUM, aGETF, ControlLink, flagsVacant, InterimPageState, PageCount, PageNumber, PageState, RealPageNumber, SD, StateVector, sUnimplemented, VersionResult, zMISC], PrincOpsUtils USING [Copy, DisableInterrupts, GetReturnFrame, GetReturnLink, LongCopy, MyLocalFrame], ProcessorFace USING [gmtEpoch, GreenwichMeanTime, ProcessorID, SetMP], TrapSupport USING [BumpPC, OpTrapTable, opTrapTable]; ProcessorHeadDLion: MONITOR IMPORTS Basics, Checksum, DeviceCleanup, PrincOpsUtils, ProcessorFace, TrapSupport EXPORTS DLionInputOutput, MicrocodeBooting, ProcessorFace SHARES Checksum, ProcessorFace = { <> 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): BOOL _ 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]; <> Go: PUBLIC SAFE PROC = CHECKED{ <> <> firstUsed: PrincOps.RealPageNumber _ DLionInputOutput.firstReservedPage + DLionInputOutput.reservedPageCount; FOR i: PrincOps.PageNumber IN [0..DLionInputOutput.numberVirtualPages) DO state: PrincOps.PageState; real: PrincOps.RealPageNumber; TRUSTED { [state, real] _ GetPageState[i] }; IF state.flags # PrincOps.flagsVacant <= DLionInputOutput.firstReservedPage-- -- but compiler warns about "foo >= 0">> THEN firstUsed _ MIN[real, firstUsed]; ENDLOOP; specialRealPages _ firstUsed - DLionInputOutput.firstReservedPage; }; GetPageState: PROC [virtual: PrincOps.PageNumber] RETURNS [state: PrincOps.PageState, real: PrincOps.RealPageNumber] = INLINE { <> DoGetPageState: PROC [virtual: --OldPageNumber--CARDINAL] RETURNS [state: PrincOps.InterimPageState] = MACHINE CODE {PrincOps.zMISC, PrincOps.aGETF}; [logSingleError: , flags: state.flags, realPage: real] _ DoGetPageState[virtual].state; }; InitializeCleanup: PUBLIC SAFE PROC = TRUSTED { OPEN DeviceCleanup; item: Item; reason: Reason; DO reason _ Await[@item]; SELECT reason FROM turnOff, kill => NULL -- we have a genuine clock, so don't need to invalidate it!--; ENDCASE ENDLOOP }; <> processorID: PUBLIC ProcessorFace.ProcessorID _ GetProcessorID[]; GetProcessorID: PROC RETURNS [ProcessorFace.ProcessorID] = { 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]]; }; <> firstSpecialRealPage: PUBLIC PrincOps.RealPageNumber _ DLionInputOutput.firstReservedPage; specialRealPages: PUBLIC PrincOps.PageCount _ 0; -- set correctly in initialization code <> GetNextAvailableVM: PUBLIC SAFE PROC [page: PrincOps.PageNumber] RETURNS [firstPage: PrincOps.PageNumber, count: PrincOps.PageCount] = TRUSTED { <> IF page < 376B THEN RETURN[page, 376B - page]; page _ MAX[page, 376B + 1]; IF page < 377B THEN RETURN[page, 377B - page]; page _ MAX[page, 377B + 1]; IF page < DLionInputOutput.numberVirtualPages THEN RETURN[page, DLionInputOutput.numberVirtualPages - page]; RETURN[LAST[PrincOps.PageNumber], 0] }; useLongMapOps: PUBLIC BOOL _ FALSE; <> <> GreenwichMeanTime: TYPE = ProcessorFace.GreenwichMeanTime; gmtEpoch: GreenwichMeanTime = ProcessorFace.gmtEpoch; GetGreenwichMeanTime: PUBLIC ENTRY SAFE PROC RETURNS [gmt: GreenwichMeanTime] = TRUSTED { tod: LONG POINTER TO TimeOfDayClock = IOPage + TimeOfDayOffset; IF tod.valid = 0 THEN RETURN[gmtEpoch]; DO gmt _ tod.time; IF Basics.LowHalf[gmt] = tod.lowCheck THEN EXIT; ENDLOOP; RETURN }; SetGreenwichMeanTime: PUBLIC ENTRY SAFE PROC [gmt: GreenwichMeanTime] = TRUSTED { pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset; tod: LONG POINTER TO TimeOfDayClock = IOPage + TimeOfDayOffset; WHILE pCSB.command.busy DO NULL ENDLOOP; pCSB.data2 _ Basics.LowHalf[gmt]; pCSB.data1 _ Basics.HighHalf[gmt]; pCSB.command _ [op: setTOD]; tod.valid _ 0; WHILE pCSB.command.busy DO NULL ENDLOOP; WHILE tod.valid = 0 DO NULL ENDLOOP; RETURN }; <> microsecondsPerHundredPulses: PUBLIC CARDINAL _ 2878; <> cvTimeoutMask: WORD = 100000B; -- DLion microcode assumes level 0 reservedNakedNotifyMask: PUBLIC WORD _ cvTimeoutMask; <> millisecondsPerTick: PUBLIC CARDINAL _ 52; InitializeCVTimeouts: PROC = { DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[177753B]]; DIW^ _ Basics.BITOR[DIW^, cvTimeoutMask]; }; <> BootButton: PUBLIC SAFE PROC = TRUSTED { pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset; PrincOpsUtils.DisableInterrupts[]; WHILE pCSB.command.busy DO NULL ENDLOOP; pCSB.command _ [op: boot]; DO ENDLOOP; }; PowerOff: PUBLIC SAFE PROC [returnIfDisabled: BOOL _ FALSE] = TRUSTED { <> <> IF powerOffCount # 0 AND returnIfDisabled THEN RETURN; PrincOpsUtils.DisableInterrupts[]; DeviceCleanup.Perform[turnOff]; DO ProcessorFace.SetMP[MPCodes.powerOff]; IF powerOffCount = 0 THEN EXIT; ENDLOOP; DO <> IF (GetGreenwichMeanTime[] - ProcessorFace.gmtEpoch) >= (gmtAutomaticPowerOn - ProcessorFace.gmtEpoch) AND (~externalEventRequired OR ExternalEvent[]) THEN BootButton[] ENDLOOP }; powerOffCount: INT _ 0; DisablePowerOff: PUBLIC ENTRY SAFE PROC = TRUSTED { <> powerOffCount _ powerOffCount + 1; }; <<>> EnablePowerOff: PUBLIC ENTRY SAFE PROC = TRUSTED { <> IF powerOffCount > 0 THEN powerOffCount _ powerOffCount - 1; }; gmtAutomaticPowerOn: ProcessorFace.GreenwichMeanTime; externalEventRequired: BOOL; ExternalEvent: PROC RETURNS [BOOL] = {RETURN[FALSE]}; SetAutomaticPowerOn: PUBLIC SAFE PROC [gmt: ProcessorFace.GreenwichMeanTime, externalEvent: BOOL] = TRUSTED { gmtAutomaticPowerOn _ gmt; externalEventRequired _ externalEvent; }; ResetAutomaticPowerOn: PUBLIC SAFE PROC = TRUSTED { gmtAutomaticPowerOn _ ProcessorFace.gmtEpoch - 1}; -- infinity <> BootSpecificMicrocode: PUBLIC PROC [bfn: MicrocodeBooting.BootFileNumber] = { BootButton[]; }; GetBootFileNumber: PUBLIC PROC [type: MicrocodeBooting.MicrocodeType] RETURNS [bfn: MicrocodeBooting.BootFileNumber] = { RETURN[MicrocodeBooting.nullBootFileNumber]; }; <> UnimplementedInstruction: ERROR = CODE; Unimplemented: PROC = { v: MACHINE DEPENDENT RECORD [a, b: UNSPECIFIED, state: PrincOps.StateVector]; v.state _ STATE; ERROR UnimplementedInstruction; }; trapTable: TrapSupport.OpTrapTable _ [ALL[LOOPHOLE[Unimplemented]], ALL[LOOPHOLE[Unimplemented]]]; <> <> <> <> UnimplementedTrap: PROC = { l: PrincOps.ControlLink; code: LONG POINTER TO PACKED ARRAY [0..0) OF [0..377B]; opcode: [0..400B); state: PrincOps.StateVector; state _ STATE; state.source _ l _ PrincOpsUtils.GetReturnLink[]; code _ LOOPHOLE[l.frame.accesslink.code.longbase]; opcode _ code[l.frame.pc]; state.dest _ IF opcode # PrincOps.zMISC THEN TrapSupport.opTrapTable.main[opcode] ELSE TrapSupport.opTrapTable.misc[code[l.frame.pc+1]]; <> <<(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 }; <> LocalBlkZ: PROC [count: CARDINAL] = { state: PrincOps.StateVector; p: POINTER; state _ STATE; TrapSupport.BumpPC[2]; IF count#0 THEN { p _ @(PrincOpsUtils.GetReturnFrame[].local[0]); p^ _ 0; IF count#1 THEN PrincOpsUtils.Copy[from: p, to: p+1, nwords: count-1]; }; state.dest.frame _ PrincOpsUtils.GetReturnFrame[]; RETURN WITH state; }; LongBlkZ: PROC [p: LONG POINTER, count: CARDINAL] RETURNS [resultP: LONG POINTER] = { state: PrincOps.StateVector; state _ STATE; TrapSupport.BumpPC[2]; IF count#0 THEN { p^ _ 0; IF count#1 THEN PrincOpsUtils.LongCopy[from: p, to: p+1, nwords: count-1]; }; resultP _ p; state.dest.frame _ PrincOpsUtils.MyLocalFrame[]; TRANSFER WITH state; }; UVersion: PROC RETURNS [PrincOps.VersionResult] = { TrapSupport.BumpPC[2]; RETURN [[ machineType: dandelion, majorVersion: 0, unused: 0, floatingPoint: FALSE, cedar: FALSE, releaseDate: ProcessorFace.gmtEpoch/86400]]; }; ComputeChecksum: PRIVATE PROC [cs, nWords: CARDINAL, p: LONG POINTER] RETURNS [CARDINAL] = { RETURN[Checksum.ComputeChecksumProc[cs, nWords, p]]; }; <
> InitializeCVTimeouts[]; PrincOps.SD[PrincOps.sUnimplemented] _ LOOPHOLE[UnimplementedTrap]; PrincOps.SD[137B] _ LOOPHOLE[@trapTable]; TrapSupport.opTrapTable.misc[PrincOps.aCHKSUM] _ LOOPHOLE[ComputeChecksum]; TrapSupport.opTrapTable.misc[100B] _ LOOPHOLE[LocalBlkZ]; TrapSupport.opTrapTable.misc[102B] _ LOOPHOLE[LongBlkZ]; TrapSupport.opTrapTable.misc[104B] _ LOOPHOLE[UVersion]; }. 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 January 31, 1985 1:46:15 pm; Orr Take out ProcessorFaceExtras, change in PrincOps.SD