DIRECTORY Environment USING [wordsPerPage], File USING [nullFile, Type], Floppy USING [AlreadyFormatted, Density, Error, FileID, maxCharactersInLabel, nullFileID, PageCount, Sides], FloppyChannel USING [Attributes, Context, DiskAddress, FormatTracks, GetDeviceAttributes, GetHandle, Handle, Nop, SectorCount, SetContext, Status, WriteSectors], FloppyExtras USING [ExtrasError, ExtrasErrorType], FloppyFormat USING [Alternate, badSpotSector, badSpotSectors, BadSpotSectors, Byte, ConvertPageCount, dataContext, FileList, FileListEntry, FileListSeal, FileListVersion, FillTrackOneSector, FillTrackZeroSector, firstDataAddress, FloppySeal, FloppyVersion, Format, ImplementedFileSize, MarkerPage, MarkerSeal, maxBadSectors, nullSector, Sector, SectorNine, SectorToDiskAddress, trackOneAddress, trackOneContext, TrackOneSector, trackZeroAddress, trackZeroContext, TrackZeroSector], FloppyImplInterface, VM USING [ defaultBase, Error, Interval, Map, nullInterval, PageCount, Unmap]; FloppyImplPublicB: MONITOR LOCKS volumeDesc USING volumeDesc: FloppyImplInterface.VolumeDesc IMPORTS Floppy, FloppyChannel, FloppyFormat, FloppyImplInterface, VM EXPORTS Floppy SHARES FloppyImplInterface = BEGIN OPEN FloppyImplInterface; ExtrasError: PUBLIC ERROR [error: FloppyExtras.ExtrasErrorType] = CODE; FormatVerifyPasses: CARDINAL _ 2; BadSector: SIGNAL [sector: CARDINAL] = CODE; Bug: ERROR [bugType: BugType] = CODE; BugType: TYPE = {impossibleEndcase}; FormatType: TYPE = {format, erase}; buffer: Space.Interval _ Space.nullInterval; CheckSectorNine: PROCEDURE [sectorNine: LONG POINTER TO FloppyFormat.SectorNine] = BEGIN IF sectorNine.seal # FloppyFormat.FloppySeal OR sectorNine.version # FloppyFormat.FloppyVersion OR sectorNine.labelSize > Floppy.maxCharactersInLabel THEN RETURN WITH ERROR Floppy.Error[notFormatted]; IF sectorNine.countBadSectors > FloppyFormat.maxBadSectors THEN RETURN WITH ERROR Floppy.Error[notFormatted]; END; -- CheckSectorNine CheckBadPageMap: PROCEDURE [ badPageMap: LONG POINTER TO FloppyFormat.BadSpotSectors, numPages: Floppy.PageCount] = BEGIN FOR i: CARDINAL IN [0..FloppyFormat.maxBadSectors) DO IF badPageMap[i].bad > numPages OR badPageMap[i].alternate > numPages THEN RETURN WITH ERROR Floppy.Error[notFormatted]; ENDLOOP; END; -- CheckSectorTen ScanFloppy: PROCEDURE [ -- Checks to see if we can write and read the floppy volumeDesc: VolumeDesc, handle: FloppyChannel.Handle, buffer: LONG POINTER, context: FloppyChannel.Context, sectorCount: CARDINAL, firstSector: CARDINAL] = BEGIN countLeft: CARDINAL; count: CARDINAL; currentSector: CARDINAL; status: FloppyChannel.Status; currentSector _ firstSector; countLeft _ sectorCount; IF ~FloppyChannel.SetContext[handle, context] THEN ERROR Floppy.Error[badDisk]; DO -- write out the information [status, count] _ FloppyChannel.WriteSectors[ handle, FloppyFormat.SectorToDiskAddress[ currentSector, volumeDesc.sectorNine.cylinders, volumeDesc.sectorNine.tracksPerCylinder, volumeDesc.sectorNine.sectorsPerTrack], NIL, countLeft, FALSE]; IF (countLeft _ countLeft - count) = 0 THEN EXIT; SIGNAL BadSector[(currentSector _ currentSector + count)]; currentSector _ currentSector + 1; countLeft _ countLeft - 1; ENDLOOP; END; -- ScanFloppy CountBadPages: PROCEDURE [sector: FloppyFormat.Sector, countBadPages: CARDINAL, badPageList: LONG POINTER TO FloppyFormat.BadSpotSectors] RETURNS [count: CARDINAL _ 1, nextIndex: CARDINAL] = BEGIN FOR i: CARDINAL IN [0.. countBadPages) DO IF sector # badPageList[i].bad THEN LOOP; FOR nextIndex IN (i.. countBadPages) DO IF badPageList[nextIndex].bad # badPageList[i].bad + nextIndex - i THEN RETURN[count, nextIndex]; count _ count.SUCC; ENDLOOP; ENDLOOP; RETURN[count, countBadPages]; END; -- CountBadPages WriteMarkerPages: PROCEDURE [volumeDesc: VolumeDesc, markerPage: LONG POINTER TO FloppyFormat.MarkerPage, countBadPages: CARDINAL, badPageList: LONG POINTER TO FloppyFormat.BadSpotSectors] = BEGIN IF countBadPages = 0 THEN BEGIN markerPage^ _ [ previous: [length: 0, body: free[]], next: [ length: volumeDesc.numPages - 2 - FirstDataSector[volumeDesc] + 1, body: free[]]]; WriteFloppy[volumeDesc, markerPage, FirstDataSector[volumeDesc], 1]; markerPage­ _ [ previous: [ length: volumeDesc.numPages - 2 - FirstDataSector[volumeDesc] + 1, body: free[]], next: [length: 0, body: free[]]]; WriteFloppy[ volumeDesc, markerPage, FloppyFormat.ConvertPageCount[ volumeDesc.numPages], 1]; RETURN; END ELSE BEGIN sector: FloppyFormat.Sector; lastSector: FloppyFormat.Sector; badPageIndex: CARDINAL; IF badPageList[0].bad = FirstDataSector[volumeDesc] THEN BEGIN -- Find the initial run of bad pages count: CARDINAL; [count, badPageIndex] _ CountBadPages[ FirstDataSector[volumeDesc], countBadPages, badPageList]; lastSector _ FirstDataSector[volumeDesc] + count; markerPage­ _ [ previous: [length: count, body: badSectors[]], next: [length: 0, body: free[]]]; END ELSE -- the first page on the disk is good BEGIN badPageIndex _ 0; lastSector _ FirstDataSector[volumeDesc]; markerPage­ _ [ previous: [length: 0, body: free[]], next: [length: 0, body: free[]]]; END; WHILE badPageIndex < countBadPages DO count: CARDINAL; -- the length of the bad page run sector _ badPageList[badPageIndex].bad - 1; IF lastSector ~= sector THEN BEGIN -- We have found a run of free pages markerPage.next.length _ sector - (lastSector + 1); WriteFloppy[volumeDesc, markerPage, lastSector, 1]; -- X/Free markerPage.previous _ [ length: sector - (lastSector + 1), body: free[]]; END; [count, badPageIndex] _ CountBadPages[ sector + 1, countBadPages, badPageList]; markerPage.next _ [length: count, body: badSectors[]]; WriteFloppy[volumeDesc, markerPage, sector, 1]; -- (Bad or Free)/Bad lastSector _ sector + count + 1; markerPage­ _ [ previous: [length: count, body: badSectors[]], next: [length: 0, body: free[]]]; -- setup for bad/free ENDLOOP; sector _ FloppyFormat.ConvertPageCount[volumeDesc.numPages]; -- Last data sector IF lastSector <= sector THEN -- i.e., the last page is not bad BEGIN markerPage.next.length _ sector - (lastSector + 1); WriteFloppy[volumeDesc, markerPage, lastSector, 1]; -- Bad/Free IF sector ~= lastSector THEN BEGIN markerPage­ _ [ previous: [length: sector - (lastSector + 1), body: free[]], next: [length: 0, body: free[]]]; WriteFloppy[volumeDesc, markerPage, sector, 1]; -- Free/Free END; END; END; -- Of initializing marker pages on the disk with bad pages present END; -- WriteMarkerPages Format: PUBLIC PROCEDURE [drive: CARDINAL, maxNumberOfFileListEntries: CARDINAL, labelString: ROPE, density: Floppy.Density, sides: Floppy.Sides] = BEGIN IF ~ValidDrive[drive] THEN ERROR Floppy.Error[noSuchDrive]; FormatInternal[volumeTable[drive], format, drive, maxNumberOfFileListEntries, labelString, density, sides]; END; -- Format Erase: PUBLIC PROCEDURE [drive: CARDINAL, maxNumberOfFileListEntries: CARDINAL, labelString: ROPE] = BEGIN IF ~ValidDrive[drive] THEN ERROR Floppy.Error[noSuchDrive]; FormatInternal[volumeTable[drive], erase, drive, maxNumberOfFileListEntries, labelString,,]; END; -- FormatInternal: ENTRY PROCEDURE [volumeDesc: VolumeDesc, formatMode: FormatType, drive: CARDINAL, maxNumberOfFileListEntries: CARDINAL, labelString: ROPE, density: Floppy.Density, sides: Floppy.Sides] = BEGIN ENABLE BEGIN IOError => GOTO dataError; UNWIND => VM.Free[buffer]; END; attributes: FloppyChannel.Attributes; format: FloppyFormat.Format; trackZeroSector: LONG POINTER TO FloppyFormat.TrackZeroSector; trackOneSector: LONG POINTER TO FloppyFormat.TrackOneSector; markerPage: LONG POINTER TO FloppyFormat.MarkerPage; countBadPages: CARDINAL; countToFormat: CARDINAL; requestedSize: Space.PageCount; address: FloppyFormat.Sector; diskAddress: FloppyChannel.DiskAddress; status: FloppyChannel.Status; sectors, trackZeroSectors: FloppyChannel.SectorCount; trackOneDensity: Floppy.Density; requestedSize _ WordsToPages[SIZE[FloppyFormat.TrackZeroSector]] + WordsToPages[ SIZE[FloppyFormat.TrackOneSector]] + WordsToPages[ SIZE[FloppyFormat.MarkerPage]]; buffer _ CreateBuffer[requestedSize]; IF buffer.count ~= requestedSize THEN ERROR; -- Insufficient VM to work in trackZeroSector _ LOOPHOLE[buffer.pointer]; markerPage _ LOOPHOLE[trackZeroSector + Environment.wordsPerPage * WordsToPages[ SIZE[FloppyFormat.TrackZeroSector]]]; trackOneSector _ LOOPHOLE[markerPage + Environment.wordsPerPage * WordsToPages[ SIZE[FloppyFormat.BadSpotSectors]]]; IF volumeDesc.open THEN BEGIN IF formatMode = format THEN BEGIN label: STRING _ [Floppy.maxCharactersInLabel]; label.length _ 0; FOR i: CARDINAL IN [0..volumeDesc.sectorNine.labelSize) DO label[i] _ volumeDesc.sectorNine.label[i]; label.length _ label.length + 1; ENDLOOP; SIGNAL Floppy.AlreadyFormatted[label]; CloseVolume[volumeDesc]; END ELSE IF formatMode = erase THEN CloseVolume[volumeDesc]; END; volumeDesc.handle _ FloppyChannel.GetHandle[drive]; attributes _ FloppyChannel.GetDeviceAttributes[volumeDesc.handle].attributes; status _ FloppyChannel.Nop[volumeDesc.handle]; IF status = notReady THEN { buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[notReady]}; IF status = writeFault THEN { buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[writeInhibited]}; IF formatMode = format THEN BEGIN SELECT attributes.twoSided FROM FALSE => IF sides = one OR sides = default THEN volumeDesc.sides _ one ELSE { buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[onlyOneSide]}; TRUE => IF sides = two OR sides = default THEN volumeDesc.sides _ two ELSE { buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[invalidFormat]}; ENDCASE; SELECT density FROM single => volumeDesc.density _ single; double => BEGIN IF FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.dataContext[double]] THEN volumeDesc.density _ double ELSE BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[onlySingleDensity]; END; END; default => volumeDesc.density _ IF FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.dataContext[double]] THEN double ELSE single; ENDCASE => BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; Bug[impossibleEndcase]; END; END ELSE IF formatMode = erase THEN -- get sides and density off floppy BEGIN byte: FloppyFormat.Format; diskAddress _ [ head: FloppyFormat.trackZeroAddress.head, cylinder: FloppyFormat.trackZeroAddress.cylinder, sector: 7]; AccessFloppy[ volumeDesc: volumeDesc, buffer: trackZeroSector, count: 1, address: diskAddress, access: read]; byte _ LOOPHOLE[trackZeroSector[71]]; -- reflects FloppyFormat.Format type SELECT byte FROM -- 64 (' ), 212 ('M), 242 ('2) are valid singleSidedSingleDensity => BEGIN volumeDesc.sides _ one; volumeDesc.density _ single; attributes.numberOfHeads _ 1; END; doubleDensity => BEGIN volumeDesc.sides _ two; volumeDesc.density _ double; END; doubleSidedSingleDensity => BEGIN volumeDesc.sides _ two; volumeDesc.density _ single; END; ENDCASE => RETURN WITH ERROR FloppyExtras.ExtrasError[notFormatted]; END; IF ~FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.dataContext[volumeDesc.density]] THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; sectors _ FloppyChannel.GetDeviceAttributes[volumeDesc.handle].maxSectorsPerTrack; volumeDesc.open _ FALSE; volumeDesc.writeProtected _ FALSE; volumeDesc.numPages _ attributes.numberOfHeads * attributes.numberOfCylinders * sectors; IF formatMode = format THEN -- start initializing volumeDesc.sectorNine volumeDesc.sectorNine­ _ [ cylinders: attributes.numberOfCylinders, tracksPerCylinder: attributes.numberOfHeads, sectorsPerTrack: sectors, firstAlternateSector: FloppyFormat.nullSector ] ELSE IF formatMode = erase THEN BEGIN -- and check them to see if they seem reasonable diskAddress _ [ head: FloppyFormat.trackZeroAddress.head, cylinder: FloppyFormat.trackZeroAddress.cylinder, sector: 9]; AccessFloppy[ volumeDesc: volumeDesc, buffer: volumeDesc.sectorNine, count: 1, address: diskAddress, access: read]; CheckSectorNine[volumeDesc.sectorNine]; countBadPages _ volumeDesc.sectorNine.countBadSectors; diskAddress.sector _ FloppyFormat.badSpotSector; AccessFloppy[ volumeDesc: volumeDesc, buffer: volumeDesc.badPageMap, count: FloppyFormat.badSpotSectors, address: diskAddress, access: read]; CheckBadPageMap[volumeDesc.badPageMap, volumeDesc.numPages]; BEGIN OPEN volumeDesc.sectorNine; fileList _ FloppyFormat.nullSector; fileListID _ Floppy.nullFileID; fileListSize _ 0; rootFile _ Floppy.nullFileID; pilotMicrocode _ FloppyFormat.nullSector; diagnosticMicrocode _ FloppyFormat.nullSector; germ _ FloppyFormat.nullSector; pilotBootFile _ FloppyFormat.nullSector; firstAlternateSector _ FloppyFormat.nullSector; -- We don't allocate alternates for now nextUnusedFileID _ 1; changing _ FALSE; END; -- of OPEN END; IF labelString ~= NIL THEN -- Copy our client's label, if any BEGIN volumeDesc.sectorNine.labelSize _ MIN[ Floppy.maxCharactersInLabel, labelString.length]; FOR i: CARDINAL IN [0..volumeDesc.sectorNine.labelSize) DO volumeDesc.sectorNine.label[i] _ labelString[i]; ENDLOOP; FOR i: CARDINAL IN [volumeDesc.sectorNine.labelSize..Floppy.maxCharactersInLabel) DO volumeDesc.sectorNine.label[i] _ ' ; ENDLOOP; END; IF formatMode = format THEN -- this block only if are formatting BEGIN countToFormat _ (attributes.numberOfCylinders - 1) * attributes.numberOfHeads; IF FloppyChannel.FormatTracks[ volumeDesc.handle, FloppyFormat.firstDataAddress, countToFormat].countDone ~= countToFormat THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; countBadPages _ 0; FOR i: CARDINAL IN [0..LENGTH[volumeDesc.badPageMap­]) DO volumeDesc.badPageMap[i] _ [ bad: FloppyFormat.nullSector, alternate: FloppyFormat.nullSector]; ENDLOOP; FOR i: CARDINAL IN [0..FormatVerifyPasses) DO cylinderZeroSectors: CARDINAL = sectors * attributes.numberOfHeads; SetBlock[buffer.pointer, Environment.wordsPerPage, 0]; ScanFloppy[ volumeDesc, volumeDesc.handle, buffer.pointer, FloppyFormat.dataContext[volumeDesc.density], FloppyFormat.ConvertPageCount[ volumeDesc.numPages - cylinderZeroSectors], FirstDataSector[ volumeDesc] ! BadSector => BEGIN FOR i: CARDINAL IN [0..countBadPages) DO temp: FloppyFormat.Alternate; IF volumeDesc.badPageMap[i].bad = sector THEN RESUME ; IF volumeDesc.badPageMap[i].bad < sector THEN LOOP; temp _ volumeDesc.badPageMap[i]; volumeDesc.badPageMap[i] _ [ bad: sector, alternate: FloppyFormat.nullSector]; sector _ temp.bad; ENDLOOP; IF countBadPages >= FloppyFormat.maxBadSectors THEN GO TO tooManyBadPages; volumeDesc.badPageMap[countBadPages] _ [ bad: sector, alternate: FloppyFormat.nullSector]; countBadPages _ countBadPages + 1; RESUME END]; REPEAT tooManyBadPages => RETURN WITH ERROR Floppy.Error[badDisk]; ENDLOOP; IF ~FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.trackZeroContext] THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; IF FloppyChannel.FormatTracks[ volumeDesc.handle, FloppyFormat.trackZeroAddress, 1].countDone ~= 1 THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; trackZeroSectors _ FloppyChannel.GetDeviceAttributes[ volumeDesc.handle].maxSectorsPerTrack; FOR i: CARDINAL IN [0..FormatVerifyPasses) DO SetBlock[buffer.pointer, Environment.wordsPerPage, 0]; ScanFloppy[ volumeDesc, volumeDesc.handle, buffer.pointer, FloppyFormat.trackZeroContext, trackZeroSectors, 1 ! BadSector => GO TO badCylinderZero; ]; REPEAT badCylinderZero => RETURN WITH ERROR Floppy.Error[badDisk]; ENDLOOP; IF volumeDesc.sides = two THEN BEGIN SELECT TRUE FROM FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.trackOneContext[ trackOneDensity _ volumeDesc.density]] => NULL; FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.trackOneContext[ trackOneDensity _ IF trackOneDensity = single THEN double ELSE single]] => NULL; ENDCASE => BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; IF FloppyChannel.FormatTracks[ volumeDesc.handle, FloppyFormat.trackOneAddress, 1].countDone ~= 1 THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; END; format _ SELECT volumeDesc.density FROM double => doubleDensity, single => SELECT volumeDesc.sides FROM one => singleSidedSingleDensity, two => doubleSidedSingleDensity ENDCASE => ERROR, ENDCASE => ERROR; FOR address IN [1..trackZeroSectors] DO IF address = 9 THEN LOOP; -- We will fill in sector nine later FloppyFormat.FillTrackZeroSector[trackZeroSector, format, address]; diskAddress _ FloppyFormat.trackZeroAddress; diskAddress.sector _ address; AccessFloppy[volumeDesc, trackZeroSector, diskAddress, 1, write]; ENDLOOP; IF volumeDesc.sides = two THEN BEGIN -- Fill in track one, cylinder zero trackOneSectors: CARDINAL; IF ~FloppyChannel.SetContext[ volumeDesc.handle, FloppyFormat.trackOneContext[trackOneDensity]] THEN BEGIN buffer.pointer _ Space.Unmap[buffer.pointer]; RETURN WITH ERROR Floppy.Error[badDisk]; END; trackOneSectors _ FloppyChannel.GetDeviceAttributes[ volumeDesc.handle].maxSectorsPerTrack; diskAddress _ FloppyFormat.trackOneAddress; FOR address IN [1..trackOneSectors] DO FloppyFormat.FillTrackOneSector[trackOneSector, format, address]; diskAddress.sector _ address; AccessFloppy[volumeDesc, trackOneSector, diskAddress, 1, write]; ENDLOOP; END; volumeDesc.sectorNine.countBadSectors _ countBadPages; diskAddress _ FloppyFormat.trackZeroAddress; diskAddress.sector _ FloppyFormat.badSpotSector; AccessFloppy[ -- Write out the bad page list volumeDesc, volumeDesc.badPageMap, diskAddress, FloppyFormat.badSpotSectors, write]; END; --- of block if only formatting WriteMarkerPages[ volumeDesc, markerPage, countBadPages, volumeDesc.badPageMap]; volumeDesc.sectorNine.fileListSize _ WordsToPages[ SIZE[FloppyFormat .FileList[maxNumberOfFileListEntries]]]; volumeDesc.fileListSpace _ Space.Map[ [File.nullFile, Space.defaultBase, volumeDesc.sectorNine.fileListSize]]; volumeDesc.fileList _ volumeDesc.fileListSpace.pointer; volumeDesc.fileList.seal _ FloppyFormat.FileListSeal; volumeDesc.fileList.version _ FloppyFormat.FileListVersion; volumeDesc.fileList.count _ 0; volumeDesc.fileList.maxEntries _ maxNumberOfFileListEntries; FOR i: CARDINAL IN [0..maxNumberOfFileListEntries) DO volumeDesc.fileList.files[i] _ []; ENDLOOP; InitializeAllocationMap[volumeDesc]; [volumeDesc.sectorNine.fileList, volumeDesc.sectorNine.fileListID] _ AllocateFile[ volumeDesc, volumeDesc.sectorNine.fileListSize, FloppyImplInterface.FileListType, FloppyFormat.nullSector]; WriteSectorNine[volumeDesc]; volumeDesc.fileList.count _ 1; volumeDesc.fileList.files[0] _ [ file: volumeDesc.sectorNine.fileListID, type: FloppyImplInterface.FileListType, location: volumeDesc.sectorNine.fileList, size: volumeDesc.sectorNine.fileListSize]; WriteFileList[volumeDesc]; CloseVolume[volumeDesc]; -- To clear out the temporary spaces buffer.pointer _ Space.Unmap[buffer.pointer]; EXITS dataError => RETURN WITH ERROR Floppy.Error[badDisk]; END; -- FormatInternal END... žFloppyImplPublicB.mesa Copyright Σ 1983, 1984, 1985, 1986, 1987 by Xerox Corporation. All rights reserved. Tim Diebert: May 7, 1987 3:34:22 pm PDT PUBLIC ERRORs Locals PRIVATE operations (must be first to avoid storage overlow in pass 5) a check by Erase to see if floppy seems to be formatted a check by Erase to see if floppy seems to be formatted NIL field should really be buffer: cheap hack to work around bug in FloppyChannel *** NOTE THAT sector MUST BE IN badPageList We must place marker pages around every run of bad pages Find the first good sector on the disk we will write the X/Free MP at lastSector and Free/Bad MP at sector PUBLIC operations trackBufferLength: CARDINAL = 6*Environment.wordsPerPage; ++not needed we'll get the floppy's density and sides in FormatInternal ENTRY procedures First create the buffer space that we need to work in check volumeDesc.open; get handle, attributes, status This doesn't look right - Swap next 2 and RET w/ERROR instead? discover sides and density Should be new error, say, [formatConflict], not invalidFormat Finish initializing volumeDesc We don't allocate alternates for now retrieve sector 9 & bad page map from floppy re-initialize some sectorNine fields keep seal through sectorsPerTrack, label & size, countBadSectors volumeDesc is initialized at this point except for allocationMap and allocationMapSpace which will be handled later Format the floppy First the data sectors. The data area formatted okay, but lets see if we can read/write it: find bad sectors eliminate duplicates Now format cylinder zero First track zero Now see if we can read/write track 0 If two sided, then format track one For now we don't care if we can read/write track one Now fill in cylinder zero with correct values Fill in track zero, cylinder zero At this point cylinder zero has mostly correct data. We now must fill in those parts of track zero that belong to the floppy file system First initialize the bad spot table on track zero write the marker pages for both formats and erases Allocate the fileListSpace now so that InitializeAllocationMap works really should catch errors and do something reasonable Finish initializing volumeDesc.sectorNine Κ“˜codešœ™KšœU™UK™'—K˜šΟk ˜ Kšœ œ˜!Kšœœ˜Kšœœa˜mKšœœŽ˜‘Kšœ œ ˜2Kšœ œΟ˜αK˜KšœœF˜N—K˜šΠlnœœœ œ+˜\Kšœ;˜DKšœ˜Kšœ˜—˜Kšœœ˜Kšœ ™ K˜KšΟn œœœ)œ˜G—˜Kšœ™—˜KšŸœœ˜!—˜KšŸ œœ œœ˜,KšŸœœœ˜%Kšœ œ˜$Kšœ œ˜#K˜,—˜KšœE™E—˜š Ÿœ œœœœ˜RKšœ7™7Kš˜šœ*˜,Kšœ0˜2šœ4œ˜;Kšœœœ˜-——šœ9˜?Kšœœœ˜-—KšœΟc˜K˜—šŸœ œ˜Kšœ œœœ˜8K˜Kšœ7™7Kš˜šœœœ!˜5šœœ#˜EKšœœœœ˜2—Kšœ˜—Kšœ ˜K˜—šŸ œ œ 4˜MKš œ>œœ/œœ˜‘Kšœ œ˜Kšœœ˜Kšœœ˜K˜K˜K˜K˜Kšœ, œ˜Ošœ ˜ ˜-K˜)K˜/K˜(Kšœ(œ œ˜?—KšœU™UKšœ%œœ˜1Kšœ4˜:K˜"K˜Kšœ˜—Kšœ  ˜——˜šŸ œ œ.œ˜OKšœ œœœœ œœ˜tKšœ'™'šœœœ˜)Kšœœœ˜)šœ œ˜'Kšœ@˜BKšœœ˜Kšœœ˜Kšœ˜—Kšœ˜—Kšœ˜Kšœ ˜——˜šŸœ œ&œœœ)œœœœ˜Δšœ ˜˜K˜$K˜K˜BK˜—K˜D˜K˜ K˜BK˜0—˜ K˜6K˜—Kšœ˜Kš˜—š ˜ Kšœ8™8K˜K˜ Kšœœ˜Kšœ&™&šœ2˜8Kšœ $˜+Kšœœ˜˜&K˜9—K˜1˜K˜.K˜!—Kš˜—šœ %˜+Kš˜K˜K˜)˜K˜$K˜!—Kšœ˜—Kšœ˜%šœC™CKšœœ !˜3K˜+šœ˜Kšœ $˜+K˜3Kšœ5  ˜>˜K˜1—Kšœ˜—˜&K˜(—K˜6Kšœ0 ˜DK˜ ˜K˜.Kšœ( ˜=—Kšœ˜—˜Kšœ4 ˜G—šœœ !˜?Kš˜K˜3Kšœ8  ˜Cšœ˜Kš˜˜K˜Kšœœœœ˜™>Kšœ ˜&K˜Kš˜—Kšœœœ˜8Kšœ˜—K˜3˜ K˜@—K˜.šœœ˜K˜-Kšœœœ˜*—šœœ˜˜-Kšœœœ˜0K˜——Kšœ™šœ˜Kš˜šœ˜šœ˜Kšœ œœ˜=šœ˜˜-Kšœœœ˜-———šœ˜Kšœ œœ˜=šœ˜˜-Kšœœœ˜/——Kšœ=™=—Kšœ˜—šœ ˜K˜&˜ Kš˜šœ˜K˜4—Kšœ˜ š˜Kš˜K˜-Kšœœœ!˜2Kšœ˜—Kšœ˜—˜ ˜šœ˜K˜4—Kšœœ˜——šœ˜ Kš˜K˜-K˜Kšœ˜——Kš˜—šœœœ #˜DKšœ˜K˜˜K˜)K˜=—˜ K˜:K˜$—˜Kšœ $˜C—šœœ (˜:˜Kš˜K˜K˜K˜Kšœ˜—˜Kš˜K˜K˜Kšœ˜—˜Kš˜K˜K˜Kšœ˜—Kšœœœœ(˜D—Kšœ˜K˜—šœ˜KšœA˜EKš˜K˜-Kšœœœ˜(Kšœ˜—˜ K˜H—Kšœ™Kšœœ˜Kšœœ˜"˜K˜B——˜šœœ +˜H˜K˜(K˜,K˜˜-Kšœ$™$—K˜——šœœ˜Kšœ-™-Kšœ 0˜9˜K˜)K˜=—˜ K˜@K˜$—K˜'K˜6K˜0˜ K˜6K˜9K˜—K˜Kš˜šœ"œ˜&K˜1—šœœœ&˜:K˜0Kšœ˜—šœœ˜Kšœ?˜AK˜$Kšœ˜—Kšœ˜——˜Kšœ@™@Kšœ2™2—˜šœœ $˜AKš˜Kšœ™Kšœ™˜K˜>—šœ˜˜1Kšœ*˜.—Kš˜K˜-Kšœœœ˜(Kšœ˜———˜KšœC™CKšœ™—˜K˜š œœœœ˜9˜K˜B—Kšœ˜—šœœœ˜-šœœ˜K˜#—K˜6˜ K˜.K˜-K˜K˜——˜KšœD™D˜2Kšœ6˜:—˜%K˜H—Kšœ6™6K˜7K˜5K˜;K˜K˜<šœœœ!˜5Kšœ#œ˜+——˜K˜$—˜Kšœ)™)—˜˜DK˜ K˜/K˜;—K˜—˜K˜˜ K˜'K˜'K˜)K˜*—K˜Kšœ $˜>K˜-Kš˜Kšœ œœœ˜5Kšœ ˜——K˜˜Kšœ˜——…—K f=