-- ProcessorHeadD0.mesa -- Last Edited by: Taft, February 27, 1983 3:26 pm DIRECTORY D0InputOutput USING [ControllerNumber, ControllerType, CSBArray, Input, null, nullControllerNumber, rdc, rdcWithServiceLate], Environment USING [Byte, PageCount, PageNumber, wordsPerPage], Frame USING [GetReturnFrame, GetReturnLink, MyLocalFrame], HeadStartChain USING [], Inline USING [BITOR, COPY, LongCOPY, LongDiv], MicrocodeBooting USING [BootFileNumber, MicrocodeType, nullBootFileNumber], MicrocodeVersion USING [VersionResult], MiscAlpha USING [aLOADRAMJ, aREADRAM], Mopcodes USING [zMISC], PrincOps USING [ControlLink, FrameHandle, StateVector], ProcessorFace USING [ProcessorID], SDDefs USING [SD, sUnimplemented], System USING [gmtEpoch], TrapSupport USING [BumpPC, OpTrapTable, opTrapTable]; ProcessorHeadD0: PROGRAM IMPORTS Frame, D0InputOutput, Inline, TrapSupport EXPORTS D0InputOutput, HeadStartChain, MicrocodeBooting, ProcessorFace SHARES ProcessorFace = PUBLIC BEGIN OPEN D0InputOutput; -- -- D0InputOutput IOPage: LONG POINTER TO CSBArray _ LOOPHOLE[LONG[pageIO*Environment.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] = BEGIN i: ControllerIndex; FOR i DECREASING IN ControllerIndex DO IF type = controllerRoster[i] AND (prev = nullControllerNumber OR prev > i) THEN RETURN[i]; ENDLOOP; RETURN[nullControllerNumber] END; InitializeD0InputOutput: PRIVATE PROC = BEGIN 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; -- Initialization microcode really should have put roster into memory somewhere. 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; END; -- -- ProcessorFace -- Initialization -- This is exported BOTH to ProcessorFace and to HeadStartChain. -- Consequently it must not do anything besides cause a start trap on the first call. Start: PROC = {-- By now start trap has occurred and main-body code has run--}; -- Processor id processorID: ProcessorFace.ProcessorID _ GetProcessorID[]; GetProcessorID: PRIVATE PROC RETURNS [ProcessorFace.ProcessorID] = BEGIN 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 BEGIN Mopcodes.zMISC, MiscAlpha.aREADRAM END; RETURN[[0, csw.bits0To15, csw.bits16To31]] -- note most significant first END; -- Real memory configuration dedicatedRealMemory: Environment.PageCount _ 0; -- Virtual memory layout GetNextAvailableVM: PROC [page: Environment.PageNumber] RETURNS [firstPage: Environment.PageNumber, count: Environment.PageCount] = BEGIN 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[Environment.PageNumber], 0]; END; page1: PRIVATE Environment.PageNumber = 1B; -- I/O page for Alto-compatible Diablo31, display, cursor, mouse coords page376B: PRIVATE Environment.PageNumber = 376B; -- I/O page for Alto-compatible keyboard/mouse bitmap pageIO: PRIVATE Environment.PageNumber = 377B; -- "official" D0 I/O page pageFirstUnimplemented: PRIVATE Environment.PageNumber = 40000B; -- [pageFirstUnimplemented..LAST[PageNumber]] not implemented -- Interval time microsecondsPerHundredPulses: CARDINAL; InitializeClockRate: PRIVATE PROC = BEGIN ReadRegister: PROC [address: [0..377B]] RETURNS [UNSPECIFIED] = MACHINE CODE { Mopcodes.zMISC, 106B}; -- The number read here is proportional to clock ticks per unit of time, -- where the value 320 denotes 1 tick every 64 microseconds. clockRate: CARDINAL = ReadRegister[323B]; microsecondsPerHundredPulses _ Inline.LongDiv[LONG[100]*64*320, clockRate]; END; -- Naked notifies cvTimeoutMask: PRIVATE WORD = 100000B; -- D0 microcode assumes level 0 reservedNakedNotifyMask: WORD _ cvTimeoutMask; -- Condition variable time -- millisecondsPerTick is exported by UserTerminalHeadD0, -- since its value depends on the display refresh rate. InitializeCVTimeouts: PRIVATE PROC = BEGIN DIW: LONG POINTER TO WORD = LOOPHOLE[LONG[421B]]; DIW^ _ Inline.BITOR[DIW^, cvTimeoutMask]; END; -- Booting and power control BootButton: PROC = BEGIN LoadRam: PROC [pMicrocode: LONG POINTER, andJump: BOOLEAN] = MACHINE CODE BEGIN Mopcodes.zMISC, MiscAlpha.aLOADRAMJ END; bootMe: ARRAY [0..7) OF WORD _ [000000B, 170000B, 000047B, 015000B, 177760B, 163351B, 007400B]; LoadRam[@bootMe, TRUE] -- never returns END; -- MicrocodeBooting; degenerate implementation for now BootSpecificMicrocode: PUBLIC PROCEDURE [bfn: MicrocodeBooting.BootFileNumber] = BEGIN BootButton[]; END; GetBootFileNumber: PUBLIC PROCEDURE [type: MicrocodeBooting.MicrocodeType] RETURNS [bfn: MicrocodeBooting.BootFileNumber] = BEGIN RETURN[MicrocodeBooting.nullBootFileNumber]; END; -- TrapSupport. UnimplementedInstruction: ERROR = CODE; Unimplemented: PROCEDURE = BEGIN v: MACHINE DEPENDENT RECORD [a, b: UNSPECIFIED, state: PrincOps.StateVector]; v.state _ STATE; ERROR UnimplementedInstruction; END; trapTable: TrapSupport.OpTrapTable _ [ALL[LOOPHOLE[Unimplemented]], ALL[LOOPHOLE[Unimplemented]]]; -- 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. UnimplementedTrap: PROC = BEGIN l: PrincOps.ControlLink; code: LONG POINTER TO PACKED ARRAY [0..0) OF Environment.Byte; opcode: [0..400B); state: PrincOps.StateVector; state _ STATE; state.source _ l _ Frame.GetReturnLink[]; code _ LOOPHOLE[l.frame.accesslink.code.longbase]; opcode _ code[l.frame.pc]; state.dest _ IF opcode # Mopcodes.zMISC THEN TrapSupport.opTrapTable.main[opcode] ELSE TrapSupport.opTrapTable.misc[code[l.frame.pc+1]]; -- If handler is fixed-frame, manually plant the return link. -- (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 END; -- Trap support for Cedar-related opcodes LocalBlkZ: PROC [count: CARDINAL] = BEGIN state: PrincOps.StateVector; p: POINTER; state _ STATE; TrapSupport.BumpPC[2]; IF count#0 THEN BEGIN p _ @(Frame.GetReturnFrame[].local[0]); p^ _ 0; IF count#1 THEN Inline.COPY[from: p, to: p+1, nwords: count-1]; END; state.dest.frame _ Frame.GetReturnFrame[]; RETURN WITH state; END; LongBlkZ: PROC [p: LONG POINTER, count: CARDINAL] RETURNS [resultP: LONG POINTER] = BEGIN state: PrincOps.StateVector; state _ STATE; TrapSupport.BumpPC[2]; IF count#0 THEN BEGIN p^ _ 0; IF count#1 THEN Inline.LongCOPY[from: p, to: p+1, nwords: count-1]; END; resultP _ p; state.dest.frame _ Frame.MyLocalFrame[]; TRANSFER WITH state; END; UVersion: PROC RETURNS [MicrocodeVersion.VersionResult] = BEGIN TrapSupport.BumpPC[2]; RETURN [[ machineType: dolphin, majorVersion: 0, unused: 0, floatingPoint: FALSE, cedar: FALSE, releaseDate: System.gmtEpoch/86400]]; END; READRTrap: PROC [reg: [0..377]] RETURNS [UNSPECIFIED] = BEGIN -- 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. TrapSupport.BumpPC[2]; RETURN [320]; END; -- -- Initialization InitializeCVTimeouts[]; InitializeD0InputOutput[]; SDDefs.SD[SDDefs.sUnimplemented] _ UnimplementedTrap; SDDefs.SD[137B] _ @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[]; END. 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