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 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]]; 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 ξProcessorHeadDLion.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Taft, February 27, 1983 3:40 pm Willie-Sue, January 31, 1985 3:05:00 pm PST Russ Atkinson (RRA) February 27, 1985 8:31:55 pm PST Doug Wyatt, February 26, 1985 5:56:58 pm PST DLionInputOutput Initialization By now start trap has occurred and main-body code has run. Scan the VM looking for the lowest real page mapped. Use this as upper bound on special real memory area (The microcode likes to use some of the bank 0 real memory for the Germ). AND real >= DLionInputOutput.firstReservedPage-- -- but compiler warns about "foo >= 0" Gets the state and real page of a virtual page. Processor ID Real memory configuration Virtual memory layout I believe that 376B and 377B are actually available on DLions, but at present the Germ assumes they aren't. ADB 1/23/84 The DLion can not use the long map ops. GreenwichMeanTime Interval time Naked notifies Condition variable time Booting and power control NOTE: This code depends on the greenwich mean time clock running with interrupts disabled and devices turned off. forever Bumps the power off disable count. This is useful during a critical operation to avoid power off operations. Decrements the power off disable count (pins at 0). MicrocodeBooting; degenerate implementation for now TrapSupport. 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. If handler is fixed-frame, manually plant the return link. (Microcode does that for traps, but not for ordinary XFERs to frames.) Trap support for Cedar-related opcodes Main body code Κ a˜codešœ™Kšœ Οmœ1™žœ˜Kšœ/™/š  œžœ Ÿžœžœ%˜fKšžœžœ"˜.—KšœW˜WKšœ˜—K˜š  œžœžœžœžœ˜/Kšžœ˜K˜ K˜šž˜K˜šžœž˜KšœžœŸ=œ˜TKšž˜—Kšž˜—Kšœ˜—K˜Kšœ ™ Kšœ žœ.˜Aš œžœžœ ˜˜ZK˜KšœžœŸ'˜XK˜K˜Kšœ™K˜š  œžœžœžœžœ?žœ˜Kšœy™yKšžœ žœžœ˜.Kšœžœ˜Kšžœ žœžœ˜.Kšœžœ˜Kšžœ+˜-Kšž œ3˜>Kšžœžœ˜$Kšœ˜K˜—šœž œžœ˜#Kšœ'™'K˜—Kšœ™K˜Kšœžœ#˜:K˜5K˜š  œžœž œžœžœžœ˜YKšœžœžœžœ+˜?Kšžœžœžœ ˜'šž˜K˜Kšžœ$žœžœ˜0Kšžœ˜—Kšž˜Kšœ˜K˜—š  œžœž œžœžœ˜QKšœžœžœžœ,˜AKšœžœžœžœ+˜?Kšžœžœžœžœ˜(K˜!K˜"K˜K˜Kšžœžœžœžœ˜(Kšžœžœžœžœ˜$Kšž˜Kšœ˜K˜—šœ ™ Kšœžœžœ˜5K˜—šœ™Kšœžœ Ÿ"˜AKšœžœžœ˜5K˜—šœ™Kšœžœžœ˜*š œžœ˜Kšžœžœžœžœžœžœžœ ˜4Kšžœ žœžœ˜)Kšœ˜K˜——šœ™K˜š   œžœžœžœžœ˜(Kšœžœžœžœ,˜AK˜"Kšžœžœžœžœ˜(K˜Kšžœžœ˜ Kšœ˜K˜—š œžœžœžœžœžœžœ˜GKšœ@™@Kšœ0™0Kšžœžœžœžœ˜6K˜"K˜šž˜K˜&Kšžœžœžœ˜Kšžœ˜—šž˜Kšœ™šžœ2˜4K˜1Kšžœžœžœ ˜A—Kšž˜—Kšœ˜K˜—šœžœ˜K˜—š  œžœžœžœž˜3Kšœm™mKšœ"˜"Kšœ˜K™—š  œžœžœžœž˜2Kšœ3™3Kšžœžœ#˜K˜K˜Kšœ3™3K˜š œžœžœ+˜MK˜ Kšœ˜K˜—š œžœžœ'žœ+˜xKšžœ&˜,Kšœ˜K˜K˜———šœ ™ K˜Kšœžœžœ˜'K˜š  œžœ˜Kš œžœž œžœž œ˜MKšœ žœ˜Kšžœ˜Kšœ˜K˜—˜$Kš œžœžœžœžœ˜=K˜K˜——šœ™Kšœ5™5KšœU™UKšœL™Lš œžœ˜K˜Kš œžœžœžœžœžœžœ ˜7K˜K˜Kšœžœ˜K˜1Kšœžœ#˜2K˜šœ žœžœ%˜QKšžœ2˜6—Kšœ:™:KšœF™FKšžœžœ!˜9Kšžœžœ Ÿ3˜GKšœ˜K˜—Kšœ&™&K˜š  œžœ žœ˜%K˜Kšœžœ˜ Kšœžœ˜K˜šžœ žœ˜K˜/K˜Kšžœ žœ7˜FKšœ˜—K˜2Kšžœžœ˜Kšœ˜K˜—š œžœžœžœ žœžœ žœžœ˜UK˜Kšœžœ˜K˜šžœ žœ˜K˜Kšžœ žœ;˜JKšœ˜—K˜ K˜0Kšžœžœ˜Kšœ˜K˜—š œžœžœ˜3K˜šžœ˜ K˜3Kšœžœ žœ.˜P—Kšœ˜K˜——š œžœžœžœžœžœžœžœ˜\Kšžœ.˜4Kšœ˜K˜K˜—Kšœ™K˜K˜Kšœ žœžœ˜CKšœ žœ žœ ˜)Kšœ1žœ˜KKšœ%žœ ˜9Kšœ%žœ ˜8Kšœ%žœ ˜8K˜Kšœ˜K˜Kšž˜K˜Kšœžœ˜2K˜Kšœžœ'˜@K˜Kšœžœ@žœ˜fK˜KšœžœD˜\K˜Kšœžœ)˜AK˜Kšœžœ*˜DK˜K˜$K˜Kšœžœ/˜IK˜K˜XK˜TK˜K˜V—…—%„8Σ