-- file: LaurelInterrupt
-- derived from Resident.mesa of September 2, 1980 7:53 AM;
-- edited by Sandman on September 2, 1980 7:53 AM
-- edited by Levin on January 16, 1981 3:19 PM
-- edited by Brotz on November 12, 1981 4:42 PM
-- edited by Taft on April 14, 1983 10:34 AM

DIRECTORY
AltoFileDefs USING [CFP],
BcplOps USING [BcplJSR, BcplOutLd],
ControlDefs USING [StateVector],
CoreSwapDefs USING [CFP, PuntInfo],
DiskDefs USING [CBNil, NextDiskCommand],
ForgotOps USING [],
ImageDefs USING [AbortMesa],
InlineDefs USING [BcplLongNumber, BcplToMesaLongNumber, MesaToBcplLongNumber],
KeyDefs USING [KeyBits, Keys, updown],
Mopcodes USING [zBRK, zKFCB],
NucleusOps USING [InterruptPriority],
OsStaticDefs USING [OsStatics],
ProcessDefs USING [DisableInterrupts, EnableInterrupts, Priority],
ProcessOps USING [FirstStateVector],
SDDefs USING [sInterrupt];

LaurelInterrupt: MONITOR
IMPORTS ImageDefs, InlineDefs, BcplOps, ProcessDefs
EXPORTS ForgotOps, NucleusOps =
BEGIN

interruptWakeup: PUBLIC CONDITION;

GetDebugger: PROCEDURE = MACHINE CODE {Mopcodes.zKFCB, SDDefs.sInterrupt};

TimeData: POINTER TO TimeDataRecord = LOOPHOLE[572B];
TimeDataRecord: TYPE = MACHINE DEPENDENT RECORD [
timeOfDay: InlineDefs.BcplLongNumber,
milliSeconds: InlineDefs.BcplLongNumber,
timeBase: InlineDefs.BcplLongNumber];

disableInterrupt: PUBLIC BOOLEAN; -- this doesn’t actually do anything

InterruptProcess: PUBLIC ENTRY PROCEDURE =
BEGIN
keys: POINTER TO KeyDefs.KeyBits ← KeyDefs.Keys;
interruptState: KeyDefs.updown ← up;
pp: ProcessDefs.Priority;
SV: POINTER TO ARRAY ProcessDefs.Priority OF ControlDefs.StateVector =
LOOPHOLE[ProcessOps.FirstStateVector↑];
timeData: POINTER TO TimeDataRecord ← TimeData;
RealTimeClock: POINTER TO CARDINAL = LOOPHOLE[430B];
clockSecond: POINTER TO InlineDefs.BcplLongNumber;
DO
WAIT interruptWakeup;
clockSecond ← OsStaticDefs.OsStatics.ClockSecond;
IF RealTimeClock↑ - timeData.timeBase.highbits > clockSecond.highbits THEN
BEGIN OPEN InlineDefs;
timeData.timeOfDay ← MesaToBcplLongNumber[
BcplToMesaLongNumber[timeData.timeOfDay] + 1];
timeData.milliSeconds ← MesaToBcplLongNumber[
BcplToMesaLongNumber[timeData.milliSeconds] + 1000];
timeData.timeBase ← MesaToBcplLongNumber[
BcplToMesaLongNumber[timeData.timeBase] +
BcplToMesaLongNumber[clockSecond↑]];
END;
IF keys.LeftShift = down AND keys.Spare2 = down AND keys.Spare3 = down THEN
BEGIN
ProcessDefs.DisableInterrupts[];
UNTIL DiskDefs.NextDiskCommand↑ = DiskDefs.CBNil DO ENDLOOP;
IF keys.Ctrl = down THEN
BEGIN
code: ARRAY [0..2) OF WORD ← [77410B, 1400B];
[] ← BcplOps.BcplJSR[code: JSR, address: @code, arg: NIL];
ProcessDefs.EnableInterrupts[];
END
ELSE
BEGIN
SwatVector: POINTER TO POINTER TO RECORD [
fill: ARRAY [0..4) OF WORD, swatee: AltoFileDefs.CFP] =
LOOPHOLE[567B];
[] ← BcplOps.BcplOutLd[code: OutLd, file: @SwatVector.swatee, message: NIL];
ProcessDefs.EnableInterrupts[];
ImageDefs.AbortMesa[];
END;
END
ELSE
IF keys.Ctrl = down AND (keys.Spare3 = down OR keys.FR5 = down) THEN
BEGIN
IF interruptState = up AND CoreSwapDefs.PuntInfo↑ # LOOPHOLE[0]
AND CoreSwapDefs.PuntInfo.pDebuggerFP ~= NIL THEN
BEGIN
interruptState ← down;
FOR pp IN [0..NucleusOps.InterruptPriority) DO
SV[pp].instbyte ← Mopcodes.zBRK;
WAIT interruptWakeup;
IF SV[pp].instbyte = 0 THEN EXIT ELSE SV[pp].instbyte ← 0;
REPEAT FINISHED => GetDebugger[ ! ABORTED => CONTINUE];
ENDLOOP;
END;
END
ELSE interruptState ← up;
ENDLOOP;
END;


END.