{ LatchTest.mc, HGM, 12-Feb-85  5:10:29 }

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

{ Test the 6 latches that remember what's on the BUS when an XackTimeout happens.
	This test assumes:
		Main memory location FFxxxx doesn't exist.
		IO location xx0000 doesn't exist.
		Both the CP and Misc are n slots with P2 connectors. }

{Used to access CIO chips}
RegDef[address, R, 2];
  RegDef[rhAddr, RH, 2];
RegDef[address10, R, 3];
RegDef[address20, R, 4];

{Used to generate troubles}
RegDef[what, R, 8];
RegDef[where, R, 9];
  RegDef[rhWhere, RH, 9];

{Data returned from Latches}
RegDef[toCommand, R, 0A];
RegDef[toData, R, 0B];
RegDef[toAddr, R, 0C];
RegDef[toAddrHi, RH, 0C];

RegDef[temp, R, 0E];

Set[Get0, 0];
Set[Get1, 1];
Set[Get2, 2];
Set[Get3, 3];
Set[Get4, 4];
Set[Get5, 5];
Set[Get6, 6];
Set[Get7, 7];
Set[Get8, 8];

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 ← 4, {Misc CIO Chip}				c1;
	address ← 090,						c2;
	address ← address LRot8, {9000}				c3;

	address10 ← address + 10,				c1;
	address20 ← address + 20,				c2;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c3;

MainLoop:
{Setup for Interrupt on XackTimeout}
	IO ← [rhAddr, address + 0], {Master Control}		c1;
	MDR ← 1, {Reset}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0], {Master Control}		c1;
	MDR ← 000, {Clear Reset}				c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0], {Master Control}		c1;
	MDR ← 080, {MIE}					c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 3], {Port A Direction}	c1;
	MDR ← 0FF, {All Bits Input}				c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 0F, {Disable all outputs}				c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 0B], {Port B Direction}	c1;
	MDR ← 0F0, {Output on low 4 bits}			c2;
	Noop,							c3;

	IO ← [rhAddr, address + 1], {Master Config Control}	c1;
	MDR ← 084, {Enable Ports A+B}				c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 0C], {Port B Special IO}	c1;
	MDR ← 40, {ONEs Catcher for TOXack}			c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 0D], {Port B Polarity}	c1;
	MDR ← 40,						c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 0F], {Port B Mask}		c1;
	MDR ← 40,						c2;
	Noop,							c3;

	IO ← [rhAddr, address + 09], {Port B Command}		c1;
	MDR ← 0C0, {Set Interrupt Enable}			c2;
	Noop,							c3;

	IO ← [rhAddr, address20 + 08], {Port B Mode}		c1;
	MDR ← 4, {Bit Port, OR Matcher}				c2;
	ClrIntErr,						c3;
	
StartTesting:
	Q ← ExtStat, MesaIntBr,					c1;
	BRANCH[$, MesaIntAlreadySet],				c2;
	Noop,							c3;
	
	what ← 0,						c1;
	rhWhere ← 0,						c2;
	where ← 0,						c3;
	
DataLoop:
	IO ← [rhWhere, where + 0],				c1;
	MDR ← what,						c2;
	Noop,							c3;

{Argh, the silly chip is very slow}
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;

	temp ← ExtStat, MesaIntBr,				c1;
	BRANCH[MesaIntNotSet, $],				c2;
	Noop,							c3;
	
	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 000, {Clear caught 1}				c2;
	Noop,							c3;

	IO ← [rhAddr, address + 09], {Port B Command}		c1;
	MDR ← 0B0, {Reset IP}					c2;
	Noop,							c3;

	ClrIntErr,						c1;
	Noop,							c2;
	Noop,							c3;

	temp ← ExtStat, MesaIntBr,				c1;
	BRANCH[$, MesaIntStillSet],				c2;
	Noop,							c3;
	
	L0 ← Get0,						c1;
	CALL[GetInfo],						c2;
	Noop,							c3, at[Get0, 10, GetRet];
	
	[] ← toData xor what, NZeroBr,				c1;
	BRANCH[$, DataNotLatched],				c2;
	Noop,							c3;

DataLoopEnd:
	Noop,							c1;
	what ← what + 1, CarryBr,				c2;
	BRANCH[DataLoop, $],					c3;

	rhWhere ← 0FF,						c1;
	where ← 0,						c2;
	Noop,							c3;

AddrLoop:
	MAR ← [rhWhere, where + 0], RawRef,			c1;
	MDR ← what,						c2;
	Noop,							c3;

	L0 ← Get1,						c1;
	CALL[GetInfo],						c2;
	Noop,							c3, at[Get1, 10, GetRet];
	
	[] ← toAddr xor where, NZeroBr,				c1;
	BRANCH[$, AddressNotLatched],				c2;
	Noop,							c3;

AddrLoopEnd:
	Noop,							c1;
	where ← where + 1, CarryBr,				c2;
	BRANCH[AddrLoop, $],					c3;

	rhWhere ← 0,						c1;
	where ← 0,						c2;
	Noop,							c3;

AddrHiLoop:
	IO ← [rhWhere, where + 0],				c1;
	MDR ← what,						c2;
	Noop,							c3;

	L0 ← Get2,						c1;
	CALL[GetInfo],						c2;
	Q ← rhWhere,						c3, at[Get2, 10, GetRet];
	
	[] ← Q xor toAddrHi, NZeroBr,				c1;
	BRANCH[$, AddrHiNotLatched],				c2;
	Noop,							c3;

AddrHiLoopEnd:
	Q ← rhWhere,						c1;
	Q ← Q + 1,						c2;
	rhWhere ← Q LRot0,					c3;

{The Multibus only supports 23 bits of word addressing.
	Thus we have to stop sooner than you might expect.}
	Q ← Q and 080,						c1;
	[] ← Q,	NZeroBr,					c2;
	BRANCH[AddrHiLoop, $],					c3;

CommandTests:
	rhWhere ← 0,						c1;
	where ← 0,						c2;
	Noop,							c3;

	IO ← [rhWhere, where + 0],				c1;
	MDR ← what,						c2;
	Noop,							c3;

	L0 ← Get3,						c1;
	CALL[GetInfo],						c2;
	Q ← 058,						c3, at[Get3, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, IOWCFailed],					c2;
	Noop,							c3;

	IO ← [rhWhere, where + 0],				c1;
	Noop,							c2;
	what ← MD,						c3;

	L0 ← Get4,						c1;
	CALL[GetInfo],						c2;
	Q ← 054,						c3, at[Get4, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, IORCFailed],					c2;
	Noop,							c3;

	rhWhere ← 0FF,						c1;
	where ← 0,						c2;
	Noop,							c3;

	MAR ← [rhWhere, where + 0], RawRef,			c1;
	MDR ← what,						c2;
	Noop,							c3;

	L0 ← Get5,						c1;
	CALL[GetInfo],						c2;
	Q ← 051,						c3, at[Get5, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, MRWTFailed],					c2;
	Noop,							c3;

	MAR ← [rhWhere, where + 0], RawRef,			c1;
	Noop,							c2;
	what ← MD,						c3;

	L0 ← Get6,						c1;
	CALL[GetInfo],						c2;
	Q ← 052,						c3, at[Get6, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, MRDCFailed],					c2;
	Noop,							c3;

	MAR ← [rhWhere, where + 0], RawRef, ADR0,		c1;
	MDR ← what,						c2;
	Noop,							c3;

	L0 ← Get7,						c1;
	CALL[GetInfo],						c2;
	Q ← 071,						c3, at[Get7, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, ADR0Failed],					c2;
	Noop,							c3;

	MAR ← [rhWhere, where + 0], RawRef, BHEN,		c1;
	Noop,							c2;
	what ← MD,						c3;

	L0 ← Get8,						c1;
	CALL[GetInfo],						c2;
	Q ← 042,						c3, at[Get8, 10, GetRet];
	
	[] ← Q xor toCommand, NZeroBr,				c1;
	BRANCH[$, BHENFailed],					c2;
	Noop,							c3;

AllDone:
	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c1;
	ExtCtrl ← 7,						c2;
	GOTO[MainLoop],						c3;
	
	
{------------------------------------------------------------------------------------}

GetInfo:
	Noop,							c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 08, {RdTOAdrH}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	Noop,							c2;
	toAddrHi ← MD,						c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 09, {RdTOAdrM}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	Noop,							c2;
	toAddr ← MD,						c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 0A, {RdTOAdrL}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	toAddr ← toAddr LRot8,					c2;
	toAddr ← toAddr or MD,					c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 0B, {RdTOCmd}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	Noop,							c2;
	toCommand ← MD,						c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 0C, {RdTODatH}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	Noop,							c2;
	toData ← MD,						c3;

	IO ← [rhAddr, address + 0E], {Port B Data}		c1;
	MDR ← 0D, {RdTODatL}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0D], {Port A Data}		c1;
	toData ← toData LRot8,					c2;
	toData ← toData or MD,					c3;

	L0Disp,							c1;
	DISP4[GetRet],						c2;

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

MesaIntAlreadySet:	GOTO[Restart],				c3;
MesaIntNotSet: 		GOTO[Restart],				c3;
MesaIntStillSet: 	GOTO[Restart],				c3;

DataNotLatched: 	GOTO[Restart],				c3;
AddressNotLatched: 	GOTO[Restart],				c3;
AddrHiNotLatched: 	GOTO[Restart],				c3;

IOWCFailed: 		GOTO[Restart],				c3;
IORCFailed: 		GOTO[Restart],				c3;
MRDCFailed: 		GOTO[Restart],				c3;
MRWTFailed: 		GOTO[Restart],				c3;
ADR0Failed:		GOTO[Restart],				c3;
BHENFailed: 		GOTO[Restart],				c3;



Restart:
	Q ← 0FF,						c1;
	Noop,							c2;
RestartLoop:
	Noop,							c3;

	Q ← Q - 1, ZeroBr,					c1;
	BRANCH[RestartLoop, $],					c2;
	GOTO[Go],						c3;