<> <> <> <> DIRECTORY DiskFace, PrincOpsUtils USING[ LowHalf ], SA4000Face; DiskHeadSA4000: CEDAR PROGRAM IMPORTS PrincOpsUtils, SA4000Face EXPORTS DiskFace = 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] }; 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 ] ] ]; 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; 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 ]; Poll: PUBLIC PROC[ControllerHandle] RETURNS [status: DiskFace.Status, op: DiskFace.OperationPtr, retriedCount: CARDINAL] = TRUSTED BEGIN completed: Queue; IF current = NIL THEN RETURN[clientError, NIL, 0]; op _ GetOp[current]; status _ diskStatus[SA4000Face.Poll[LOOPHOLE[op]]]; 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 current.tries _ current.tries - 1; IF current.tries = 0 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] }; 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 }; END; GetFormattingUnit: PUBLIC PROC[DeviceHandle] RETURNS [DiskFace.FormattingUnit] = TRUSTED { RETURN[arbitrary] }; END.