DIRECTORY BasicTime USING [GMT], Disk USING [Channel, Command, defaultTries, DriveAttributes, DoIO, GetBootChainLink, Label, PageCount, PageNumber, Request, Status], DiskFace USING [DeviceHandle, DontCare, GetDeviceAttributes, GetNextDevice, nullDeviceHandle], FormatDisk, Rope USING [ROPE], VM USING [AddressForPageNumber, Allocate, Free, Interval, Pin, Unpin]; FormatDiskDLion: MONITOR -- only one guy in here at a time! IMPORTS Disk, DiskFace, VM EXPORTS FormatDisk = BEGIN OPEN FormatDisk; BadPage: PUBLIC SIGNAL [page: Disk.PageNumber, correctable: BOOLEAN] = CODE; Error: PUBLIC ERROR [page: Disk.PageNumber, status: Disk.Status] = CODE; Sweep: PUBLIC ENTRY PROC [channel: Disk.Channel, operation: Operation, firstPage: Disk.PageNumber, pageCount: Disk.PageCount, label: LONG POINTER TO Disk.Label, data: LONG POINTER] = BEGIN IF operation=format THEN BEGIN initialLabel: Disk.Label _ label^; p: CARDINAL; [sectorsPerTrack: p] _ DeviceFromChannel[channel].GetDeviceAttributes[]; IF (firstPage MOD p) # 0 OR (pageCount MOD p) # 0 THEN ERROR; -- can only format entire tracks WHILE pageCount#0 DO Transfer[channel: channel, firstPage: firstPage, pageCount: p, command: [write, write, write], label: label, data: data, reportSoftErrors: FALSE]; firstPage _ [firstPage+p]; pageCount _ pageCount-p; ENDLOOP; label^ _ initialLabel; END ELSE Transfer[channel: channel, firstPage: firstPage, pageCount: pageCount, command: commandTable[operation], label: label, data: data, reportSoftErrors: TRUE]; END; commandTable: ARRAY Operation OF Disk.Command = [ format: [write, write, write], write: [verify, write, write], read: [verify, read, read], verify: [verify, verify, verify]]; MicrocodeInstallFailure: PUBLIC SIGNAL [why: FailureType] = CODE; InstallInitialMicrocode: PUBLIC ENTRY PROC [channel: Disk.Channel, getPage: PROC [ptr: LONG POINTER] RETURNS [ok: BOOLEAN]] = BEGIN label: Disk.Label; vmInterval: VM.Interval _ VM.Allocate[count: 1]; pageBuffer: LONG POINTER _ VM.AddressForPageNumber[vmInterval.page]; thisPage: Disk.PageNumber _ hardUCodeStart; prevPage: Disk.PageNumber _ [hardUCodeStart-1]; VM.Pin[vmInterval]; BEGIN ENABLE UNWIND => {VM.Unpin[vmInterval]; VM.Free[vmInterval]}; DO ok: BOOLEAN; IF (ok _ getPage[pageBuffer]) THEN BEGIN ENABLE BadPage, Error => IF thisPage=hardUCodeStart THEN GOTO firstPageBad ELSE {thisPage _ [thisPage+1]; RETRY}; IF thisPage>=hardUCodeStart+hardUCodeSize THEN ERROR MicrocodeInstallFailure[microcodeTooBig]; label _ initialMicrocodeLabel; label.dontCare _ channel.GetBootChainLink[[thisPage+1]]; Transfer[channel: channel, firstPage: thisPage, pageCount: 1, command: [verify, write, write], label: @label, data: pageBuffer]; label _ initialMicrocodeLabel; Transfer[channel: channel, firstPage: thisPage, pageCount: 1, command: [verify, verify, verify], label: @label, data: pageBuffer]; END; IF thisPage#Disk.PageNumber[prevPage+1] OR ~ok THEN BEGIN ENABLE BadPage, Error => GOTO flakeyPageFound; label _ initialMicrocodeLabel; Transfer[channel: channel, firstPage: prevPage, pageCount: 1, command: [verify, verify, read], label: @label, data: pageBuffer]; label _ initialMicrocodeLabel; label.dontCare _ IF ok THEN channel.GetBootChainLink[thisPage] ELSE eofLink; Transfer[channel: channel, firstPage: prevPage, pageCount: 1, command: [verify, write, write], label: @label, data: pageBuffer]; END; IF ~ok THEN EXIT; thisPage _ [(prevPage _ thisPage)+1]; REPEAT firstPageBad => ERROR MicrocodeInstallFailure[firstPageBad]; flakeyPageFound => ERROR MicrocodeInstallFailure[flakeyPageFound]; ENDLOOP; END; VM.Unpin[vmInterval]; VM.Free[vmInterval]; END; IdentifyInitialMicrocode: PUBLIC ENTRY PROC [channel: Disk.Channel] RETURNS [microcodeInstalled: BOOLEAN, time: BasicTime.GMT, name: Rope.ROPE] = BEGIN microcodeInstalled _ FALSE; -- DLion microcode does not follow this convention END; hardUCodeFileID: ARRAY [0..5) OF CARDINAL = [0, 0, 0, 0, 0]; -- boot microcode knows this ID initialMicrocodeLabel: Disk.Label = [fileID: [abs[LOOPHOLE[hardUCodeFileID]]], filePage: 0, attributes: LOOPHOLE[0], dontCare: LOOPHOLE[LONG[0]]]; -- boot microcode knows this label. All pages of the initial microcode have the same label, except for the boot chain link which is filled in for every page. That is, the initial microcode is not a well-formed file. nullLink: DiskFace.DontCare = LOOPHOLE[LONG[0]]; eofLink: DiskFace.DontCare = LOOPHOLE[LONG[-1]]; hardUCodeStart: PUBLIC Disk.PageNumber; -- computed by Start hardUCodeSize: PUBLIC Disk.PageCount; -- computed by Start altoRegionJargon: PUBLIC Rope.ROPE _ NIL; altoRegionsMax: PUBLIC INT _ 0; altoRegionsStart: PUBLIC Disk.PageNumber _ [0]; altoRegionsSize: PUBLIC Disk.PageCount _ 0; altoRegionsBottomUp: PUBLIC BOOL _ FALSE; Start: PUBLIC PROC = BEGIN sectors, heads: CARDINAL; device: DiskFace.DeviceHandle = DiskFace.GetNextDevice[DiskFace.nullDeviceHandle]; IF device=DiskFace.nullDeviceHandle THEN ERROR; [sectorsPerTrack: sectors, movingHeads: heads] _ DiskFace.GetDeviceAttributes[device]; hardUCodeStart _ [sectors]; -- one track reserved before start of microcode hardUCodeSize _ (heads-1)*sectors; -- microcode fills rest of first cylinder END; Transfer: PROC [channel: Disk.Channel, firstPage: Disk.PageNumber, pageCount: Disk.PageCount, command: Disk.Command, label: LONG POINTER TO Disk.Label, data: LONG POINTER, reportSoftErrors: BOOLEAN _ FALSE] = BEGIN retrying: BOOLEAN _ FALSE; WHILE pageCount>0 DO request: Disk.Request _ [diskPage: firstPage, data: data, incrementDataPtr: FALSE, command: command, tries: IF reportSoftErrors AND ~retrying THEN 1 ELSE Disk.defaultTries, count: IF retrying THEN 1 ELSE pageCount]; countDone: Disk.PageCount; status: Disk.Status; [status: status, countDone: countDone] _ channel.DoIO[label: label, request: @request]; WITH s: status SELECT FROM changed => ERROR Error[firstPage, status]; unchanged => SELECT s.status FROM goodCompletion => IF retrying THEN {retrying _ FALSE; SIGNAL BadPage[firstPage, TRUE]}; notReady, recalibrateError, seekTimeout, memoryError, memoryFault, clientError, operationReset => ERROR Error[firstPage, status]; ENDCASE => BEGIN IF ~retrying THEN retrying _ TRUE ELSE BEGIN retrying _ FALSE; SIGNAL BadPage[firstPage, FALSE]; countDone _ countDone+1; -- skip over the bad page label.filePage _ label.filePage+1; END; END; ENDCASE => ERROR; pageCount _ pageCount-countDone; firstPage _ [firstPage+countDone]; ENDLOOP; END; DeviceFromChannel: PROC [channel: Disk.Channel] RETURNS [device: DiskFace.DeviceHandle] = BEGIN device _ DiskFace.nullDeviceHandle; FOR ordinal: CARDINAL IN [0..CARDINAL[channel.DriveAttributes[].ordinal]] DO device _ device.GetNextDevice[]; IF device=DiskFace.nullDeviceHandle THEN ERROR; -- bogus ordinal ENDLOOP; END; END. ’FormatDiskDLion.mesa NOTE: At the time this module is started, the disk head must already have been initialized so that the result returned by DiskFace.GetDeviceAttributes is defined. This code assumes that all attached disks are of the same shape. Last Edited by: Andrew Birrell December 6, 1983 1:15 pm Last Edited by: Taft, January 26, 1984 4:40:40 pm PST Disk formatting and checking Initial microcode Reserved disk areas Initialization Private ! BadPage, Error; The idea here is as follows. If reportSoftErrors=FALSE then we just make a normal call and let the disk channel (and head) do all the error recovery. But if reportSoftErrors=TRUE, we initially request the disk channel (and head) to perform only one try so that we get to find out the exact address of any error. When an error occurs, we then retry just that one page with full error recovery enabled in order to discover whether the error is correctable. Κε– "cedar" style˜headšœ™Ibodyšœγ™γLšœ8™8Lšœ5™5code2šΟk ˜ Mšœ œ˜Mšœœz˜„Mšœ œP˜^M˜ Mšœœœ˜Mšœœ>˜F——šœœΟc"˜;Mšœ˜Mšœ ˜Mšœœ ˜—™Mš œ œœ&œœ˜LMšœœœ0œ˜HšΟnœ œœmœœœœœ˜ΆMš˜šœ˜Mš˜M˜"Mšœœ˜ M˜HMš œ œœ œœœž ˜^šœ ˜Mšœ‹œ˜’Mšœ˜Mšœ˜Mšœ˜—M˜Mš˜—Mšœ–œ˜ Mšœ˜—šœœ œ˜1Mšœ˜Mšœ˜Mšœ˜Mšœ"˜"——™Mšœœœœ˜AšŸœ œœ"œœœœœ˜}Mš˜M˜Mšœ0˜0Mšœ œœ,˜DMšœ+˜+Mšœ/˜/˜Mš œœ0˜Cš˜Mšœœ˜ šœ˜"šœœ˜Mšœœœ ˜1Mšœœ˜&—Mšœ(œœ*˜^M˜Mšœ8˜8Mšœ€˜€M˜Mšœ‚˜‚Mšœ˜—šœ&œ˜3Mšœœœ˜4M˜Mšœ€˜€M˜Mšœœœ$œ ˜LMšœ€˜€Mšœ˜—Mšœœœ˜M˜%š˜Mšœœ'˜