DIRECTORY DeviceCleanup USING [Perform], DisplayFace USING [Cursor, CursorPtr, Point], DoradoInputOutput USING [GetMemConfig, Halt, pagesPerBank, RWMufMan], MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], MicrocodeVersion USING [VersionResult], MPCodes USING [Code, emptyMP, powerOff], PrincOps USING [ aSETMP, aTEXTBLT, BitBltTable, BitBltTablePtr, BYTE, ControlLink, FrameHandle, maxPagesInVM, PageCount, PageNumber, SD, StateVector, sUnimplemented, zMISC], PrincOpsUtils USING [ BITBLT, BITAND, BITOR, COPY, DIVMOD, DisableInterrupts, EnableInterrupts, GetReturnFrame, GetReturnLink, LongCOPY, LongDiv, LongMult, MyLocalFrame], ProcessorFace USING [GetClockPulses, gmtEpoch, GreenwichMeanTime, ProcessorID, SetMP], SoftwareTextBlt USING [TextBlt], TrapSupport USING [BumpPC, OpTrapTable, opTrapTable]; ProcessorHeadDorado: PROGRAM IMPORTS DeviceCleanup, DoradoInputOutput, PrincOpsUtils, ProcessorFace, SoftwareTextBlt, TrapSupport EXPORTS DoradoInputOutput, MicrocodeBooting, ProcessorFace SHARES ProcessorFace = BEGIN OPEN DoradoInputOutput; Go: PUBLIC SAFE PROC = CHECKED{ -- By now start trap has occurred and main-body code has run--}; 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; 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] }; 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 PrincOpsUtils.LongMult[GetMemConfig[].virtualBanks, pagesPerBank]; microsecondsPerHundredPulses: PUBLIC CARDINAL _ 32*100; cvTimeoutMask: WORD = 100000B; -- Dorado microcode assumes level 0 reservedNakedNotifyMask: PUBLIC WORD _ cvTimeoutMask; InitializeCVTimeouts: PROC = { DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[421B]]; DIW^ _ PrincOpsUtils.BITOR[DIW^, cvTimeoutMask]; }; GetGreenwichMeanTime: PUBLIC SAFE PROC RETURNS [ProcessorFace.GreenwichMeanTime] = CHECKED{ OPEN ProcessorFace; 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 SAFE PROC [gmt: ProcessorFace.GreenwichMeanTime] = CHECKED{pulsesGmtSimulated _ ProcessorFace.GetClockPulses[]; gmtSimulated _ gmt}; gmtSimulated: ProcessorFace.GreenwichMeanTime _ ProcessorFace.gmtEpoch; -- => not set pulsesGmtSimulated: LONG CARDINAL; -- interval timer value corresponding to gmtSimulated pulsesPerSecond: LONG CARDINAL = PrincOpsUtils.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 = TRUSTED { OPEN ProcessorFace; timeToGo: LONG INTEGER; PrincOpsUtils.DisableInterrupts[]; DeviceCleanup.Perform[turnOff]; SetMP[MPCodes.powerOff]; timeToGo _ gmtAutomaticPowerOn - GetGreenwichMeanTime[]; IF gmtAutomaticPowerOn = gmtEpoch-1 THEN [] _ RWMufMan[[useDMD: TRUE, dMuxAddr: 2262B]] ELSE IF timeToGo<26 THEN BootButton[] ELSE [] _ RWMufMan[[useDMD: TRUE, dMuxAddr: IF timeToGo >= (200000B*256)/10 THEN 2262B ELSE 2263B]]; Halt[PrincOpsUtils.LongDiv[timeToGo * 10, 256]]; }; 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 PrincOps.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]]; 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[]; }; InitSetMPTrap: PROC = { GetCode: PROC RETURNS [code: MPCodes.Code] = MACHINE CODE {}; code: MPCodes.Code; cursorPtr: DisplayFace.CursorPtr = 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 DisplayFace.Point = 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] _ PrincOpsUtils.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 = PrincOpsUtils.BITAND[@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 DisplayFace.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 [MicrocodeVersion.VersionResult] = { TrapSupport.BumpPC[2]; RETURN [[ machineType: dorado, majorVersion: 0, unused: 0, floatingPoint: FALSE, cedar: FALSE, releaseDate: ProcessorFace.gmtEpoch/86400]]; }; InitializeCVTimeouts[]; PrincOps.SD[PrincOps.sUnimplemented] _ UnimplementedTrap; PrincOps.SD[137B] _ @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[]; END. 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 ÎProcessorHeadDorado.mesa Last Edited by: Taft, February 27, 1983 3:29 pm Last Edited by: Levin, April 22, 1983 3:38 pm Last Edited by: Birrell, July 8, 1983 2:40 pm ProcessorFace Initialization Processor id Real memory configuration Virtual memory layout I/O page for Alto-compatible display, cursor, mouse coords. NOTE: even though we declare this page off-limits, boot files may contain data for it. Therefore, boot devices (disk and Ethernet) CANNOT use page1 for their CSBs. I/O page for Alto-compatible keyboard/mouse bitmap I/O page for newly-written device microcode First nonexistent VM page. Interval time Naked notifies Condition variable time millisecondsPerTick is exported by UserTerminalHeadDorado, since its value depends on the display refresh rate. Greenwich mean time Booting and power control Manifold 2262 turns the machine off indefinitely. Manifold 2263 turns the machine off for a specified interval in units of 25.6 sec. The interval must be left on the BMux when the machine halts. MicrocodeBooting Push sealed and checksum boot file parameters on the stack for Initial to look at. Note: in general calling BootButton with a non-empty stack would be illegal, but is OK here because BootButton calls only machine code procedures. 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.) Handler for TEXTBLT trap. The opcode actually takes a pile of arguments and returns a pile of results. The trap handler is defined strangely in order to avoid needless pushing and popping. TEXTBLT is a minimal-stack instruction, so no need to save state vector. Fixed-frame handler for SetMP trap. (Needs to be fixed-frame because SetMP may occur in contexts where frame allocation is impossible.) SetMP trap enters here with code on top of stack. I should use the procedures exported through DisplayFace to do this, but DisplayHeadDorado may not have been STARTed yet (or may not exist). These belong in SETMPTrap's local frame, but are here in the global frame because if SETMPTrap's local frame is too large it causes frame allocation traps during early initialization when they can't be handled. Note: PrincOps BBTable must be 16-word aligned, but Dorado requires only 2-word. Strike-format font, densely packed, characters 6 high, 5 wide SetCursorPattern stores a copy of the real cursor here, and the SetMP trap handler copies this into the real cursor whenever a code of emptyMP is posted, thereby restoring the client's cursor across world-swaps. This can't be done by UserTerminalHeadDorado's cleanup procedure, because calls to cleanup procedures are surrounded by SetMPs, thereby clobbering the cursor. Trap support for Cedar-related opcodes Initialization Ê ˜Jšœ™Jšœ/™/J™-Jšœ-™-šÏk ˜ Jšœœ ˜Jšœ œ˜-Jšœœ.˜EJšœœ5˜KJšœœ˜'Jšœœ˜(šœ œ˜Jšœ/œAœ&˜œ—šœœ˜Jšœœœœq˜”—JšœœC˜VJšœœ ˜ Jšœ œ$˜5J˜—šœ˜š˜Jšœ\˜\—Jšœ3˜:Jšœ˜J˜—Jš˜J˜Jšœ˜J˜Jšœ ™ J˜Jšœ™J˜Jš ÏnœœœœœÏc>œ˜`J˜Jšœ ™ J˜Jšœ œ.˜AJ˜Qšžœœœœ ˜DJ˜šœœœ˜Jšœ*œ˜NJšœ˜—šœ˜#J˜Jšœ(Ÿ˜F—Jšœ˜J˜—Jšœ™J˜Jšœœ˜3J˜Jšœ™J˜šžœœœœ˜@Jšœ?œ˜OJšœœœ˜0Jšœœ˜Jšœœœ˜6Jšœœ˜Jšœœœ˜2Jšœœ˜Jšœ œ&˜RJšœœ˜$Jšœ˜J˜—Jšœ;™;Jšœ¤™¤J˜ J˜Jšœ2™2J˜%J˜Jšœ+™+J˜#J˜Jšœ™˜-šœA˜HJšœ˜—JšœC˜GJ˜—Jšœ ™ Jšœœœ ˜7J˜Jšœ™Jšœœ Ÿ#˜BJšœœœ˜5J˜Jšœ™Jšœ:™:Jšœ4™4šžœœ˜Jšœœœœœœœ˜1Jšœœœ˜0Jšœ˜J˜—Jšœ™J˜š žœœœœœ%œ˜[Jšœ˜šœœŸ,˜O˜J˜8—JšœDŸ˜UJ˜&Jšœ˜—Jšœ˜Jšœ˜J˜—šžœœœœ)˜OJšœJ˜QJ˜—JšœIŸ ˜VJšœœœŸ5˜Yšœœœ˜ Jšœ=˜=—J˜Jšœ™J˜š ž œœœœœ˜(J˜"JšœœŸ˜JJšœœ˜ Jšœ˜J˜—š žœœœœœ˜&Jšœ˜Jšœ œœ˜J˜"J˜J˜J˜8Jšœ1™1JšœR™RJšœ=™=Jšœ"œœ˜WJšœœ œ ˜%šœœ˜!Jšœ œœœ ˜B—J˜0Jšœ˜J˜—J˜5J˜šžœœœœ˜'Jšœ5œœ˜FJšœ˜J˜—š žœœœœœ˜3Jšœ3Ÿ ˜>Jšœ˜J˜J˜—Jšœ™J˜šžœœœ+˜MJšœœ Ÿ)˜OJšœœ˜(Jšœœ ˜%Jš žœœœœœ˜HJšœR™RJšœL™LJšœE™Ešœ)˜/J˜D—J˜ Jšœ˜J˜—šžœœœ'˜EJšœ+˜2šœ˜šœ˜J˜J˜J˜J˜3J˜Jšœ*˜1——Jšœ˜J˜J˜—Jšœ ™ J˜Jšœœœ˜'J˜šž œœ˜Jš œœ œœ œ˜MJšœ œ˜Jšœ˜Jšœ˜J˜—˜$Jš œœœœœ˜=J˜J˜—Jšœ™Jšœ5™5JšœU™UJšœL™Lšžœœ˜J˜Jšœœœœœœœ œ˜;J˜J˜Jšœœ˜J˜1Jšœœ#˜2J˜šœ œœ%˜QJšœ2˜6—Jšœ:™:JšœF™FJšœœ!˜9JšœœŸ3˜FJšœ˜J˜—Jšœ™JšœL™LJšœU™Ušž œœ˜JšœH™HJšžœœœ˜2J˜J˜ Jšœ˜J˜—Jšœ#™#JšœB™BJšœ ™ šž œœ˜Jš žœœœœœ˜=J˜Jšœ#œœ˜8Jš œœ œœ œ˜MJ˜J˜SJšœ œ˜J˜"J˜Jš˜J˜-J˜!Jšœœ ˜Jšœ1™1J˜"J˜Jšœ œ˜J˜Jšœœ˜7šœ˜JšœD™DJšœG™GJš œœœœœœ˜IJšœœ˜J˜#Jš œœœ œœ˜8š œœ œœ˜'Jšœœ ˜/J˜˜ J˜!J˜ Jšœ:œ˜BJ˜Jšœ'œ˜;—Jšœœ˜Jšœ˜—Jšœ˜—Jšœ˜Jšœ˜J˜—JšœI™IJšœP™PJšœ7™7JšœP™PJš œ œœœ œ˜?Jšœ/œ˜Kšœ œ œœ˜(šœ=™=J˜"J˜"J˜"J˜"J˜"J˜#J˜——JšœR™RJšœN™NJšœH™HJšœO™OJšœ8™8Jšœ œœ˜0J˜Jšœ&™&J˜šž œœ œ˜%J˜Jšœœ˜ Jšœœ˜J˜šœ œ˜J˜/J˜Jšœ œœ$˜FJšœ˜—J˜2Jšœœ˜Jšœ˜J˜—šžœœœœ œœ œœ˜UJ˜Jšœœ˜J˜šœ œ˜J˜Jšœ œ;˜JJšœ˜—J˜ J˜0Jšœœ˜Jšœ˜J˜—šžœœœ%˜;J˜šœ˜ J˜0Jšœœ œ.˜P—Jšœ˜J˜—J™Jšœ™J˜J˜Jšœ œ.˜9Jšœ œ˜J˜Jšœ2œ˜HJšœ%œ ˜9Jšœ%œ ˜8Jšœ%œ ˜8J˜J˜Jšœ˜J˜Jšœœ+œœ˜Lšœœ˜6J˜KJ˜±—J˜;J˜?J˜QJ˜>J˜WJ˜AJ˜OJ˜TJ˜4J˜J˜—…—)A