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; 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]]; 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 ΚProcessorHeadD0.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Taft, February 27, 1983 3:26 pm Birrell, November 3, 1983 1:19 pm Willie-Sue, January 31, 1985 1:47:52 pm PST Russ Atkinson (RRA) February 27, 1985 8:31:58 pm PST Doug Wyatt, February 26, 1985 5:55:44 pm PST D0InputOutput Initialization microcode really should have put roster into memory somewhere. ProcessorFace Processor id Real memory configuration Virtual memory layout The Dolphin can not use the long map ops. I/O page for Alto-compatible Diablo31, display, cursor, mouse coords I/O page for Alto-compatible keyboard/mouse bitmap [pageFirstUnimplemented..LAST[PageNumber]] not implemented Interval time The number read here is proportional to clock ticks per unit of time, where the value 320 denotes 1 tick every 64 microseconds. Greenwich mean time Naked notifies Condition variable time Booting and power control 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 If READR traps, assume we are reading the clock rate (see InitializeClockRate above) and return a value denoting a 40 MHz crystal and 2560 cycles per clock tick. Initialization Κ [˜codešœ™Kšœ Οmœ1™œ˜_K˜š  œžœžœžœžœ˜/Kšžœ˜K˜ K˜šž˜K˜šžœž˜Kšœ7˜7Kšž˜—Kšž˜—Kšœ˜—K˜K˜K˜Kšœ žœžœ˜CKšœ žœ žœ ˜)Kšœ%žœ ˜9Kšœ%žœ ˜8Kšœ%žœ ˜8Kšœ%žœ ˜9K˜KšœH˜HK˜Kšœ˜K˜Kšœžœ˜.K˜Kšœžœ žœ˜ZK˜Kšœžœ‚˜œK˜KšœžœE˜_K˜Kšœžœ$˜