-- Miscellaneous.mesa; edited by Levin, September 8, 1978 3:37 PM DIRECTORY AllocDefs: FROM "allocdefs" USING [AllocInfo, MakeSwappedIn], AltoDefs: FROM "altodefs" USING [PageSize], BcdDefs: FROM "bcddefs" USING [VersionStamp], CodeDefs: FROM "codedefs" USING [CodeHandle], ControlDefs: FROM "controldefs" USING [ FrameHandle, GFT, GFTIndex, GlobalFrameHandle, NullEpBase, NullGlobalFrame], FrameDefs: FROM "framedefs" USING [ GlobalFrame, RemoveGlobalFrame, SwapInCode, SwapOutCode, ValidateGlobalFrame], ImageDefs: FROM "imagedefs" USING [ AbortMesa, CleanupItem, CleanupMask, CleanupProcedure, ImageHeader, StopMesa], InlineDefs: FROM "inlinedefs" USING [BITAND, COPY], MiscDefs: FROM "miscdefs", Mopcodes: FROM "mopcodes" USING [zSTARTIO], NucleusDefs: FROM "nucleusdefs" USING [Resident], OsStaticDefs: FROM "osstaticdefs" USING [OsStatics], ProcessDefs: FROM "processdefs" USING [DisableInterrupts, EnableInterrupts], SDDefs: FROM "sddefs" USING [SD, sGoingAway], SegmentDefs: FROM "segmentdefs" USING [ DefaultBase, DeleteFileSegment, FileHandle, FileSegmentAddress, FileSegmentHandle, NewFileSegment, Read, SwapIn, Unlock], TrapDefs: FROM "trapdefs"; DEFINITIONS FROM ControlDefs; Miscellaneous: PROGRAM IMPORTS AllocDefs, FrameDefs, SegmentDefs, NucleusDefs, CodeDefs EXPORTS FrameDefs, ImageDefs, MiscDefs, NucleusDefs SHARES ControlDefs, ImageDefs = BEGIN DeletedFrame: PUBLIC PROCEDURE [gfi: GFTIndex] RETURNS [BOOLEAN] = BEGIN RETURN[GFT[gfi] = [frame: NullGlobalFrame, epbase: NullEpBase]]; END; LockCode: PUBLIC PROCEDURE [link: UNSPECIFIED] = BEGIN FrameDefs.SwapInCode[FrameDefs.GlobalFrame[link]]; RETURN END; UnlockCode: PUBLIC PROCEDURE [link: UNSPECIFIED] = BEGIN SegmentDefs.Unlock[CodeDefs.CodeHandle[FrameDefs.GlobalFrame[link]]]; RETURN END; CodeSegment: PUBLIC PROCEDURE [frame:FrameHandle] RETURNS [codeseg: SegmentDefs.FileSegmentHandle] = BEGIN FrameDefs.ValidateGlobalFrame[frame.accesslink]; RETURN[CodeDefs.CodeHandle[frame.accesslink]] END; MakeCodeResident: PUBLIC PROCEDURE [f:GlobalFrameHandle] = BEGIN OPEN SegmentDefs, FrameDefs; seg: FileSegmentHandle = CodeDefs.CodeHandle[f]; info: AllocDefs.AllocInfo = [unused: 0, effort: hard, direction: bottomup, request: initial, class: code, swapunlocked: TRUE, compact: FALSE]; ValidateGlobalFrame[f]; IF seg.lock = 0 THEN SwapOutCode[f]; AllocDefs.MakeSwappedIn[seg, DefaultBase, info]; RETURN END; -- data shuffling SetBlock: PUBLIC PROCEDURE [p:POINTER, v:UNSPECIFIED, l:CARDINAL] = BEGIN IF l=0 THEN RETURN; p↑ ← v; InlineDefs.COPY[from:p, to:p+1, nwords:l-1]; END; -- Image Version ImageVersion: PUBLIC PROCEDURE RETURNS [version: BcdDefs.VersionStamp] = BEGIN OPEN ControlDefs, SegmentDefs; imagefile: FileHandle ← CodeDefs.CodeHandle[ FrameDefs.GlobalFrame[NucleusDefs.Resident]].file; headerseg: FileSegmentHandle ← NewFileSegment[imagefile, 1, 1, Read]; image: POINTER TO ImageDefs.ImageHeader; SwapIn[headerseg]; image ← FileSegmentAddress[headerseg]; version ← image.prefix.version; Unlock[headerseg]; DeleteFileSegment[headerseg]; RETURN END; -- Fake Modules DestroyFakeModule: PUBLIC PROCEDURE [f: GlobalFrameHandle] RETURNS [seg: SegmentDefs.FileSegmentHandle, offset: CARDINAL] = BEGIN seg ← CodeDefs.CodeHandle[f]; IF ~f.shared THEN seg.class ← other; FrameDefs.RemoveGlobalFrame[f]; ProcessDefs.DisableInterrupts[]; IF f.code.swappedout THEN BEGIN f.code.swappedout ← FALSE; offset ← f.code.offset; END ELSE offset ← f.code.offset - seg.VMpage*AltoDefs.PageSize; ProcessDefs.EnableInterrupts[]; RETURN END; -- Get Network Number wordsPerPup: INTEGER = 280; Byte: TYPE = [0..255]; PupHeader:TYPE= MACHINE DEPENDENT RECORD [ eDest, eSource: Byte, eWord2, pupLength: INTEGER, transportControl, pupType: Byte, pupID1, pupID2: INTEGER, destNet, destHost: Byte, destSocket1, destSocket2: INTEGER, sourceNet, sourceHost: Byte, sourceSocket1, sourceSocket2: INTEGER, xSum:CARDINAL]; Pup:TYPE= MACHINE DEPENDENT RECORD [ head:PupHeader, junk:ARRAY [0..100] OF WORD]; EthernetDeviceBlock: TYPE = MACHINE DEPENDENT RECORD [ EPLocMicrocodeStatus, EPLocHardwareStatus: Byte, EBLocInterruptBit: WORD, EELocInputFinishCount: INTEGER, ELLocCollisionMagic: WORD, EILocInputCount: INTEGER, EILocInputPointer: POINTER, EOLocOutputCount: INTEGER, EOLocOutputPointer: POINTER]; -- StartIO is Mesa bytecode used to control Ethernet interface StartIO: PROCEDURE [WORD] = MACHINE CODE BEGIN Mopcodes.zSTARTIO END; outputCommand: WORD = 1; inputCommand: WORD = 2; resetCommand: WORD = 3; timer: POINTER TO INTEGER = LOOPHOLE[430B]; GetNetworkNumber: PUBLIC PROCEDURE RETURNS[CARDINAL] = BEGIN myHost: Byte ← OsStaticDefs.OsStatics.SerialNumber; then: INTEGER; now: INTEGER; device: POINTER TO EthernetDeviceBlock ← LOOPHOLE[600B]; xpup: Pup; pup: POINTER TO Pup = @xpup; gatewayRequest:PupHeader ← [ eDest: 0, eSource: myHost, eWord2: 1000B, pupLength: 22, transportControl: 0, pupType: 200B, pupID1:, pupID2:, destNet: 0, destHost: 0, destSocket1: 0, destSocket2: 2, sourceNet: 0, sourceHost: myHost, sourceSocket1: 0, sourceSocket2: 2, xSum: 177777B]; device.EBLocInterruptBit ← 0; StartIO[resetCommand]; THROUGH [0..2) DO device↑ ← EthernetDeviceBlock[ EPLocMicrocodeStatus: 0, EPLocHardwareStatus: 0, EBLocInterruptBit: 0, EELocInputFinishCount: 0, ELLocCollisionMagic: 0, EILocInputCount: 0, EILocInputPointer: pup, EOLocOutputCount: 13, EOLocOutputPointer: @gatewayRequest]; StartIO[outputCommand]; then ← timer↑; DO IF device.EPLocHardwareStatus#0 THEN BEGIN IF device.EPLocMicrocodeStatus = 0 AND pup.head.eWord2 = 1000B AND wordsPerPup+2-device.EELocInputFinishCount > 13 AND pup.head.destSocket1 = 0 AND pup.head.destSocket2 = 2 AND pup.head.pupType = 201B THEN RETURN[pup.head.sourceNet]; device↑ ← EthernetDeviceBlock[ EPLocMicrocodeStatus: 0, EPLocHardwareStatus: 0, EBLocInterruptBit: 0 , EELocInputFinishCount: 0, ELLocCollisionMagic: 0, EILocInputCount: wordsPerPup+2, EILocInputPointer: pup, EOLocOutputCount: 0, EOLocOutputPointer: NIL]; StartIO[inputCommand]; END; now ← timer↑; IF now-then > 14 THEN EXIT; ENDLOOP; ENDLOOP; RETURN[0]; END; -- procedure lists 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 -- 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 => ImageDefs.StopMesa[]; Abort => ImageDefs.AbortMesa[]; ENDCASE; END; -- Main Body; SDDefs.SD[SDDefs.sGoingAway] ← UserCleanupProc; END...