{MiscDayBreak.mc, Last changed by RCH, 22-Jul-86  9:49:32

	Based on MiscDicentra by HGM, November 1983

DayBreak specific portion of Misc.mc }

{ 	Copyright (C) 1984, 1985 by Xerox Corporation.  All rights reserved.}

{#############################################################################
#									     #
#			MiscDayBreak change log:			     #
#									     #
RCH   7/22/86     Commented out INPUT, OUTPUT, WR, and DaybreakSpecificAdditions

JPM	7/31/85	Fix possible bug in SoftwareLock

JPM	7/3/85	Opie redesign conversion

JPM	5/8/85	do software locking

JPM	4/19/85	move some unused landing spots to MiscPCE

JPM	3/15/85	reinstate SetLOCK & ClrLOCK

JPM	2/7/85	redo @WRMP and @LOCKMEM to use U-regs

JPM	12/4/84	temporarily remove SetLOCK & ClrLOCK (they cause trouble)

JPM	11/13/84 un-simplified @LOCKMEM (timing constraint still holds)

JPM	10/25/84 change @NOTIFYIOP to do set, clear rather than clear, set

JPM	10/10/84 updated maintenance panel addresses

JPM	10/9/84	simplified @LOCKMEM when timing constraint removed

JPM	10/1/84	changed cycle for ClrLOCK (should be cycle 3 before last mem
		reference)

JPM	9/25/84	@RRIT must reread counters if calculated low word is 0
		(timing problem)

JPM	9/24/84	fixed bugs in @RRIT (needed another stack push; high byte of
		counts must be masked off)

JPM	9/19/84	moved label @LOCKMEM next to code (for analysis tool), added
		other labels for debugging

JPM	9/6/84	added @BYTESWAP; added copyright notice

JPM	8/24/84	corrected hardware address values in @RRIT

JPM	6/26/84	changed @WRMP to do store & notify

JPM	6/25/84	added @LOCKMEM and @NOTIFYIOP

SXW	5/30/84	changed Read Interval timer @RRIT for 8254
		Do we still need an I/O read and write command, @OUTPUT & 
		@INPUT.
		Do we also still need a maintaince panel write @WRMP
		( I don't think so )
		Also the dicentra specific additions need to be checked
		for daybreak applicability
		remover RawRefs from @RawRead and @RawWrite
		deleted @SetPhoneLineCSB, @GetExternalStatus & @SetExtCtrl
#									     #
#									     #
#									     #
#############################################################################}

{timer addresses and commands}

Set[T1Count, 41];
Set[T2Count, 42];
Set[T012Control, 43];

Set[T12Latch, 0DC];

{*****************************************************************************
	INPUT	Input
*****************************************************************************}

{@INPUT:	rhRio ← TOS LRot0,					c1, at[0,10,ESC8n];
	Rio ← STK, pop,						c2;
	pop,							c3;

	IO ← [rhRio, Rio+0], push, GOTO[Ra]			c1;}


{*****************************************************************************
	OUTPUT	Output
*****************************************************************************}

{@OUTPUT:
	rhRio ← TOS LRot0,					c1, at[1,10,ESC8n];
	Rio ← STK, pop,						c2;
	T ← STK, pop,						c3;

	IO ← [rhRio, Rio+0], GOTO[Wb],				c1;}


{*****************************************************************************
	WR - Write Registers
*****************************************************************************}

{YETCH.  Pilot wants to smash the clock.}

@WRIT:	pop,							c1, at[5,10,ESC7n];
	IBDisp, GOTO[SLa],					c2;


{Write maintenance panel}
@WRMP:	TT ← uMaintPanel, {maint panel code}			c1, at[7,10,ESC7n];
	rhTT ← uIORgnHigh,					c2;
	TOS ← TOS LRot8, {must byteswap}			c3;

	MAR ← [rhTT, TT + 0],					c1;
	MDR ← TOS,						c2;
	TT ← TT + 1, {maint panel down-notify mask}		c3;

	MAR ← [rhTT, TT + 0],					c1;
	Noop,							c2;
	TOS ← MD, GOTO[@NOTIFYIOP],				c3;


{*****************************************************************************
	RR - Read Registers
*****************************************************************************}

{Read Interval timer}
@RRIT:	rhRio ← T012Control,					c1, at[0D,10,ESC7n];
	Rx ← 0, push,						c2;
	STK ← TOS, push,					c3;

{ The two halves of the counter are synchronized by a latch command given to the 8254 control register.  The counts are correct and synchronized to the command, not to when the counters are read. }
  
ReadTimer:
	IO ← [rhRio, 0], {Control Register}			c1;
	MDR ← T12Latch, {Latching the counts}			c2;
	rhRio ← T2Count,					c3;

{ read timer two, higher 16 bits }

	IO ← [rhRio, 0], {Cnt 2 LSB}				c1;
	T ← 0FF,						c2;
	Q ← MD and T, {mask high byte}				c3;

	IO ← [rhRio, 0], {Cnt 2 MSB}				c1;
	rhRio ← T1Count,					c2;
	TOS ← MD and T, {mask high byte}			c3;

{ read timer one, lower 16 bits, and finish higher (interlaced instructions)}

	IO ← [rhRio, 0], {Cnt 1 LSB}				c1;
	TOS ← TOS LRot8 or Q, {combine timer 2 bytes}		c2;
	Q ← MD and T, {mask high byte}				c3;

	IO ← [rhRio, 0], {Cnt 1 MSB}				c1;
	TOS ← 0 - TOS, {down count},				c2;
	T ← MD and T, {mask high byte}				c3;

	T ← T LRot8 or Q, {combine timer 1 bytes}		c1;
	T ← 1 - T, {down count, carries at 1}			c2;
	[] ← T or Rx, NZeroBr, {timing glitch when T is 0}	c3;

	STK ← T, BRANCH[$,RRx], {in Misc.mc}			c1;
	Rx ← 1, {need only one repeat}				c2;
	rhRio ← T012Control, GOTO[ReadTimer],			c3;
	

{-------------------------------------------------------------------------
	Daybreak Specific Additions
-------------------------------------------------------------------------}

{@RawRead:
	rhRio ← TOS LRot0,					c1, at[04,10,ESC8n];
	Rio ← STK, pop,						c2;
	pop,							c3;

	MAR ← [rhRio, Rio+0], push, GOTO[Ra], {In Read}		c1;

@RawWrite:
	rhRio ← TOS LRot0,					c1, at[05,10,ESC8n];
	Rio ← STK, pop,						c2;
	T ← STK, pop,						c3;

	MAR ← [rhRio, Rio+0], GOTO[Wb],				c1;}

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

@BYTESWAP:
	TOS ← TOS LRot8, pop,				c1, at[07,10,ESC8n];
	push, IBDisp, GOTO[DISPNIonly],			c2;


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

{@LOCKMEM: [operation, offset, value, mask] RETURNS [result]}
{TOS contains lock mask}
{T is loaded with value for operation}
{TT is loaded with offset into IORegion, whose base address is in [uIORgnHigh, rIORgn]}
{rhT is loaded with operation code}

@LOCKMEM:
	T ← STK, pop,						c1, at[08,10,ESC8n];
	TT ← STK, pop, L4 ← SoftwareLockRets.LOCKMEM,		c2;
	rhT ← STK, pop,						c3;

	MAR ← [rhIORgn, rIORgn + iopRequestsLock],		c1;
	TT ← TT + rIORgn, CANCELBR[SoftwareLockSideDoor,0],	c2;

	MDR ← 0, IBDisp, push, CANCELBR[$,0],			c2, at[SoftwareLockRets.LOCKMEM,10,SoftwareLockRets];
	STK ← TOS, fXpop, fZpop, DISPNI[OpTable],		c3;

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

@NOTIFYIOP: {TOS contains notify mask: byte-mask in high byte, byte offset in low}
	T ← uMesaProc,						c1, at[09,10,ESC8n];
	rhT ← uIORgnHigh,					c2;
	TT ← LShift1 (T + downNotifyBits), LOOPHOLE[niblTiming], c3;

	MAR ← [rhT, T + notifiersLockMask],			c1;
	STK ← TOS, T ← TOS and ~0FF, CANCELBR[$,0],		c2;
	TOS ← MD, L4 ← SoftwareLockRets.NOTIFYIOP,		c3;

	rhTT ← STK, pop, XLDisp,				c1;
{the following branch is reversal of Mesa byte order to do byte-swapping for IOP}
	TT ← RShift1 (TT + rhTT), LOOPHOLE[niblTiming], BRANCH[MaskInLowByte,$,2], c2;
	rhT ← lock.or, SetMPIntIOP, CALL[SoftwareLock],		c3;
MaskInLowByte:
	rhT ← lock.or, SetMPIntIOP,				c3;

	MAR ← [rhIORgn, rIORgn + iopRequestsLock],		c1;
	T ← T LRot8, CANCELBR[SoftwareLockSideDoor,0],		c2;

	MDR ← 0, IBDisp, CANCELBR[$,0],				c2, at[SoftwareLockRets.NOTIFYIOP,10,SoftwareLockRets];
	ClrMPIntIOP, DISPNI[OpTable],				c3;

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

@SetWakeupBits:
	T ← TOS, push, MesaIntRq,				c1, at[0A,10,ESC8n];
	STK ← TOS, pop,						c2;
	TOS ← STK, pop,						c3;

	T ← T or uWP,						c1;
	uWP ← T, IBDisp, GOTO[DISPNIonly],			c2;


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

{Catch unused landing spots.}

@a206:	PC ← PC - 1, GOTO[ESCb],				c1, at[06,10,ESC8n];

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

{SoftwareLock subroutine
L4 contains return branch
TOS contains mask
T contains value
TT contains low real address of word on which locked op is done
rhT contains operation code in lower three bits
on return, TOS contains result}

SoftwareLock:
	MAR ← [rhIORgn, rIORgn + iopRequestsLock],			c1;
	CANCELBR[$,0],							c2;
SoftwareLockSideDoor:
	Rx ← MD,							c3;

	Rx ← TOS and Rx,						c1;
	[] ← Rx, ZeroBr, {zero iff lock available}			c2;
	BRANCH[SoftwareLock,$],						c3;

	MAR ← [rhIORgn, rIORgn + mesaHasLock],				c1;
	MDR ← TOS, CANCELBR[$,0],					c2;
	rhTT ← uIORgnHigh,						c3;

LockAcquired:
	MAR ← [rhTT, TT + 0],						c1;
	Xbus ← rhT, XDisp,						c2;
	TOS ← MD, DISP4[LockedOp,08],					c3;

LockedAdd:
	MAR ← [rhTT, TT + 0],						c1, at[lock.add,10,LockedOp];
	MDR ← TOS ← T + TOS, GOTO[ClearLock],				c2;

LockedAnd:
	MAR ← [rhTT, TT + 0],						c1, at[lock.and,10,LockedOp];
	MDR ← TOS ← T and TOS, GOTO[ClearLock],				c2;

LockedOr:
	MAR ← [rhTT, TT + 0],						c1, at[lock.or,10,LockedOp];
	MDR ← TOS ← T or TOS, GOTO[ClearLock],				c2;

LockedXchg:
	MAR ← [rhTT, TT + 0],						c1, at[lock.xchg,10,LockedOp];
	MDR ← T, GOTO[ClearLock],					c2;

LockedWrIfNil:
	[] ← TOS, ZeroBr,						c1, at[lock.wrIfNil,10,LockedOp];
	BRANCH[ClearLock,$],						c2;
	GOTO[LockedOr] {same as write, since TOS = 0},			c3;

ClearLock:
	L4Disp,								c3;

	MAR ← [rhIORgn, rIORgn + mesaHasLock], DISP4[SoftwareLockRets],	c1;