<> <> <> <> <> <> <> DIRECTORY Basics USING [ BITOR, HighHalf, LowHalf ], Checksum USING [ComputeChecksumProc], DeviceCleanup USING [Await, Item, Perform, Reason], DLionInputOutput, MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], MPCodes USING [processorIDChanged, powerOff], PrincOps USING [aCHKSUM, aGETF, alpha, ControlLink, flagsVacant, InterimPageState, PageCount, PageNumber, PageState, PageValue, 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 = TRUSTED { <> <> firstUsed: PrincOps.RealPageNumber _ DLionInputOutput.firstReservedPage + DLionInputOutput.reservedPageCount; FOR i: PrincOps.PageNumber IN [0..DLionInputOutput.numberVirtualPages) DO pv: PrincOps.PageValue _ GetPageValue[i]; IF pv.state.flags # PrincOps.flagsVacant THEN firstUsed _ MIN[pv.real, firstUsed]; ENDLOOP; specialRealPages _ firstUsed - DLionInputOutput.firstReservedPage; }; <> aSETMAP: PrincOps.alpha = 150B; aGETMAPFLAGS: PrincOps.alpha = 151B; aSETMAPFLAGS: PrincOps.alpha = 152B; GetPageValue: PROC [virtual: PrincOps.PageNumber] RETURNS [pv: PrincOps.PageValue] = { <> OldGetPageValue: PROC [virtual: CARDINAL] RETURNS [state: PrincOps.InterimPageState] = MACHINE CODE {PrincOps.zMISC, PrincOps.aGETF}; NewGetPageValue: PROC [vp: LONG CARDINAL] RETURNS [PrincOps.PageState, LONG CARDINAL] = MACHINE CODE {PrincOps.zMISC, aGETMAPFLAGS}; IF --ProcessorFace.--useLongMapOps THEN [pv.state, pv.real] _ NewGetPageValue[virtual] ELSE [flags: pv.state.flags, realPage: pv.real] _ OldGetPageValue[virtual].state; }; InitializeCleanup: PUBLIC SAFE PROC = TRUSTED { initial: ProcessorFace.ProcessorID _ processorID; item: DeviceCleanup.Item; DO reason: DeviceCleanup.Reason _ DeviceCleanup.Await[@item]; SELECT reason FROM turnOff, kill => NULL -- we have a genuine clock, so don't need to invalidate it!--; turnOn => { -- Can't call procs (maybe no frames) so copy code pCSB: LONG POINTER TO ProcessorCSB = IOPage + ProcessorCSBOffset; current: ProcessorFace.ProcessorID; WHILE pCSB.command.busy DO NULL ENDLOOP; pCSB.command _ [op: readPID]; WHILE pCSB.command.busy DO NULL ENDLOOP; current _ [pCSB.data0, pCSB.data1, pCSB.data2]; IF initial # current THEN { <> ProcessorFace.SetMP[MPCodes.processorIDChanged]; DO ENDLOOP; }; }; 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 _ TRUE; <> 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 Code; Code: TYPE = RECORD [SEQUENCE COMPUTED CARDINAL OF CodeByte]; CodeByte: TYPE = [0..255]; opcode: CodeByte; 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.misc[code[l.frame.pc+1]] ELSE TrapSupport.opTrapTable.main[opcode]; <> <<(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 }; <> LocalGetPageValue: PROC [virtual: PrincOps.PageNumber] RETURNS [ps: PrincOps.PageState, pn: LONG CARDINAL] = { pv: PrincOps.PageValue; IF useLongMapOps THEN useLongMapOps _ FALSE ELSE ERROR; TrapSupport.BumpPC[2]; pv _ GetPageValue[virtual]; ps _ pv.state; pn _ pv.real; }; 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]; TrapSupport.opTrapTable.misc[aGETMAPFLAGS] _ LOOPHOLE[LocalGetPageValue]; }. 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 June 4, 1986 6:48:39 pm PDT; Orr Take out ProcessorFaceExtras, change in PrincOps.SD, GetPageValue, OldGetPageValue (local of GetPageValue), NewGetPageValue (local of GetPageValue), InitializeCleanup, useLongMapOps, ResetAutomaticPowerOn, TrapSupport, January <<>> <> <> <<>>