-- MMDebug.mesa; edited by Sandman June 19, 1979 9:43 AM -- Edited by Forrest July 15, 1980 2:21 PM -- Edited by Gobbel November 3, 1980 11:43 PM DIRECTORY BcplOps USING [BcplJSR], ControlDefs USING [FrameHandle, GlobalFrameHandle, StateVector, SVPointer], DiskDefs USING [DS], FrameDefs USING [UnNew], FrameOps USING [GetReturnFrame, GetReturnLink, MyLocalFrame], ImageDefs USING [ AbortMesa, CleanupItem, CleanupMask, CleanupProcedure, PuntMesa, StopMesa], InlineDefs USING [BITAND], MMInit USING [MakeBootFile, MMMakeBoot, MMStart], MMOps USING [BootNetExec, etherBooted, FakeModulesCode, MMEtherBoot], Mopcodes USING [zSTARTIO], OsStaticDefs USING [OsStatics], ProcessDefs USING [DisableInterrupts, EnableInterrupts], SDDefs USING [ sCallDebugger, SD, sInterrupt, sProcessBreakpoint, sUncaughtSignal], SystemDefs USING [FreePages]; MMDebug: PROGRAM [user: PROGRAM] IMPORTS BcplOps, FrameDefs, FrameOps, ImageDefs, InlineDefs, MMInit, MMOps, ProcessDefs, SystemDefs EXPORTS ImageDefs, MMInit, MMOps SHARES DiskDefs = BEGIN OPEN ControlDefs; debugState: SVPointer; reason: {uncaughtsignal, interrupt, breakpoint, explicitcall} _ explicitcall; etherBooted: PUBLIC BOOLEAN _ FALSE; ProcessBreakpoint: PROCEDURE [s: SVPointer] = BEGIN reason _ breakpoint; debugState _ s; Swap[]; RETURN END; Interrupt: PROCEDURE = BEGIN -- called by BRK trap handler in resident code state: ControlDefs.StateVector; state _ STATE; state.dest _ FrameOps.MyLocalFrame[]; reason _ interrupt; debugState _ @state; Swap[]; END; Catcher: PROCEDURE [msg, signal: UNSPECIFIED, frame: FrameHandle] = BEGIN OPEN ControlDefs; state: StateVector; state.stk[0] _ msg; state.stk[1] _ signal; state.stkptr _ 0; state.dest _ FrameOps.GetReturnFrame[]; reason _ uncaughtsignal; debugState _ @state; Swap[]; RETURN END; CallDebugger: PROCEDURE [s: STRING] = BEGIN -- user's entry point to debugger state: ControlDefs.StateVector; state _ STATE; state.stk[0] _ s; state.stkptr _ 1; state.dest _ FrameOps.GetReturnLink[]; reason _ explicitcall; debugState _ @state; Swap[]; RETURN END; SetSD: PROCEDURE = BEGIN OPEN SDDefs; sd: POINTER TO ARRAY [0..0) OF UNSPECIFIED _ SD; sd[sProcessBreakpoint] _ ProcessBreakpoint; sd[sUncaughtSignal] _ Catcher; sd[sInterrupt] _ Interrupt; sd[sCallDebugger] _ CallDebugger; END; Swap: PROCEDURE = BEGIN break: RECORD[a,b: WORD] _ [77400B, 1400B]; DiskStatus: POINTER TO DiskDefs.DS = LOOPHOLE[522B]; IF DiskStatus.notReady # 0 THEN NetDebug[] ELSE [] _ BcplOps.BcplJSR[JSR, @break, 0]; RETURN END; TypeStore: UNSPECIFIED = 200B; TypeFetch: UNSPECIFIED = 201B; TypeProceed: UNSPECIFIED = 202B; TypeProceedReply: UNSPECIFIED = 203B; TypeAck: UNSPECIFIED = 204B; TeleDebugSocket: CARDINAL = 60B; -- these types for clarity Byte: TYPE = [0..255]; ByteCount, WordCount: TYPE = CARDINAL; MachineAddress: TYPE = MACHINE DEPENDENT RECORD [ net, host: Byte]; Pair: TYPE = MACHINE DEPENDENT RECORD [a,b: CARDINAL]; Port: TYPE = MACHINE DEPENDENT RECORD [ machine: MachineAddress, socket: Pair]; PacketTypePup: CARDINAL = 1000B; SocDebugger: Pair = [0,TeleDebugSocket]; DPup:TYPE= MACHINE DEPENDENT RECORD [ -- the Ethernet encapsulation eDest, eSource: Byte, eWord2: CARDINAL, -- Pup starts here pupLength: ByteCount, transportControl, pupType: Byte, pupID: Pair, destPort: Port, sourcePort: Port, data: Data, xSum: CARDINAL]; PacketSize: WordCount = SIZE[DPup]; PupSize: ByteCount = (PacketSize-2)*2; Data: TYPE = MACHINE DEPENDENT RECORD [ SELECT OVERLAID * FROM short => [ sAddress: POINTER, sValue: UNSPECIFIED, lenChunk: CARDINAL], long => [ lAddress: LONG POINTER, lValue: UNSPECIFIED], ENDCASE]; NoChecksum: CARDINAL = 177777B; EthernetDeviceBlock: TYPE = MACHINE DEPENDENT RECORD [ EPLocMicrocodeStatus, EPLocHardwareStatus: Byte, EBLocInterruptBit: WORD, EELocInputFinishCount: INTEGER, ELLocCollisionMagic: WORD, EILocInputCount: INTEGER, EILocInputPointer: POINTER, EOLocOutputCount: INTEGER, EOLocOutputPointer: POINTER]; EtherDevice: POINTER TO EthernetDeviceBlock = LOOPHOLE[600B]; EtherCommand: --MACHINE DEPENDENT-- TYPE = {null, output, input, reset}; Ether: PROCEDURE [EtherCommand] = MACHINE CODE BEGIN Mopcodes.zSTARTIO END; rtClock: POINTER TO INTEGER = LOOPHOLE[430B]; TicksPerSec: CARDINAL = 26; TenSec: CARDINAL = 10 * TicksPerSec; delayCount: CARDINAL _ 200; TeleSwatCursor: ARRAY [0..16) OF WORD = [ 0, 73507B, 22104B, 23507B, 22104B, 23567B, 0, 0, 65227B, 105252B, 45252B, 25272B, 142452B, 0, 0, 0]; NetDebug: PROCEDURE = BEGIN myHost: Byte _ OsStaticDefs.OsStatics.SerialNumber; d0: BOOLEAN = OsStaticDefs.OsStatics.AltoVersion.engineeringnumber = 4; debugger: Port; device: POINTER TO EthernetDeviceBlock _ LOOPHOLE[600B]; cursor: POINTER TO ARRAY [0..16) OF WORD _ LOOPHOLE[431B]; saveCursor: ARRAY [0..16) OF WORD _ cursor^; xpup: DPup; dpup: POINTER TO DPup = @xpup; proceedTime: INTEGER _ 0; cursor^ _ TeleSwatCursor; device.EBLocInterruptBit _ 0; Ether[reset]; device.EILocInputPointer _ device.EOLocOutputPointer _ dpup; device.EILocInputCount _ device.EOLocOutputCount _ PacketSize; UNTIL proceedTime # 0 AND proceedTime-rtClock^ <= 0 DO Ether[reset]; device.EPLocMicrocodeStatus _ 0; device.EPLocHardwareStatus _ 0; device.ELLocCollisionMagic _ 0; Ether[input]; DO IF device.EPLocHardwareStatus#0 THEN BEGIN IF device.EPLocMicrocodeStatus = 0 AND dpup.eWord2 = PacketTypePup AND dpup.destPort.socket = SocDebugger THEN BEGIN IF dpup.pupType # TypeProceedReply THEN proceedTime _ 0; SELECT dpup.pupType FROM TypeFetch => BEGIN dpup.data.sValue _ dpup.data.sAddress^; dpup.data.lenChunk _ 0; END; TypeStore => BEGIN dpup.data.sAddress^ _ dpup.data.sValue; dpup.data.lenChunk _ 0; END; TypeProceed => proceedTime _ rtClock^ + TenSec; TypeProceedReply => IF proceedTime # 0 THEN BEGIN cursor^ _ saveCursor; RETURN END; ENDCASE => EXIT; END ELSE EXIT; dpup.eDest _ dpup.eSource; dpup.eSource _ myHost; debugger _ dpup.sourcePort; dpup.sourcePort _ dpup.destPort; dpup.destPort _ debugger; dpup.pupType _ TypeAck; dpup.pupLength _ PupSize; dpup.transportControl _ 0; dpup.xSum _ NoChecksum; device.EPLocMicrocodeStatus _ 0; device.EPLocHardwareStatus _ 0; device.ELLocCollisionMagic _ 0; -- delay before sending ack THROUGH [0..delayCount) DO NULL ENDLOOP; Ether[output]; EXIT; END; ENDLOOP; UNTIL device.EPLocHardwareStatus#0 DO NULL ENDLOOP; ENDLOOP; cursor^ _ saveCursor; RETURN END; BootViaNet: PUBLIC PROCEDURE [bootIndex: CARDINAL, host: WORD _ 0] = BEGIN StartLoader: ARRAY [0..8] OF UNSPECIFIED _ [ 20406B, -- lda 0 lvBootLoaderPacket ; Get pointer to loader 101400B, -- inc 0 0 ; Compute page0image-1 24405B, -- lda 1 k400 ; Last destination address 34405B, -- lda 3 lblt ; Negative of number of words 61005B, -- blt ; Move loader into page 0 6B, -- jmp boot0-page0image+page0origin ; Dive into loader 0B, -- lvBootLoaderPacket: bootLoaderPacket 400B, -- k400: 400 177402B]; -- lblt: -401+page0origin BootFileNumberIndex: CARDINAL = 74B; HostIndex: CARDINAL = 67B; EtherCodeStartIndex: CARDINAL = 31B; etherBootCode: POINTER TO ARRAY [0..0) OF WORD _ MMOps.FakeModulesCode[MMOps.MMEtherBoot]; ProcessDefs.DisableInterrupts[]; etherBootCode[BootFileNumberIndex] _ bootIndex; etherBootCode[HostIndex] _ host*400B; StartLoader[6B] _ @etherBootCode[EtherCodeStartIndex]; [] _ BcplOps.BcplJSR[JSR,@StartLoader[0B],NIL]; -- bye bye END; MakeBoot: PUBLIC PROCEDURE = BEGIN MMInit.MakeBootFile[]; FrameDefs.UnNew[LOOPHOLE[MMInit.MMMakeBoot]]; RETURN END; UserCleanupList: POINTER TO ImageDefs.CleanupItem _ NIL; AddCleanupProcedure: PUBLIC PROCEDURE [item: POINTER TO ImageDefs.CleanupItem] = BEGIN ProcessDefs.DisableInterrupts[]; RemoveCleanupProcedure[item]; item.link _ UserCleanupList; UserCleanupList _ item; ProcessDefs.EnableInterrupts[]; END; RemoveCleanupProcedure: PUBLIC PROCEDURE [item: POINTER TO ImageDefs.CleanupItem] = BEGIN prev, this: POINTER TO ImageDefs.CleanupItem; IF UserCleanupList = NIL THEN RETURN; ProcessDefs.DisableInterrupts[]; prev _ this _ UserCleanupList; IF this = item THEN UserCleanupList _ this.link ELSE UNTIL (this _ this.link) = NIL DO IF this = item THEN BEGIN prev.link _ this.link; EXIT END; prev _ this; ENDLOOP; ProcessDefs.EnableInterrupts[]; END; UserCleanupProc: PUBLIC ImageDefs.CleanupProcedure = BEGIN OPEN ImageDefs, MMOps; -- all interrupts off if why = finish or abort this, next: POINTER TO ImageDefs.CleanupItem; this _ UserCleanupList; UserCleanupList _ NIL; WHILE this # NIL DO next _ this.link; IF InlineDefs.BITAND[ImageDefs.CleanupMask[why], this.mask] # 0 THEN this.proc[why ! ANY => IF why = Abort OR why = Finish THEN CONTINUE]; AddCleanupProcedure[this]; this _ next; ENDLOOP; SELECT why FROM Finish => IF ~etherBooted THEN StopMesa[] ELSE BootNetExec[]; Abort => IF ~etherBooted THEN AbortMesa[] ELSE BootNetExec[]; ENDCASE; END; -- Main body STOP; BEGIN ENABLE ANY => ImageDefs.PuntMesa; SetSD[]; SystemDefs.FreePages[LOOPHOLE[MMInit.MMStart, GlobalFrameHandle].code.handle]; FrameDefs.UnNew[LOOPHOLE[MMInit.MMStart]]; END; START user; ImageDefs.StopMesa[]; END...