{MemHunt.mc, HGM, 21-Mar-85 23:32:16}

	Reserve[0F5F, 0FFF]; {section used by the CP Kernel }
	SetTask[0]; StartAddress[Go];

RegDef[address, R, 1];  {Word within bank}
  RegDef[rhAddr, RH, 1];
RegDef[addres2, R, 2];
  RegDef[rhAdr2, RH, 2];
  
RegDef[expected, R, 3];
RegDef[found, R, 4];

RegDef[toAddr, R, 5];
RegDef[toAddrHi, RH, 5];

RegDef[temp, R, 6];

RegDef[eIncr, R, 7];
RegDef[aIncr, R, 8];
RegDef[count, R, 9];
RegDef[rhCount, RH, 9];

RegDef[lastBank, R, 0A]; {Must be power of 2}

RegDef[saveExpected, U, 0];
RegDef[aIncrIncr, U, 1];
RegDef[eIncrIncr, U, 2];


RegDef[errorCount, U, 10];  {Zeroed by Burdock.}
RegDef[diff, U, 11];
RegDef[picked, U, 12];
RegDef[dropped, U, 13];


RegDef[toData, U, 40];
RegDef[toCommand, U, 41];

RegDef[found2, U, 42];
RegDef[found3, U, 43];


Set[Setup0, 0];
Set[Setup1, 1];
Set[Setup2, 2];
Set[Setup3, 3];
Set[Setup4, 4];
Set[Setup5, 5];
Set[Setup6, 6];
Set[Setup7, 7];
Set[Setup8, 8];
Set[Setup9, 9];
Set[SetupA, 0A];
Set[SetupB, 0B];
Set[SetupC, 0C];
Set[SetupD, 0D];

Set[Fetch0, 0];
Set[Fetch1, 1];
Set[Fetch2, 2];
Set[Fetch3, 3];
Set[Fetch4, 4];
Set[Fetch5, 5];

Set[Info0, 0];
Set[Info1, 1];

Trap:	temp ← RRot1 ErrnIBnStkp, ClrIntErr, CANCELBR[$, 0F],	c1, at[0];
	Xbus ← temp LRot0, XwdDisp,				c2;
	DISP2[TrapType],					c3;
	
Parity:	GOTO[GoToGo],						c1, at[0,4,TrapType];
Init:	GOTO[GoToGo],						c1, at[1,4,TrapType];
Stack:	GOTO[GoToGo],						c1, at[2,4,TrapType];
IB:	GOTO[GoToGo],						c1, at[3,4,TrapType];

GoToGo:
	Noop,							c2;
	Noop, GOTO[Go],						c3;

Go:	rhAddr ← 0,						c1;
	Noop,							c2;
	Noop,							c3;

{Setup Misc Board to Interrupt on XACK Timeout}
	rhAdr2 ← 4, {Misc CIO Chip}				c1;
	addres2 ← 090,						c2;
	addres2 ← addres2 LRot8, {9000}				c3;

	temp  ← addres2 + 0, L0 ← Setup0, {Master Control}	c1;
	Q ← 1, CALL[Setup], {Reset}				c2;
	Noop,							c3, at[Setup0, 10, SetupRet];

	temp  ← addres2 + 0, L0 ← Setup1, {Master Control}	c1;
	Q ← 00, CALL[Setup], {Clear Reset}			c2;
	Noop,							c3, at[Setup1, 10, SetupRet];

	temp  ← addres2 + 0, L0 ← Setup2, {Master Control}	c1;
	Q ← 080, CALL[Setup], {MIE}				c2;
	Noop,							c3, at[Setup2, 10, SetupRet];

	temp  ← addres2 + 20, L0 ← Setup3, {Port A Mode}		c1;
	Q ← 0, CALL[Setup], {Bit Port}				c2;
	Noop,							c3, at[Setup3, 10, SetupRet];

	temp  ← addres2 + 23, L0 ← Setup5, {Port A Direction}	c1;
	Q ← 0FF, CALL[Setup], {All Bits Input}			c2;
	Noop,							c3, at[Setup5, 10, SetupRet];

	temp  ← addres2 + 0E, L0 ← Setup6, {Port B Data}		c1;
	Q ← 0F, CALL[Setup], {Disable all outputs}		c2;
	Noop,							c3, at[Setup6, 10, SetupRet];

	temp  ← addres2 + 2B, L0 ← Setup7, {Port B Direction}	c1;
	Q ← 0F0, CALL[Setup], {Output on low 4 bits}		c2;
	Noop,							c3, at[Setup7, 10, SetupRet];

	temp  ← addres2 + 1, L0 ← Setup8, {Master Config Control}	c1;
	Q ← 084, CALL[Setup], {Enable Ports A+B}		c2;
	Noop,							c3, at[Setup8, 10, SetupRet];

	temp  ← addres2 + 2C, L0 ← Setup9, {Port B Special IO}	c1;
	Q ← 40, CALL[Setup], {ONEs Catcher for TOXack}		c2;
	Noop,							c3, at[Setup9, 10, SetupRet];

	temp  ← addres2 + 2D, L0 ← SetupA, {Port B Polarity}	c1;
	Q ← 40, CALL[Setup],					c2;
	Noop,							c3, at[SetupA, 10, SetupRet];

	temp  ← addres2 + 2F, L0 ← SetupB, {Port B Mask}		c1;
	Q ← 40, CALL[Setup],					c2;
	Noop,							c3, at[SetupB, 10, SetupRet];

	temp  ← addres2 + 09, L0 ← SetupC, {Port B Command}	c1;
	Q ← 0C0, CALL[Setup], {Set Interrupt Enable}		c2;
	Noop,							c3, at[SetupC, 10, SetupRet];

	temp  ← addres2 + 28, L0 ← Setup4, {Port B Mode}		c1;
	Q ← 4, CALL[Setup], {Bit Port, OR Matcher}		c2;
	Noop,							c3, at[Setup4, 10, SetupRet];

	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c1;
	ClrIntErr,						c2;
	GOTO[MainLoop],						c3;

	
{------------------------------------------------------------------------------------}
MainLoop:
	aIncr ← aIncr or 1,					c1;
	Noop,							c2;
	Noop,							c3;
	
WriteSetup:
	saveExpected ← expected,				c1;
	rhAddr ← 0, address ← 0,				c2;
	rhCount ← 0, count ← 0,					c3;
	
	expected ← expected + eIncr,				c1;
	Noop,							c2;
PreWriteLoop:
	Noop,							c3;

WriteLoop:
	MAR ← [rhAddr, address + 0], RawRef, BRANCH[$, WriteLoopEnd], c1;
	MDR ← expected, MesaIntBr,				c2;
	expected ← expected + eIncr, BRANCH[$, MesaIntWrite],	c3;
	
	Noop,							c1;
	address ← address + aIncr, CarryBr,			c2;
	count ← count + 1, CarryBr, BRANCH[WriteLoop, $],	c3;
	
WriteLoopCarry:
	Q ← rhAddr + 1, CANCELBR[$],				c1, LOOPHOLE[niblTiming];
	rhAddr ← Q and lastBank LRot0,				c2;
	[] ← count, ZeroBr, GOTO[WriteLoop],			c3;

WriteLoopEnd:
	Q ← rhCount + 1,					c2, LOOPHOLE[niblTiming];
	rhCount ← Q LRot0,					c3;

	[] ← lastBank - Q, NegBr,				c1;
	BRANCH[PreWriteLoop, $],				c2;
	Noop,							c3;

	
ReadSetup:
	expected ← saveExpected,				c1;
	rhAddr ← 0, address ← 0,				c2;
	rhCount ← 0, count ← 0,					c3;
	
	Noop,							c1;
	Noop,							c2;
PreReadLoop:
	Noop,							c3;

ReadLoop:
	MAR ← [rhAddr, address + 0], RawRef, BRANCH[$, ReadLoopEnd], c1;
	expected ← expected + eIncr, MesaIntBr,			c2;
	found ← MD, BRANCH[$, MesaIntRead],			c3;
	
	[] ← expected xor found, NZeroBr,			c1;
	address ← address + aIncr, CarryBr, BRANCH[$, BugR],	c2;
	count ← count + 1, CarryBr, BRANCH[ReadLoop, $],	c3;
	
ReadLoopCarry:
	Q ← rhAddr + 1, CANCELBR[$],				c1, LOOPHOLE[niblTiming];
	rhAddr ← Q and lastBank LRot0,				c2;
	[] ← count, ZeroBr, GOTO[ReadLoop],			c3;

ReadLoopEnd:
	Q ← rhCount + 1,					c2, LOOPHOLE[niblTiming];
	rhCount ← Q LRot0,					c3;

	[] ← lastBank - Q, NegBr,				c1;
	BRANCH[PreReadLoop, $],					c2;
	Noop,							c3;

PassOK:	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c1;
	ExtCtrl ← 7, 						c2;
	Noop,							c3;

	Q ← aIncrIncr,						c1;
	aIncr ← aIncr + Q,					c2;
	Noop,							c3;

	Q ← eIncrIncr,						c1;
	eIncr ← eIncr + Q,					c2;
	GOTO[MainLoop],						c3;

{------------------------------------------------------------------------------------}


BugR:	address ← address - aIncr, CANCELBR[Error],			c3;

Error:	Noop,							c1;
	Noop,							c2;
	Q ← MD,							c3, LOOPHOLE[mdok];

	found2 ← Q,						c1;
	Noop,							c2;
	Noop,							c3;

	Q ← errorCount,						c1;
	Q ← Q + 1,						c2;
	errorCount ← Q,						c3;

	MAR← [rhAddr, address + 0], RawRef,			c1;
	Noop,							c2;
	Q ← MD,							c3;

	found3 ← Q,						c1;
	Noop,							c2;
	Noop,							c3;

	Q ← found xor expected,					c1;
	diff ← Q,						c2;
	Noop,							c3;

	temp ← Q and ~expected,					c1;
	picked ← temp,						c2;
	Noop,							c3;

	temp ← Q and expected,					c1;
	dropped ← temp,						c2;
	Noop,							c3;

DataMismatch:
	Noop,							c1;
	MesaIntBr,						c2;
	BRANCH[$, DataMismatchWithParityError],			c3;
	
DataMismatchButNoParityError:
	Noop,							c1;
	Noop,							c2;
	GOTO[Go],						c3;
	
DataMismatchWithParityError:
	Noop,							c1;
	L1 ← Info0,						c2;
	CALL[Info],						c3;
	
DataMismatchAndParityError:
	Noop,							c1, at[Info0, 10, InfoRet];
	Noop,							c2;
	GOTO[Go],						c3;
	
{------------------------------------------------------------------------------------}

MesaIntWrite:
	Noop,							c1;
	Noop,							c2;
	GOTO[MesaInt],						c3;
	
MesaIntRead:
	Noop,							c1;
	Noop,							c2;
	GOTO[MesaInt],						c3;
	
MesaInt:
	Noop,							c1;
	L1 ← Info1,						c2;
	CALL[Info],						c3;
	
	Q ← errorCount,						c1, at[Info1, 10, InfoRet];
	Q ← Q + 1,						c2;
	errorCount ← Q,						c3;

MesaIntIsProbablyAParityError:
	Noop,							c1;
	Noop,							c2;
	GOTO[Go],						c3;
	
{------------------------------------------------------------------------------------}

Info:
	rhAdr2 ← 4, {Misc CIO Chip}				c1;
	addres2 ← 090,						c2;
	addres2 ← addres2 LRot8, {9000}				c3;

	Q ← 05, L0 ← Fetch0, {RdTODatL}				c1;
	CALL[Fetch],						c2;
	toData ← temp,						c3, at[Fetch0, 10, FetchRet];

	Q ← 04, L0 ← Fetch1, {RdTODatH}				c1;
	CALL[Fetch],						c2;
	temp ← temp LRot8,						c3, at[Fetch1, 10, FetchRet];

	Q ← toData,						c1;
	temp ← temp or Q,						c2;
	toData ← temp,						c3;

	Q ← 03, L0 ← Fetch2, {RdTOCmd}				c1;
	CALL[Fetch],						c2;
	toCommand ← temp,						c3, at[Fetch2, 10, FetchRet];

	Q ← 00, L0 ← Fetch3, {RdTOAdrH}				c1;
	CALL[Fetch],						c2;
	toAddrHi ← temp LRot0,					c3, at[Fetch3, 10, FetchRet];

	Q ← 02, L0 ← Fetch4, {RdTOAdrL}				c1;
	CALL[Fetch],						c2;
	toAddr ← temp,						c3, at[Fetch4, 10, FetchRet];

	Q ← 01, L0 ← Fetch5, {RdTOAdrM}				c1;
	CALL[Fetch],						c2;
	temp ← temp LRot8,						c3, at[Fetch5, 10, FetchRet];

	Q ← toAddr,						c1;
	Q ← Q or temp, L1Disp,					c2;
	toAddr ← Q, DISP4[InfoRet],				c3;
	
{------------------------------------------------------------------------------------}

Setup:
	Noop,							c3;

	IO ← [rhAdr2, temp + 0], L0Disp,				c1;
	MDR ← Q, DISP4[SetupRet],				c2;

{------------------------------------------------------------------------------------}

Fetch:
	Noop,							c3;

	IO ← [rhAdr2, addres2 + 0E], {Port B Data}		c1;
	MDR ← Q + 8,						c2;
	Noop,							c3;

	IO ← [rhAdr2, addres2 + 0D], {Port A Data}		c1;
	Noop,							c2;
	temp ← MD,						c3;

	L0Disp,							c1;
	DISP4[FetchRet],					c2;

{------------------------------------------------------------------------------------}