-- OthelloOpsImpl.mesa (last edited by: Forrest on: July 29, 1980 9:21 AM) DIRECTORY Boot USING [ BootFileType, Location, LVBootFiles, nullDiskFileID, PVBootFiles], BootFile USING [ currentVersion, Entry, Header, maxEntriesPerHeader, maxEntriesPerTrailer, MDSIndex, Trailer], Device USING [Type], DiskChannel USING [GetDriveAttributes, PVHandle], Environment, File, Inline USING [LongDivMod, LongNumber, LowHalf], KernelFile, OthelloOps, PhysicalVolume, Space USING [ Create, Delete, Handle, LongPointer, Map, Unmap, virtualMemory], SpecialFile, SpecialVolume, StartList USING [BootLocation, Header, VersionID], TemporaryBooting USING [ defaultSwitches, MakeBootable, MakeUnbootable, Switch, Switches, UpDown], Utilities USING [Bit, BitIndex, BitPut], Volume; OthelloOpsImpl: PROGRAM IMPORTS DiskChannel, File, Inline, KernelFile, PhysicalVolume, Space, SpecialFile, SpecialVolume, TemporaryBooting, Utilities, Volume EXPORTS OthelloOps, PhysicalVolume SHARES File= PUBLIC BEGIN OPEN OthelloOps; maxFilePermissions: File.Permissions = File.read+File.write+File.grow+File.shrink+File.delete; ImpossibleBootFileType: ERROR = CODE; ConvertBootFileType: PROC [ x: BootFileType] RETURNS [Boot.BootFileType] = BEGIN SELECT x FROM hardMicrocode => RETURN[hardMicrocode]; softMicrocode => RETURN[softMicrocode]; germ => RETURN[germ]; pilot => RETURN[pilot]; ENDCASE => ERROR ImpossibleBootFileType; END; BadSwitch: SIGNAL [c: CHARACTER] = CODE; DecodeSwitches: PROC [switchString: STRING] RETURNS [switches: TemporaryBooting.Switches] = BEGIN c: CHARACTER; aOffset: Utilities.BitIndex = LOOPHOLE[TemporaryBooting.Switch[a]]; zeroOffset: Utilities.BitIndex = LOOPHOLE[TemporaryBooting.Switch[zero]]; SetSwitch: PROC [switch: Utilities.BitIndex] = BEGIN down: Utilities.Bit = LOOPHOLE[TemporaryBooting.UpDown[down]]; Utilities.BitPut[down, @switches, switch]; END; switches _ TemporaryBooting.defaultSwitches; FOR i: CARDINAL IN [0..switchString.length) DO SELECT (c _ switchString[i]) FROM IN ['0..'9] => SetSwitch[(c-'0)+zeroOffset]; IN ['a..'z] => SetSwitch[(c-'a)+aOffset]; IN ['A..'Z] => SetSwitch[(c-'A)+aOffset]; ENDCASE => SIGNAL BadSwitch[c]; ENDLOOP; END; -- do an old style delete temps. Volume should be Open VolumeNotClosed: ERROR = CODE; DeleteTempFiles: PROC [lvID: Volume.ID] = BEGIN DeleteTempsInner: PROC = BEGIN lastCap: File.Capability _ File.nullCapability; DO temp, immutable: BOOLEAN; thisCap: File.Capability = KernelFile.GetNextFile[lvID, lastCap]; IF thisCap = File.nullCapability THEN EXIT; [immutable: immutable, temporary: temp] _ File.GetAttributes[thisCap]; IF ~temp THEN lastCap _ thisCap ELSE IF immutable THEN File.DeleteImmutable[thisCap, lvID] ELSE File.Delete[thisCap]; ENDLOOP; END; IF Volume.GetStatus[lvID]=open THEN ERROR VolumeNotClosed; Volume.Open[lvID]; DeleteTempsInner[! UNWIND => Volume.Close[lvID]]; Volume.Close[lvID]; END; Handle: PUBLIC TYPE = DiskChannel.PVHandle; GetDriveSize: PROC [ h: Handle] RETURNS [nPages: LONG CARDINAL] = {RETURN[DiskChannel.GetDriveAttributes[h.drive].nPages]}; MakeBootable: PROC [ file: File.Capability, type: BootFileType, firstPage: File.PageNumber] = BEGIN SELECT type FROM pilot => TemporaryBooting.MakeBootable[file, firstPage]; ENDCASE => BEGIN lvID: Volume.ID = File.GetAttributes[file].volume; l: SpecialFile.Link = SpecialFile.MakeBootable[ file: file, firstPage: firstPage, count: File.GetSize[file]-firstPage, lastLink: SpecialFile.eofLink]; END; END; MakeUnbootable: PROC [ file: File.Capability, type: BootFileType, firstPage: File.PageNumber] = BEGIN SELECT type FROM pilot => TemporaryBooting.MakeUnbootable[file, firstPage]; ENDCASE => SpecialFile.MakeUnbootable[ file: file, firstPage: firstPage, count: File.GetSize[file]-firstPage]; END; SetVolumeBootFile: PROC [ file: File.Capability, type: BootFileType, firstPage: File.PageNumber] = BEGIN bootFiles: Boot.LVBootFiles; lvID: Volume.ID = File.GetAttributes[file].volume; l: SpecialFile.Link = KernelFile.GetBootLocation[file, firstPage].link; SpecialVolume.GetLogicalVolumeBootFiles[lvID, @bootFiles]; bootFiles[ConvertBootFileType[type]] _ [file.fID, firstPage, LOOPHOLE[l]]; SpecialVolume.SetLogicalVolumeBootFiles[lvID, @bootFiles]; END; SetPhysicalVolumeBootFile: PROC[ file: File.Capability, type: BootFileType, firstPage: File.PageNumber] = BEGIN pvID: PhysicalVolume.ID = PhysicalVolume.GetContainingPhysicalVolume[ File.GetAttributes[file].volume]; l: SpecialFile.Link = KernelFile.GetBootLocation[file, firstPage].link; pBootFiles: Boot.PVBootFiles; SpecialVolume.GetPhysicalVolumeBootFiles[pvID, @pBootFiles]; pBootFiles[ConvertBootFileType[type]] _ [file.fID, firstPage, LOOPHOLE[l]]; SpecialVolume.SetPhysicalVolumeBootFiles[pvID, @pBootFiles]; END; GetVolumeBootFile: PROC [lvID: Volume.ID, type: BootFileType] RETURNS [cap: File.Capability, firstPage: File.PageNumber] = BEGIN bootFiles: Boot.LVBootFiles; cType: Boot.BootFileType = ConvertBootFileType[type]; SpecialVolume.GetLogicalVolumeBootFiles[lvID, @bootFiles]; IF bootFiles[cType].fID = File.nullID THEN RETURN[File.nullCapability, 0] ELSE RETURN[ [bootFiles[cType].fID, maxFilePermissions], bootFiles[cType].firstPage]; END; GetPhysicalVolumeBootFile: PROC [pvID: PhysicalVolume.ID, type: BootFileType] RETURNS [cap: File.Capability, firstPage: File.PageNumber] = BEGIN cType: Boot.BootFileType = ConvertBootFileType[type]; bootFiles: Boot.PVBootFiles; SpecialVolume.GetPhysicalVolumeBootFiles[pvID, @bootFiles]; IF bootFiles[cType].fID = File.nullID THEN RETURN[File.nullCapability, 0] ELSE RETURN[ [bootFiles[cType].fID, maxFilePermissions], bootFiles[cType].firstPage]; END; VoidVolumeBootFile: PROC [lvID: Volume.ID, type: BootFileType] = BEGIN pBootFiles: Boot.LVBootFiles; SpecialVolume.GetLogicalVolumeBootFiles[lvID, @pBootFiles]; pBootFiles[ConvertBootFileType[type]] _ Boot.nullDiskFileID; SpecialVolume.SetLogicalVolumeBootFiles[lvID, @pBootFiles]; END; VoidPhysicalVolumeBootFile: PROC [pvID: PhysicalVolume.ID, type: BootFileType] = BEGIN pBootFiles: Boot.PVBootFiles; SpecialVolume.GetPhysicalVolumeBootFiles[pvID, @pBootFiles]; pBootFiles[ConvertBootFileType[type]] _ Boot.nullDiskFileID; SpecialVolume.SetPhysicalVolumeBootFiles[pvID, @pBootFiles]; END; -- Set Debug implemenation BootHeadPtr: PRIVATE TYPE = LONG POINTER TO BootFile.Header; StartListHeadPtr: PRIVATE TYPE = LONG POINTER TO StartList.Header; SetDebugger: PROC [ debuggeeCap: File.Capability, debuggeeFirstPage: File.PageNumber, debugger: Volume.ID, debuggerType: Device.Type, debuggerOrdinal: CARDINAL] RETURNS [setDebuggerSuccess] = BEGIN bootSpace: Space.Handle; debuggerBootFiles: Boot.LVBootFiles; memPage: Environment.PageNumber; offset: CARDINAL; pBootHeader: BootHeadPtr; pStartListHeader: StartListHeadPtr; IF debuggeeCap=File.nullCapability THEN RETURN[nullBootFile]; SpecialVolume.GetLogicalVolumeBootFiles[ debugger, @debuggerBootFiles]; IF debuggerBootFiles[pilot].fID=File.nullID OR debuggerBootFiles[debugger].fID=File.nullID OR debuggerBootFiles[debuggee].fID=File.nullID THEN RETURN[noDebugger]; bootSpace _ Space.Create[1, Space.virtualMemory]; BEGIN ENABLE UNWIND => Space.Delete[bootSpace]; Space.Map[bootSpace, [debuggeeCap, debuggeeFirstPage]]; pBootHeader _ LOOPHOLE[Space.LongPointer[bootSpace]]; IF pBootHeader.version#BootFile.currentVersion THEN { Space.Delete[bootSpace]; RETURN[startListHeaderHasBadVersion]; }; IF pBootHeader.continuation.kind#initial THEN { Space.Delete[bootSpace]; RETURN[notInitialBootFile]; }; [memPage, offset] _ PointerMunge[ pBootHeader.pStartListHeader, WITH pBootHeader.continuation SELECT FROM initial=>mdsi, ENDCASE=>[0]]; pStartListHeader _ FindStartListHeader[ bootSpace, debuggeeCap, pBootHeader, debuggeeFirstPage, memPage, offset]; IF pStartListHeader=NIL THEN { Space.Delete[bootSpace]; RETURN[cantFindStartListHeader]; }; IF pStartListHeader.version#StartList.VersionID THEN { Space.Delete[bootSpace]; RETURN[startListHeaderHasBadVersion]; }; pStartListHeader.locDebuggerMicrocode _ LOOPHOLE[Boot.Location[ deviceType: debuggerType, deviceOrdinal: debuggerOrdinal, vp: disk[debuggerBootFiles[softMicrocode]]]]; pStartListHeader.locDebuggerGerm _ LOOPHOLE[Boot.Location[ deviceType: debuggerType, deviceOrdinal: debuggerOrdinal, vp: disk[debuggerBootFiles[germ]]]]; pStartListHeader.locDebugger _ LOOPHOLE[Boot.Location[ deviceType: debuggerType, deviceOrdinal: debuggerOrdinal, vp: disk[debuggerBootFiles[debugger]]]]; pStartListHeader.locDebuggee _ LOOPHOLE[Boot.Location[ deviceType: debuggerType, deviceOrdinal: debuggerOrdinal, vp: disk[debuggerBootFiles[debuggee]]]]; END; Space.Delete[bootSpace]; RETURN[success]; END; FindStartListHeader: PRIVATE PROC [sp: Space.Handle, file: File.Capability, pHeader: LONG POINTER TO BootFile.Header, firstPage: File.PageNumber, page: Environment.PageNumber, offset: CARDINAL] RETURNS [p: StartListHeadPtr] = BEGIN pTrailer: LONG POINTER TO BootFile.Trailer; pagesRemaining: File.PageCount _ pHeader.countData; curBase: File.PageNumber _ firstPage+1; -- start at first data page nEntries: CARDINAL _ Inline.LowHalf[ MIN[pagesRemaining, BootFile.maxEntriesPerHeader]]; entries: LONG POINTER TO ARRAY [0..0) OF BootFile.Entry _ @pHeader.entries; i: CARDINAL ; DO FOR i IN [0..nEntries) DO IF entries[i].page=page THEN GOTO Found; ENDLOOP; curBase _ curBase+nEntries; pagesRemaining _ pagesRemaining-nEntries; IF pagesRemaining=0 THEN RETURN[NIL]; Space.Unmap[sp]; Space.Map[sp, [file, curBase]]; curBase _ curBase+1; pTrailer _ LOOPHOLE[Space.LongPointer[sp]]; nEntries _ Inline.LowHalf[ MIN[pagesRemaining, BootFile.maxEntriesPerTrailer]]; entries _ @pTrailer.entries; REPEAT Found => NULL; ENDLOOP; curBase _ curBase+i; Space.Unmap[sp]; Space.Map[sp, [file, curBase]]; RETURN[LOOPHOLE[Space.LongPointer[sp]+offset]]; END; PointerMunge: PRIVATE PROC [p: POINTER, n: BootFile.MDSIndex] RETURNS [page: Environment.PageNumber, offset: CARDINAL] = BEGIN ln: Inline.LongNumber = [num[lowbits: LOOPHOLE[p], highbits: n]]; [page, offset] _ Inline.LongDivMod[ln.lc, Environment.wordsPerPage]; END; SubVolumeUnknown: ERROR [sv: SubVolume] = CODE; GetNextSubVolume: PROC [pvID: PhysicalVolume.ID, thisSv: SubVolume] RETURNS [SubVolume] = BEGIN sv: SpecialVolume.SubVolume = SpecialVolume.GetNextSubVolume[ pvID, IF thisSv=nullSubVolume THEN SpecialVolume.nullSubVolume ELSE [lvID: thisSv.lvID, firstLVPageNumber: thisSv.firstLVPageNumber, firstPVPageNumber: thisSv.firstPVPageNumber, subVolumeSize: thisSv.subVolumeSize] ! SpecialVolume.SubVolumeUnknown => GOTO error]; RETURN[ IF sv=SpecialVolume.nullSubVolume THEN nullSubVolume ELSE [lvID: sv.lvID, subVolumeSize: sv.subVolumeSize, firstLVPageNumber: sv.firstLVPageNumber, firstPVPageNumber: sv.firstPVPageNumber]]; EXITS error => ERROR SubVolumeUnknown[thisSv]; END; END. (1792) LOG Time: May 31, 1980 9:54 PM By: Forrest Action: Re-created file from combines of old VolumeImplA & B. Time: July 13, 1980 8:10 PM By: Forrest Action: Another run at the old fence.