<> <> <> <> <> <> <> <<>> DIRECTORY Basics USING [BITOR, LongDiv], D0InputOutput USING [ControllerNumber, ControllerType, CSBArray, Input, null, nullControllerNumber, rdc, rdcWithServiceLate], DeviceCleanup USING [Await, Item, Perform, Reason], MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], PrincOps USING [aLOADRAMJ, aREADRAM, ControlLink, FrameHandle, PageCount, RealPageNumber, SD, StateVector, sUnimplemented, PageNumber, VersionResult, wordsPerPage, zMISC], PrincOpsUtils USING [Copy, DisableInterrupts, LongCopy, GetReturnFrame, GetReturnLink, MyLocalFrame], ProcessorFace USING [GetClockPulses, gmtEpoch, GreenwichMeanTime, ProcessorID], TrapSupport USING [BumpPC, OpTrapTable, opTrapTable]; ProcessorHeadD0: MONITOR -- Protects GreenwichMeanTime calculation IMPORTS Basics, D0InputOutput, DeviceCleanup, PrincOpsUtils, ProcessorFace, TrapSupport EXPORTS D0InputOutput, MicrocodeBooting, ProcessorFace SHARES ProcessorFace = PUBLIC { OPEN D0InputOutput; <<>> <> IOPage: LONG POINTER TO CSBArray _ LOOPHOLE[pageIO*PrincOps.wordsPerPage]; firstController: ControllerNumber = 4B; -- tasks 0B thru 3B taken up by emulator lastController: ControllerNumber = 15B; -- tasks 16B and 17B taken by timers and faults ControllerIndex: TYPE = ControllerNumber [firstController..lastController]; controllerRoster: ARRAY ControllerIndex OF ControllerType _ ALL[null]; GetNextController: PROC [type: ControllerType, prev: ControllerNumber] RETURNS [ControllerNumber] = { i: ControllerIndex; FOR i DECREASING IN ControllerIndex DO IF type = controllerRoster[i] AND (prev = nullControllerNumber OR prev > i) THEN RETURN[i]; ENDLOOP; RETURN[nullControllerNumber] }; InitializeD0InputOutput: PRIVATE PROC = { IDRegister: TYPE = MACHINE DEPENDENT RECORD [ type: ControllerType, lowByte: [0..256)]; r: IDRegister; -- code generator bug in 6.0n requires this idRegNo: [0..17B] = 0; i: ControllerIndex; t: ControllerType; <> FOR i IN ControllerIndex DO r _ LOOPHOLE[Input[[controller: i, register: idRegNo]], IDRegister]; t _ r.type; IF t = rdcWithServiceLate THEN t _ rdc; -- #*%$@!! RDC controllerRoster[i] _ t; ENDLOOP; }; <<>> <> <> processorID: ProcessorFace.ProcessorID _ GetProcessorID[]; GetProcessorID: PRIVATE PROC RETURNS [ProcessorFace.ProcessorID] = { csw: CSWord = ReadRam[7777B]; CSWord: TYPE = MACHINE DEPENDENT RECORD [ bits16To31: CARDINAL, bits0To15: CARDINAL, bits32To35: [0..17B], address: [0..7777B]]; ReadRam: PROC [address: [0..7777B]] RETURNS [CSWord] = MACHINE CODE { PrincOps.zMISC, PrincOps.aREADRAM }; RETURN[[0, csw.bits0To15, csw.bits16To31]] -- note most significant first }; <> dedicatedRealMemory: PrincOps.PageCount _ 0; firstSpecialRealPage: PUBLIC PrincOps.RealPageNumber _ 0; specialRealPages: PUBLIC PrincOps.PageCount _ 0; <> GetNextAvailableVM: SAFE PROC [page: PrincOps.PageNumber] RETURNS [firstPage: PrincOps.PageNumber, count: PrincOps.PageCount] = CHECKED { IF page < page1 THEN RETURN[page, page1 - page]; page _ MAX[page, page1 + 1]; IF page < page376B THEN RETURN[page, page376B - page]; page _ MAX[page, page376B + 1]; IF page < pageIO THEN RETURN[page, pageIO - page]; page _ MAX[page, pageIO + 1]; IF page < pageFirstUnimplemented THEN RETURN[page, pageFirstUnimplemented - page]; RETURN[LAST[PrincOps.PageNumber], 0]; }; useLongMapOps: PUBLIC BOOL _ FALSE; <> page1: PRIVATE PrincOps.PageNumber = 1B; <> page376B: PRIVATE PrincOps.PageNumber = 376B; <> pageIO: PRIVATE PrincOps.PageNumber = 377B; -- "official" D0 I/O page pageFirstUnimplemented: PRIVATE PrincOps.PageNumber = 40000B; <<[pageFirstUnimplemented..LAST[PageNumber]] not implemented>> <> microsecondsPerHundredPulses: CARDINAL; InitializeClockRate: PRIVATE PROC = { ReadRegister: PROC [address: [0..377B]] RETURNS [UNSPECIFIED] = MACHINE CODE { PrincOps.zMISC, 106B}; <> <> clockRate: CARDINAL = ReadRegister[323B]; microsecondsPerHundredPulses _ Basics.LongDiv[LONG[100]*64*320, clockRate]; }; <> GetGreenwichMeanTime: PUBLIC ENTRY SAFE PROC RETURNS [ProcessorFace.GreenwichMeanTime] = CHECKED{ OPEN ProcessorFace; ENABLE UNWIND => NULL; IF gmtSimulated ~= gmtEpoch THEN {-- don't update clock unless it has been set seconds: GreenwichMeanTime = (GetClockPulses[] - pulsesGmtSimulated)/pulsesPerSecond; pulsesGmtSimulated _ pulsesGmtSimulated + seconds*pulsesPerSecond; -- long multiply! gmtSimulated _ gmtSimulated + seconds; }; RETURN[gmtSimulated] }; SetGreenwichMeanTime: PUBLIC ENTRY SAFE PROC [gmt: ProcessorFace.GreenwichMeanTime] = CHECKED { ENABLE UNWIND => NULL; pulsesGmtSimulated _ ProcessorFace.GetClockPulses[]; gmtSimulated _ gmt }; gmtSimulated: ProcessorFace.GreenwichMeanTime _ ProcessorFace.gmtEpoch; -- => not set pulsesGmtSimulated: LONG CARDINAL; -- interval timer value corresponding to gmtSimulated pulsesPerSecond: LONG CARDINAL; <> cvTimeoutMask: PRIVATE WORD = 100000B; -- D0 microcode assumes level 0 reservedNakedNotifyMask: WORD _ cvTimeoutMask; <> <<>> millisecondsPerTick: PUBLIC CARDINAL _ 40; -- the correct value is set by UserTerminalHead InitializeCVTimeouts: PRIVATE PROC = { DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[421B]]; DIW^ _ Basics.BITOR[DIW^, cvTimeoutMask]; }; <> BootButton: SAFE PROC = TRUSTED { LoadRam: PROC [pMicrocode: LONG POINTER, andJump: BOOL] = MACHINE CODE { PrincOps.zMISC, PrincOps.aLOADRAMJ }; bootMe: ARRAY [0..7) OF WORD _ [000000B, 170000B, 000047B, 015000B, 177760B, 163351B, 007400B]; LoadRam[@bootMe, TRUE] -- never returns }; PowerOff: PUBLIC SAFE PROC [returnIfDisabled: BOOL _ FALSE] = TRUSTED { OPEN ProcessorFace; IF powerOffCount # 0 AND returnIfDisabled THEN RETURN; PrincOpsUtils.DisableInterrupts[]; DeviceCleanup.Perform[turnOff]; DO 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; SetAutomaticPowerOn: PUBLIC SAFE PROC [gmt: ProcessorFace.GreenwichMeanTime, externalEvent: BOOL] = TRUSTED { }; ResetAutomaticPowerOn: PUBLIC SAFE PROC = TRUSTED { }; <> 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: dolphin, majorVersion: 0, unused: 0, floatingPoint: FALSE, cedar: FALSE, releaseDate: ProcessorFace.gmtEpoch/86400]]; }; READRTrap: PROC [reg: [0..377]] RETURNS [UNSPECIFIED] = { <> <> TrapSupport.BumpPC[2]; RETURN [320]; }; <<>> <> Go: PUBLIC SAFE PROC = CHECKED{-- By now start trap has occurred and main-body code has run--}; InitializeCleanup: PUBLIC SAFE PROC = TRUSTED { OPEN DeviceCleanup; item: Item; reason: Reason; DO reason _ Await[@item]; SELECT reason FROM turnOff, kill => gmtSimulated _ ProcessorFace.gmtEpoch; ENDCASE ENDLOOP }; InitializeCVTimeouts[]; InitializeD0InputOutput[]; PrincOps.SD[PrincOps.sUnimplemented] _ LOOPHOLE[UnimplementedTrap]; PrincOps.SD[137B] _ LOOPHOLE[@trapTable]; TrapSupport.opTrapTable.misc[100B] _ LOOPHOLE[LocalBlkZ]; TrapSupport.opTrapTable.misc[102B] _ LOOPHOLE[LongBlkZ]; TrapSupport.opTrapTable.misc[104B] _ LOOPHOLE[UVersion]; TrapSupport.opTrapTable.misc[106B] _ LOOPHOLE[READRTrap]; InitializeClockRate[]; pulsesPerSecond _ Basics.LongDiv[1D6*100, microsecondsPerHundredPulses]; }. August 8, 1979 1:47 AM Redell Create file October 17, 1979 6:54 PM Redell Add patch to detect RDC thinking it's an old ethernet February 4, 1980 10:36 AM McJones Rename OISProcessorFaceD0Impl=>OISProcessorHeadD0; delete device registry/enumeration; add new OISProcessorFace items February 25, 1980 3:06 PM McJones Move export of millisecondsPerTick to UserTerminalHeadD0 April 30, 1980 10:17 AM Forrest Add InitializeCVTimeout May 14, 1980 4:27 PM McJones Add reservedNakedNotifyMask; remove Start from HeadStartChain (export to OISProcessorFace now); change GetNextController to deliver highest controller number first June 25, 1980 4:23 PM McJones Drop "OIS" from name; expand processor id to 48 bits. August 12, 1980 10:26 AM McJones Add dedicatedRealMemory; use MiscAlpha. August 26, 1980 11:17 AM McJones Change cvTimeoutMask for new process microcode. October 3, 1980 5:17 PM Forrest Move in unimplemented trap. February 4, 1981 1:08 PM Knutsen PrincOps fields changed names. 19-Jul-81 14:43:33 Taft Use TrapSupport to handle unimplemented opcode traps. 22-Jun-82 16:53:22 Taft Implement and export MicrocodeBooting; degenerate implementation for now. 14-Jul-82 15:56:50 Taft Add trap support for LocalBlkZ, LongBlkZ, and UVersion opcodes. October 4, 1982 12:50 pm Taft Init microsecondsPerHundredPulses according to system clock rate. October 8, 1982 3:07 pm Taft Don't InitializeClockRate until after trap support set up. February 27, 1983 2:31 pm Taft Export HeadStartChain.Start; absorb TrapSupportImpl November 3, 1983 10:51 am Birrell 5.0 conversion January 31, 1985 1:46:15 pm; Orr Take out ProcessorFaceExtras, change in PrincOps.SD