<> <> <> <> <> <> <> <> <<>> DIRECTORY DiskFace, PrincOpsUtils USING[ LowHalf ], SA4000Face, DiskHeadSA4000Private; DiskHeadSA4000: CEDAR PROGRAM IMPORTS PrincOpsUtils, SA4000Face EXPORTS DiskFace, DiskHeadSA4000Private = BEGIN <> ControllerHandle: PUBLIC TYPE = CARDINAL; -- not used: we have only one controller nullControllerHandle: PUBLIC ControllerHandle _ 0; GetNextController: PUBLIC PROC[old: ControllerHandle] RETURNS [ControllerHandle] = TRUSTED { RETURN[ IF old = nullControllerHandle THEN 1 ELSE nullControllerHandle ] }; GetControllerAttributes: PUBLIC PROC[ControllerHandle] RETURNS[globalStateSize: CARDINAL] = TRUSTED { RETURN[ SA4000Face.globalStateSize ] }; InitializeController: PUBLIC PROC[controller: ControllerHandle, globalState: LONG POINTER, mask: WORD] = TRUSTED { SA4000Face.Initialize[t: mask, globalState: LOOPHOLE[PrincOpsUtils.LowHalf[globalState]] ]; }; InitializeCleanup: PUBLIC PROC[ControllerHandle] = TRUSTED { SA4000Face.InitializeCleanup[]; }; DeviceHandle: PUBLIC TYPE = RECORD[SA4000Face.DeviceHandle]; nullDeviceHandle: PUBLIC DeviceHandle _ [SA4000Face.nullDeviceHandle]; GetNextDevice: PUBLIC PROC[old: DeviceHandle] RETURNS[DeviceHandle] = TRUSTED { RETURN[ [SA4000Face.GetNextDevice[old]] ] }; DetermineDiskShape: PUBLIC PROC[device: DeviceHandle, operation: DiskFace.OperationPtr, mode: DiskFace.DeterminationMode, buffer: LONG POINTER _ NIL] RETURNS [nowKnown: BOOL] = TRUSTED { RETURN[TRUE] }; GetDeviceType: PUBLIC PROC[DeviceHandle] RETURNS [DiskFace.Type] = TRUSTED { RETURN[sa4000] }; GetDeviceAttributes: PUBLIC PROC[device: DeviceHandle] RETURNS [cylinders, movingHeads, fixedHeads, sectorsPerTrack: CARDINAL] = TRUSTED { [cylinders, movingHeads, fixedHeads, sectorsPerTrack] _ SA4000Face.GetDeviceAttributes[device] }; GetTrueDeviceAttributes: PUBLIC PROC[device: DeviceHandle] RETURNS [cylinders, movingHeads, fixedHeads, sectorsPerTrack: CARDINAL] = TRUSTED { [cylinders, movingHeads, fixedHeads, sectorsPerTrack] _ SA4000Face.GetTrueDeviceAttributes[device] }; SuggestedTries: PUBLIC PROC[DeviceHandle] RETURNS [DiskFace.Tries] = TRUSTED { RETURN[24] }; Recalibrate: PUBLIC PROC[device: DeviceHandle] = TRUSTED { SA4000Face.Recalibrate[device] }; <> QueueObj: TYPE = RECORD[ next: Queue, tries, initTries: CARDINAL, initCommand: DiskFace.Command ]; Queue: TYPE = LONG POINTER TO QueueObj; current: Queue _ NIL; last: Queue _ NIL; GetOp: PROC[queue: Queue] RETURNS[DiskFace.OperationPtr] = TRUSTED INLINE { RETURN[ LOOPHOLE[queue - SA4000Face.operationSize] ] }; GetQueue: PROC[op: DiskFace.OperationPtr] RETURNS[Queue] = TRUSTED INLINE { RETURN[ LOOPHOLE[op + SA4000Face.operationSize] ] }; operationSize: PUBLIC CARDINAL _ SA4000Face.operationSize + SIZE[QueueObj]; Reset: PUBLIC PROC[ControllerHandle] = TRUSTED BEGIN current _ NIL; FOR d: DeviceHandle _ GetNextDevice[nullDeviceHandle], GetNextDevice[d] UNTIL d = nullDeviceHandle DO SA4000Face.Reset[d] ENDLOOP; END; none: SA4000Face.Command = vv; saCommand: PACKED ARRAY DiskFace.Op OF PACKED ARRAY DiskFace.Op OF PACKED ARRAY DiskFace.Op OF SA4000Face.Command = [ --header-- noOp: [ --label-- noOp: [ --data-- noOp: none, read: none, write: none, verify: none ], read: [ --data-- noOp: none, read: none, write: none, verify: none ], write: [ --data-- noOp: none, read: none, write: none, verify: none ], verify:[ --data-- noOp: none, read: none, write: none, verify: none ] ], read: [ noOp: [ --data-- noOp: none, read: none, write: none, verify: none ], read: [ --data-- noOp: rr, read: rrr, write: rrw, verify: rrv ], write: [ --data-- noOp: rw, read: none, write: rww, verify: none ], verify:[ --data-- noOp: rv, read: rvr, write: rvw, verify: rvv ] ], write: [ noOp: [ --data-- noOp: w, read: none, write: none, verify: none ], read: [ --data-- noOp: none, read: none, write: none, verify: none ], write: [ --data-- noOp: none, read: none, write: www, verify: none ], verify:[ --data-- noOp: none, read: none, write: none, verify: none ] ], verify: [ noOp: [ --data-- noOp: none, read: none, write: none, verify: none ], read: [ --data-- noOp: vr, read: vrr, write: vrw, verify: vrv ], write: [ --data-- noOp: vw, read: none, write: vww, verify: none ], verify:[ --data-- noOp: vv, read: vvr, write: vvw, verify: vvv ] ] ]; <> FilePageRep: TYPE = MACHINE DEPENDENT RECORD[ n(0): SELECT OVERLAID * FROM cedar => [cedar(0): INT], pilot => [ filePageLo(0): CARDINAL, pilotHi(1): RECORD[ filePageHi(0:0..6): [0..128), -- restricts to 23-bit page numbers (32-bit byte counts) pad1 (0:7..12): [0..64) _ 0, -- always zero immutable (0:13..13): BOOL _ FALSE, -- valid only in label of page 0 temporary (0:14..14): BOOL _ FALSE, -- valid only in label of page 0 zeroSize (0:15..15): BOOL _ FALSE ] ], raw => [ lowHalf(0): CARDINAL, highHalf(1): CARDINAL ] ENDCASE ]; Initiate: PUBLIC PROC[diskOp: DiskFace.OperationPtr] = TRUSTED BEGIN saOp: SA4000Face.OperationPtr = LOOPHOLE[diskOp]; queue: Queue = GetQueue[diskOp]; command: DiskFace.Command = queue.initCommand _ diskOp.command; queue.tries _ queue.initTries _ diskOp.tries; saOp.unused _ 0; saOp.command _ saCommand[command.header][command.label][command.data]; queue.next _ NIL; IF current = NIL THEN current _ queue ELSE last.next _ queue; last _ queue; BEGIN -- Fix up label file page number representation kludge: LONG POINTER TO FilePageRep = LOOPHOLE[@saOp.labelPtr.filePage]; <<... AND kludge.filePageHi = 0 is necessary because an operation may be queued more than once due to failure of a previous operation.>> IF kludge.highHalf # 0 THEN kludge.pilotHi _ [filePageHi: kludge.highHalf]; END; -- Fix up SA4000Face.Initiate[saOp]; END; diskStatus: PACKED ARRAY SA4000Face.Status OF DiskFace.Status = [ inProgress: inProgress, goodCompletion: goodCompletion, dataError: dataCRCError, labelError: labelCRCError, labelCheck: labelVerifyError, seekTimeout: seekTimeout, sectorTimeout: otherError, notReady: notReady, wrongSector: otherError, wrongCylinder: otherError, wrongHead: otherError, hardwareError: otherError ]; statusStats: PUBLIC ARRAY SA4000Face.Status OF INT _ ALL[0]; retries: PUBLIC INT _ 0; recalibrates: PUBLIC INT _ 0; lastErrorStatus: PUBLIC SA4000Face.Status _ inProgress; Poll: PUBLIC PROC [ControllerHandle] RETURNS [status: DiskFace.Status, op: DiskFace.OperationPtr, retriedCount: CARDINAL] = TRUSTED BEGIN completed: Queue; pollStatus: SA4000Face.Status; IF current = NIL THEN RETURN[clientError, NIL, 0]; op _ GetOp[current]; pollStatus _ SA4000Face.Poll[LOOPHOLE[op]]; status _ diskStatus[pollStatus]; retriedCount _ current.initTries - current.tries; SELECT status FROM goodCompletion => { completed _ current; current _ current.next }; inProgress => completed _ NIL; ENDCASE => -- some sort of error: possibly retry this one, and requeue all others. BEGIN lastErrorStatus _ pollStatus; current.tries _ current.tries - 1; IF current.tries = 0 -- RRA sez let's not do this: OR status = labelVerifyError -- THEN { -- give up on this operation -- completed _ current; current _ current.next } ELSE { completed _ NIL; status _ inProgress; IF current.tries MOD 4 = 0 THEN {Recalibrate[op.device]; recalibrates _ recalibrates + 1}; retries _ retries + 1; }; FOR other: Queue _ current, other.next UNTIL other = NIL DO SA4000Face.Initiate[LOOPHOLE[GetOp[other]]]; ENDLOOP; END; IF status # inProgress THEN { --restore word 6-- op.command _ completed.initCommand; op.tries _ completed.initTries; BEGIN -- Fix up label file page number representation kludge: LONG POINTER TO FilePageRep = LOOPHOLE[@op.labelPtr.filePage]; IF kludge.highHalf # 0 THEN kludge.highHalf _ kludge.pilotHi.filePageHi; END; -- Fix up }; statusStats[pollStatus] _ statusStats[pollStatus] + 1; END; GetFormattingUnit: PUBLIC PROC[DeviceHandle] RETURNS [DiskFace.FormattingUnit] = TRUSTED { RETURN[arbitrary] }; END.