{  File:  [Iris]<WMicro>DLion>Common.asm

Dennis Grundler  1-Sep-84 17:04:04  Added copyright notice
Michael Thatcher 21-Dec-83 15:18:41  Added Async Flow Control
Dennis Grundler 18-Jan-83 17:52:44: Rearrange MPanel routines for further optimization.
Dennis Grundler  5-Dec-82 20:53:53: Modify MPanel routines
Jim Frandeen July 30, 1982  12:41 PM: new IOPage format
Rewritten by Jim Frandeen April 2, 1982  8:26 AM
Written by Roy Ogus (As Exec) May 6, 1980 2:26 PM}

{ 	Copyright (C) 1980, 1982, 1983 by Xerox Corporation.  All rights reserved.}


;  DEFINITION FILES:

	GET	"SysDefs"
	GET	"CommonDefs"
	GET	"FloppyDefs"

;  IMPORTS/EXPORTS:

	IMP	ExitInterrupt	;From RS232CSubs
	IMP	FloppyIntr		;From FloppyTask
	IMP	NoMoreBytesToSend	;From RS232CInterrupts
	IMP	RxAsyncDataInt	;From RS232CGet
	IMP	RxAsyncExternalInt	;From RS232CGet
	IMP	RxAsyncSpecialInt	;From RS232CGet
	IMP	RxSDLCDataInt	;From RS232CGet
	IMP	RxSDLCExternalInt	;From RS232CGet
	IMP	RxSDLCSpecialInt	;From RS232CGet
	IMP	RxBisyncExternalInt	;From RS232CGet
	IMP	RxBisyncSpecialInt	;From RS232CGet
	IMP	RxIllegalInt		;From RS232CSubs
	IMP	Start
	IMP	TxAsyncDataInt		;From RS232CInterrupts
	IMP	TxAsyncExternalInt	;From RS232CInterrupts
	IMP	TxSDLCExternalInt	;From RS232CInterrupts
	IMP	TxBisyncExternalInt	;From RS232CInterrupts
	IMP	TxIllegalInt		;From RS232CSubs

	EXP	AsyncJumpTable
	EXP	ClearMiscControl1Bit
	EXP	ClearMPanel
	EXP	DisableRST
	EXP	DoMiscClock
	EXP	EnableRST
	EXP	ErrorReport
	EXP	KeyMap
	EXP	MiscControl1Val
	EXP	NegativeMPValue
	EXP	PutMPanel
	EXP	PutMPanel1
	EXP	RS232CInterruptSwitch
	EXP	RxBisyncStateSwitch
	EXP	SetMiscControl1Bit
	EXP	Wait
	EXP	ZeroCommand
;
;---------------- START of Program @ 2000H -------------------------
Go:
	JMP	Start
;----------------- Hook for Kernel BurdockCP interrupt @ 2003H------
GoToBurdockCPIntr:
	JMP	BurdockCPIntrError
;----------------- Hook for RS232C RST 6.5 interrupt @ 2006H------
GoToRS232CIntr:
	DB	opJMP		;JMP oc code
RS232CInterruptSwitch:
	DW	0
;	JMP	AsyncRS232CInterrupt
;	JMP	SdlcRS232CInterrupt
;	JMP	BisyncRS232CInterrupt
;----------------- Hook for Floppy RST 7.5 interrupt @ 2009H------
GoToFloppyIntr:
	JMP	FloppyIntr		;Go to Floppy interrupt routine
;----------------- Hook for IOP break RST 2 @ 200CH------
GoToIOPBreakTrap:
	lxi	h,ErrorIOPBreak
	JMP	ErrorReport
;------------------------------------------------------------
	
KeyMap:
{ First 8 bytes are Alto keyboard map.  Last 4 bytes are Extended Map. Note:  Bit = 0 means DOWN, bit = 1 means UP. Bytes are stored least significant byte, then most significant byte}
	DB	0FFH		;0: Zero,K,Dash,P,Slash,BackSlash,LF,BS
	DB	0FFH		;1: Five,Four,Six,E,Seven,D,U,V

	DB	0FFH		;2: X,O,L,Comma,Quote,RightBracket,Spare2,Spare1
	DB	0FFH		;3: Three,Two,W,Q,S,A,Nine,I

	DB	0FFH		;4: Z,LeftShift,Period,SemiColon,Return,Arrow,DEL,FL3
	DB	0FFH		;5: One,ESC,TAB,F,Ctrl,C,J,B

	DB	0FFH		;6: Lock,Sp,LeftBracket,Equal,RightShift,Spare3,FL4,FR5
	DB	0FFH		;7: R,T,G,Y,H,Eight,N,M

	DB	0FFH		;8: A8, L8, L5, L2, R2, R7, R4, D2
	DB	0FFH		;9: R5, R9, L10, L7, L4, L1, A9, R10

	DB	0FFH		;A: T8, T10, R3, Key47, A10, R8, A11, A12
	DB	0FFH		;B: D1, Key48, T1, T3, T4, T5, T6, T7
;
ZeroCommand:
	DW	0

{The next location is at 2020. This is the jump table to jump to the appropriate RS232C interrupt handler for SDLC mode. We start at an address with zero in the 5 low order bits so that we can multiply the inerrupt vector by two and OR the result into a jump table address.}
SDLCJumpTable:
	JMP	NoMoreBytesToSend	;When Vecter =0 Tx Buffer Empty
	DB	0
	JMP	TxSDLCExternalInt	;When Vecter =2 Ex Stat
	DB	0
	JMP	TxIllegalInt	;When Vecter =4 Tx Char
	DB	0
	JMP	ExitInterrupt	;When Vecter =6 Sp Tx Cond
	DB	0
	JMP	RxIllegalInt	;When Vecter =8 Tx Buffer Empty
	DB	0
	JMP	RxSDLCExternalInt	;When Vecter =A Ex Stat
	DB	0
	JMP	RxSDLCDataInt	;When Vecter =C Rx Char
	DB	0
	JMP	RxSDLCSpecialInt	;When Vecter =E Sp Rx Cond
	DB	0

{The next location is at 2040. This is the jump table to jump to the appropriate RS232C interrupt handler for Bisync mode. We start at an address with zero in the 5 low order bits so that we can multiply the inerrupt vector by two and OR the result into a jump table address.}
BisyncJumpTable:
	JMP	TxIllegalInt	;When Vecter =0 Tx Buffer Empty
	DB	0
	JMP	TxBisyncExternalInt	;When Vecter =2 Ex Stat
	DB	0
	JMP	TxIllegalInt	;When Vecter =4 Tx Char
	DB	0
	JMP	ExitInterrupt	;When Vecter =6 Sp Tx Cond
	DB	0
	JMP	RxIllegalInt	;When Vecter =8 Tx Buffer Empty
	DB	0
	JMP	RxBisyncExternalInt	;When Vecter =A Ex Stat
	DB	0
	DB	opJMP		;When Vecter =C Rx Char
RxBisyncStateSwitch:
	DW	0
	DB	0
	JMP	RxBisyncSpecialInt	;When Vecter =E Sp Rx Cond
	DB	0

{The next location is at 2060. This is the jump table to jump to the appropriate RS232C interrupt handler for Async mode. We start at an address with zero in the 5 low order bits so that we can multiply the interrupt vector by two and OR the result into a jump table address.}
AsyncJumpTable:
	JMP	TxAsyncDataInt	;When Vecter =0 Tx Buffer Empty
	DB	0
	JMP	TxAsyncExternalInt	;When Vecter =2 Ex Stat
	DB	0
	JMP	TxIllegalInt	;When Vecter =4 Tx Char
	DB	0
	JMP	ExitInterrupt	;When Vecter =6 Sp Tx Cond
	DB	0
	JMP	RxIllegalInt	;When Vecter =8 Tx Buffer Empty
	DB	0
	JMP	RxAsyncExternalInt	;When Vecter =A Ex Stat
	DB	0
	JMP	RxAsyncDataInt	;When Vecter =C Rx Char
	DB	0
	JMP	RxAsyncSpecialInt	;When Vecter =E Sp Rx Cond
	DB	0
;
{COMMON  SUBROUTINES}


;  Programming the 8085 interrupt mask.
;  The two subroutines allow access to the 8085 interrupt mask.
;  Each subroutine has on entry, an RSTInterruptMask in A.
;  RSTInterruptMask format:
;	bit 0,1,2  -  don't care
;	bit 3       -  0 = don't reset RST 7.5 FF, 1 = Reset RST 7.5 FF
;	bit 4       -  don't care
;	bit 5       -  1 = Floppy interrupt (RST 7.5) specified, 0 = not specified
;	bit 6       -  1 = RS232C interrupt (RST 6.5) specified, 0 = not specified
;	bit 7       -  1 = Burdock/CP interrupt (RST 5.5) specified, 0 = not specified
;  Note:  RST 5.5 currently has privileged use.


;  Subroutine:  DisableRST [A:  RSTInterruptMask].
;   Program the interrupt mask to disable the specified interrupts in the 8085.
;  On entry:   A =  RSTInterruptMask.
DisableRST:
	ORI	MskSetEnable	;OR in IE bit
	MOV	D,A		;Save interrupt mask in D
	RIM			;Get current interrupt disable mask
	ANI	RSTMask	;Discard all but interrupt masks
	ORA	D		;OR in new values (can use directly)
	SIM			;Change the mask
	RET

;  Subroutine:  EnableRST [A:  RSTInterruptMask].
;   Program the interrupt mask to enable the specified interrupts in the 8085.
;   Note:  RST 7.5 FF can be cleared as well.
;  On entry:   A =  RSTInterruptMask.
EnableRST:
	MOV	D,A		;Save interrupt mask in D
	ANI	ResetRst75	;Isolate the Reset &.5 FF bit in mask
	ORI	MskSetEnable	;OR in IE bit
	MOV	E,A		;Save OR component in E
	MOV	A,D		;Retrieve interrupt mask again
	ANI	RSTMask		;Isolate RST flags
	CMA			;Make into active low signals
	MOV	D,A		;Save AND part in D
	RIM			;Get current interrupt disable mask
	ANI	RSTMask		;Discard all but interrupt masks
	ANA	D		;AND component
	ORA	E		;OR component 
	SIM			;Change the mask
	RET

;  Subroutine:  Wait [H,L:  WaitValue].
;   Waits a period of time specified in H,L (16 bits).
;  On entry:   H,L = wait value.
;  Delay is approx:  38 +  20*WaitValue  cycles  
;  	  =  13 +  6.67*WaitConst  usec  
Wait:
	PUSH	psw		;[12] Save A
	XRA	A		;[4] Clear A
WaitLoop:
	DCX	H		;[6]
	CMP	L		;[4] Check low
	JNZ	WaitLoop	;[10]
	CMP	H		;[4] Check high
	JNZ	WaitLoop	;[10]

	POP	psw		;[10] Restore A
	RET			;[12]

;  Subroutine:  PutMPanel.
;  Put a number in the maintenance panel (no Yields).
;  On entry:  H,L contains the number to be put in the panel.

NegativeMPValue:
	DW	-10000		;Negative (One more than the MP can hold).
ClearMPanel:
	LXI	H,0		;Place 0000 in the MP.
PutMPanel:
	XCHG
	LHLD	NegativeMPValue	;Load old value of MP.
	DAD	D		;Compute the difference in the MP values
PutMPanel1:
	MOV	A,H		;Check to see if new MP value is lower
	ORA	A		;Set the flags
	JP	SaveNegativeMPValue
	PUSH	D		;Save the new MP Value
	PUSH	D		;Again save the new MP Value
	MVI	D,ClrMPanel	;Mask for ClrMPanel clock
	CALL	DoMiscClock
	POP	H		;Fetch count from zero to new MP Value
	POP	D		;Restore the new MP Value
SaveNegativeMPValue:
	MOV	A,E		;save the 2's complement of the MP in NegativeMPValue
	CMA
	MOV	E,A
	MOV	A,D
	CMA	
	MOV	D,A
	INX	D
	XCHG
	SHLD	NegativeMPValue
	XCHG
	MVI	D,IncMPanel	;Mask for IncMPanel clock
	JMP	PutMPanelCheck	;Enter the loop with a check for 0000
PutMPanelLoop:
	CALL	DoMiscClock
	DCX	H		;Decrement the count
PutMPanelCheck:
	MOV	A,H
	ORA	L		;Check for HL equal 0
	JNZ	PutMPanelLoop	;Not 0 so we continue looping
UnBlankMP:
	MVI	A,nBlankMPanel		;unBlank the panel
;  Fall through to ClearMiscControl1Bit and return.


;  Subroutine:  ClearMiscControl1Bit [A:  Mask of bit(s) to be cleared].
;  Clear the bit(s) specified in A (by 0's) in MiscControl1Val and MiscControl1.

ClearMiscControl1Bit:
	DB	opANI		;Turn off bits in MiscControl1Val
MiscControl1Val2:
	DB	0
ChangeMiscControl1Bit:
	OUT	MiscControl1
	STA	MiscControl1Val
	STA	MiscControl1Val2
	RET

;  Subroutine:  SetMiscControl1Bit [A:  Mask of bit(s) to be set].
;  Set the bit(s) specified in A in MiscControl1Val and MiscControl1.

SetMiscControl1Bit:
	DB	opORI		;OR in current MiscControl1Val
MiscControl1Val:
	DB	0

	JMP	ChangeMiscControl1Bit

;  Subroutine [DoMiscClock].
;  Clocks a bit in the MiscClocks1 register.
;  Width of clock pulse is 14 cycles (~5 usec).
;    On entry:	D  contains a mask of the bit(s) to be toggled.

DoMiscClock:
	MVI	A,0FFH		;Set all high
	XRA	D		;Clear clock bit(s)
	OUT	MiscClocks1	
	XRA	D		;Toggle bit again
	OUT	MiscClocks1	
	RET


;  Trap:  ErrorReport.
;  Blink the Maintenance panel with the error code.
;  On entry:  H,L = error code.

ErrorReport:
	CALL	PutMPanel	;Put the number in the panel (no Yields)
	MVI	A,BlankMPanel	;Blank bit in A
ErrorTrap:
	OUT	MiscControl1	;Blank/unblank the panel
	LXI	H,BlinkConst	;H,L ← blink constant (~.5 sec)
	CALL	Wait
	XRI	BlankMPanel	;Toggle blank bit
	JMP	ErrorTrap

;  Burdock attempted to use the EtherKludge.  Signal an error.
BurdockCPIntrError:
	LXI	H,ErrorBurdockCPDisabled
	JMP	ErrorReport

	END	Common