<> <> <> <> <> <> <> <> DIRECTORY Basics USING [BYTE, DivMod, LongDiv, LongMult], DeviceCleanup USING [Await, Item, Perform, Reason], DoradoInputOutput USING [GetMemConfig, Halt, pagesPerBank, RWMufMan], MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], MPCodes USING [Code, emptyMP, powerOff], PrincOps USING [aSETMP, aTEXTBLT, BitBltTable, BitBltTablePtr, ControlLink, FrameHandle, maxPagesInVM, PageCount, PageNumber, RealPageNumber, SD, StateVector, sUnimplemented, VersionResult, zMISC], PrincOpsUtils USING [BITBLT, BITAND, BITOR, Copy, DisableInterrupts, EnableInterrupts, GetReturnFrame, GetReturnLink, LongCopy, MyLocalFrame], ProcessorFace USING [GetClockPulses, gmtEpoch, GreenwichMeanTime, ProcessorID, SetMP], SoftwareTextBlt USING [TextBlt], TerminalDefs USING [Cursor, Position], TrapSupport USING [BumpPC, OpTrapTable, opTrapTable]; ProcessorHeadDorado: MONITOR -- Protects GreenwichMeanTime calculation IMPORTS Basics, DeviceCleanup, DoradoInputOutput, PrincOpsUtils, ProcessorFace, SoftwareTextBlt, TrapSupport EXPORTS DoradoInputOutput, MicrocodeBooting, ProcessorFace SHARES ProcessorFace = { OPEN DoradoInputOutput; <> <> Go: PUBLIC SAFE PROC = CHECKED { <> }; 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 }; <> processorID: PUBLIC ProcessorFace.ProcessorID _ GetProcessorID[]; baseProcessorIDDorado: ProcessorFace.ProcessorID = [a: 0, b: 52612B, c: 100000B]; GetProcessorID: PRIVATE PROC RETURNS [ProcessorFace.ProcessorID] = { doradoSN: [0..377B] _ 0; FOR i: CARDINAL IN [0..7] DO doradoSN _ 2*doradoSN + RWMufMan[[useDMD: FALSE, dMuxAddr: 2220B+i]].dMuxData; ENDLOOP; RETURN[[a: baseProcessorIDDorado.a, b: baseProcessorIDDorado.b, c: baseProcessorIDDorado.c + doradoSN]] -- note most significant first }; <> dedicatedRealMemory: PUBLIC PrincOps.PageCount _ 0; firstSpecialRealPage: PUBLIC PrincOps.RealPageNumber _ 0; specialRealPages: PUBLIC PrincOps.PageCount _ 0; <> GetNextAvailableVM: PUBLIC SAFE PROC [page: PrincOps.PageNumber] RETURNS [firstPage: PrincOps.PageNumber, count: PrincOps.PageCount] = TRUSTED { 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 _ TRUE; <> <> <> page1: PrincOps.PageNumber = 1B; <> page376B: PrincOps.PageNumber = 376B; <> pageIO: PrincOps.PageNumber = 377B; <> pageFirstUnimplemented: PrincOps.PageNumber = IF GetMemConfig[].virtualBanks > PrincOps.maxPagesInVM/pagesPerBank THEN PrincOps.maxPagesInVM ELSE Basics.LongMult[GetMemConfig[].virtualBanks, pagesPerBank]; <> microsecondsPerHundredPulses: PUBLIC CARDINAL _ 32*100; <> cvTimeoutMask: WORD = 100000B; -- Dorado microcode assumes level 0 reservedNakedNotifyMask: PUBLIC WORD _ cvTimeoutMask; <> millisecondsPerTick: PUBLIC CARDINAL _ 40; -- the correct value is set by UserTerminalHead InitializeCVTimeouts: PROC = { DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[421B]]; DIW^ _ PrincOpsUtils.BITOR[DIW^, cvTimeoutMask]; }; <> 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 = Basics.LongDiv[1D6*100, microsecondsPerHundredPulses]; <> BootButton: PUBLIC SAFE PROC = TRUSTED { PrincOpsUtils.DisableInterrupts[]; [] _ RWMufMan[[useDMD: TRUE, dMuxAddr: 2264B]]; -- Request BaseBoard boot DO ENDLOOP; }; PowerOff: PUBLIC SAFE PROC [returnIfDisabled: BOOL _ FALSE] = TRUSTED { OPEN ProcessorFace; timeToGo: LONG INTEGER; IF powerOffCount # 0 AND returnIfDisabled THEN RETURN; PrincOpsUtils.DisableInterrupts[]; DeviceCleanup.Perform[turnOff]; DO SetMP[MPCodes.powerOff]; IF powerOffCount = 0 THEN EXIT; ENDLOOP; timeToGo _ gmtAutomaticPowerOn - GetGreenwichMeanTime[]; <> <> <> SELECT TRUE FROM gmtAutomaticPowerOn = gmtEpoch-1 => [] _ RWMufMan[[useDMD: TRUE, dMuxAddr: 2262B]]; timeToGo < 26 => BootButton[]; ENDCASE => [] _ RWMufMan[[useDMD: TRUE, dMuxAddr: IF timeToGo >= (200000B*256)/10 THEN 2262B ELSE 2263B]]; Halt[Basics.LongDiv[timeToGo * 10, 256]]; }; 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 { gmtAutomaticPowerOn _ gmt}; ResetAutomaticPowerOn: PUBLIC SAFE PROC = TRUSTED { gmtAutomaticPowerOn _ ProcessorFace.gmtEpoch - 1; -- infinity }; <> BootSpecificMicrocode: PUBLIC PROC [bfn: MicrocodeBooting.BootFileNumber] = { microcodeBFNOffset: CARDINAL = 3000B; -- microcode boot server uses offset BFNs ubfn: CARDINAL _ bfn-microcodeBFNOffset; bootParameterSeal: CARDINAL = 56623B; PushBootParams: PROC [ubfn, seal, checksum: CARDINAL] = MACHINE CODE {}; <> <> <> IF bfn#MicrocodeBooting.nullBootFileNumber THEN PushBootParams[ubfn, bootParameterSeal, 0-(ubfn+bootParameterSeal)]; BootButton[]; }; GetBootFileNumber: PUBLIC PROC [type: MicrocodeBooting.MicrocodeType] RETURNS [bfn: MicrocodeBooting.BootFileNumber] = { RETURN[[ SELECT type FROM altoMesa => 3110B, lisp => 3112B, smalltalk76 => 3111B, smalltalk80 => MicrocodeBooting.nullBootFileNumber, pilotMesa, cedarMesa => 3113B, ENDCASE => 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 Basics.BYTE; 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 }; <> <> <> TEXTBLTTrap: PROC = { <> TextBlt: PROC = LOOPHOLE[SoftwareTextBlt.TextBlt]; TrapSupport.BumpPC[2]; TextBlt[]; }; <> <<(Needs to be fixed-frame because SetMP may occur in contexts where>> <> InitSetMPTrap: PROC = { GetCode: PROC RETURNS [code: MPCodes.Code] = MACHINE CODE {}; code: MPCodes.Code; cursorPtr: LONG POINTER TO TerminalDefs.Cursor = LOOPHOLE[LONG[431B]]; state: MACHINE DEPENDENT RECORD [a, b: UNSPECIFIED, v: PrincOps.StateVector]; TrapSupport.opTrapTable.misc[PrincOps.aSETMP].frame _ PrincOpsUtils.MyLocalFrame[]; state.v _ STATE; PrincOpsUtils.DisableInterrupts[]; DO state.v.dest _ PrincOpsUtils.GetReturnLink[]; PrincOpsUtils.EnableInterrupts[]; TRANSFER WITH state.v; <> PrincOpsUtils.DisableInterrupts[]; code _ GetCode[]; state.v _ STATE; TrapSupport.BumpPC[2]; IF code = MPCodes.emptyMP THEN cursorPtr^ _ savedCursor ELSE { <> <> cursorPosition: LONG POINTER TO TerminalDefs.Position = LOOPHOLE[LONG[426B]]; digit, digitOffset: CARDINAL; cursorPosition^ _ [x: 304, y: 404]; FOR i: CARDINAL IN [0..15] DO cursorPtr[i] _ 0; ENDLOOP; FOR i: CARDINAL DECREASING IN [0..2] DO [code, digit] _ Basics.DivMod[code, 10]; digitOffset _ digit*5; bbPtr^ _ [ dst: [word: cursorPtr, bit: 5*i], dstBpl: 16, src: [word: @digitFont + digitOffset/16, bit: digitOffset MOD 16], srcDesc: [srcBpl[64]], width: 5, height: 6, flags: [disjoint: TRUE, dstFunc: or]]; PrincOpsUtils.BITBLT[bbPtr]; ENDLOOP; }; ENDLOOP; }; <> <> <> <> bbTable: ARRAY[0..SIZE[PrincOps.BitBltTable]+1) OF UNSPECIFIED; bbPtr: PrincOps.BitBltTablePtr = LOOPHOLE[PrincOpsUtils.BITAND[LOOPHOLE[@bbTable+1], 177776B] ]; digitFont: ARRAY [0..24) OF CARDINAL _ [ <> 30614B, 61474B, 167461B, 117000B, 45222B, 112441B, 512B, 57000B, 54202B, 22471B, 141062B, 57000B, 64214B, 14405B, 21111B, 157000B, 44220B, 117645B, 22110B, 57000B, 31736B, 60430B, 142063B, 117000B]; <> savedCursor: PUBLIC TerminalDefs.Cursor _ ALL[0]; <> 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: dorado, majorVersion: 0, unused: 0, floatingPoint: FALSE, cedar: FALSE, releaseDate: ProcessorFace.gmtEpoch/86400]]; }; <<>> <> InitializeCVTimeouts[]; PrincOps.SD[PrincOps.sUnimplemented] _ LOOPHOLE[UnimplementedTrap]; PrincOps.SD[137B] _ LOOPHOLE[@trapTable]; InitSetMPTrap[]; TrapSupport.opTrapTable.misc[PrincOps.aTEXTBLT] _ LOOPHOLE[TEXTBLTTrap]; TrapSupport.opTrapTable.misc[100B] _ LOOPHOLE[LocalBlkZ]; TrapSupport.opTrapTable.misc[102B] _ LOOPHOLE[LongBlkZ]; TrapSupport.opTrapTable.misc[104B] _ LOOPHOLE[UVersion]; ResetAutomaticPowerOn[]; }. December 5, 1980 5:39 PM Taft Convert for Dorado; mostly remove D0 I/O junk December 11, 1980 12:55 PM Taft Maint panel in cursor 9-Jun-81 18:59:01 Taft Export savedCursor; use it when SetMP code = cClient 7-Jul-81 19:50:43 Taft Use TrapSupport; pass TextBlt trap off to SoftwareTextBlt; fully implement GetNextAvailableVM; add PowerOff and residual stuff from GMTUsingIntervalTimer. 17-Aug-81 13:55:50 Taft Fixed frame handler for SetMP trap. 21-Aug-81 9:54:25 Taft BootButton now requests BaseBoard boot. 26-Sep-81 13:22:52 Taft Fix bug in PowerOff; fully implement SetAutomaticPowerOn. 22-Jun-82 14:59:02 Taft Implement and export MicrocodeBooting. 14-Jul-82 12:36:50 Taft Add trap support for LocalBlkZ, LongBlkZ, and UVersion opcodes. September 28, 1982 3:55 pm Taft Do arithmetic right in PowerOff February 13, 1983 1:21 pm Taft Remove machine code procs to DoradoInputOutput February 27, 1983 2:31 pm Taft Export HeadStartChain.Start; absorb TrapSupportImpl April 8, 1983 5:39 pm Levin Convert to Cedar Nucleus