-- DicentraDiskDriverUtilsImpl.mesa
-- Driver for Century Data AMS-315 disk drive and Xylogics SMD controller
-- Jim Gasbarro 19-Mar-84 10:18:45

DIRECTORY
	DicentraDiskDriverUtils,
	DicentraInputOutput,
	Inline,
	Process USING [Pause, SecondsToTicks],
	ProcessorFace USING [SetMP];


DicentraDiskDriverUtilsImpl: PROGRAM
	IMPORTS DicentraInputOutput, Inline, Process, ProcessorFace
	EXPORTS DicentraDiskDriverUtils
	= BEGIN

K64Words: LONG CARDINAL = LONG[64]*1024;

FallenOffTheEndOfHyperspace: PUBLIC ERROR = CODE;

HyperStore: PUBLIC PROC [ sourcePtr: LONG POINTER TO WORD, destOffset: LONG CARDINAL, wordCount: LONG CARDINAL] =
	BEGIN
	-- The destination area is referred to by an offset from the beginning of hyperspace.
	-- The microcode that implements WriteHyper has a feature that prevents it writing data across a 64K hyperspace boundary. Thats why some transfers have to be done in two parts.
	IF LOOPHOLE[DicentraDiskDriverUtils.hyperStart+destOffset+wordCount, LONG CARDINAL] > LOOPHOLE[DicentraDiskDriverUtils.hyperEndPlus1, LONG CARDINAL] THEN ERROR FallenOffTheEndOfHyperspace;
	WHILE wordCount>0 DO
		toNextBoundary: LONG CARDINAL ← K64Words - Inline.LowHalf[destOffset];
			-- use Inline.LowHalf above because MOD on LONG CARDINAL generates bad code
		xferSize: CARDINAL ← CARDINAL[MIN[wordCount, toNextBoundary, K64Words-1]];
		DicentraInputOutput.WriteHyper[from: sourcePtr, to: DicentraDiskDriverUtils.hyperStart+destOffset, words: xferSize];
		sourcePtr ← sourcePtr + xferSize;
		destOffset ← destOffset + xferSize;
		wordCount ← wordCount - xferSize;
		ENDLOOP;
	END;
	
HyperRead: PUBLIC PROC [destPtr: LONG POINTER TO WORD, sourceOffset: LONG CARDINAL, wordCount: LONG CARDINAL] =
	BEGIN
	-- The destination area is referred to by an offset from the beginning of hyperspace.
	-- Has to cope with microcode feature which will not transfer across 64K boundaries
	WHILE wordCount>0 DO
		toNextBoundary: LONG CARDINAL ← K64Words - Inline.LowHalf[sourceOffset];
		xferSize: CARDINAL ← CARDINAL[MIN[wordCount, toNextBoundary, K64Words-1]];
		IF Inline.HighHalf[DicentraDiskDriverUtils.hyperStart+sourceOffset] # Inline.HighHalf[DicentraDiskDriverUtils.hyperStart+sourceOffset+xferSize-1] THEN ERROR; 
		DicentraInputOutput.ReadHyper[from: DicentraDiskDriverUtils.hyperStart+sourceOffset, to: destPtr, words: xferSize];
		destPtr ← destPtr + xferSize;
		sourceOffset ← sourceOffset + xferSize;
		wordCount ← wordCount - xferSize;
		ENDLOOP;
	END;

ShowMP: PUBLIC PROC [n: CARDINAL] =
	BEGIN
	ProcessorFace.SetMP[n];
	Process.Pause[Process.SecondsToTicks[2]];
	END;
	
END.