; LarkMonIntML.dsm
; Interrupt assistance

; L. Stewart, September 14, 1982  10:51 PM
; L. Stewart, October 26, 1982  1:51 PM
;   INT 5 will be CallDebugger
; L. Stewart, November 8, 1982
;   delete DOXXI, add osstatic globals
; November 10, 1982  3:50 PM, leave 3FC - 3FF empty
; February 7, 1983  8:12 PM, new monitor
; February 23, 1983  10:31 AM, incorporate wdc
; February 25, 1983  3:47 PM, DoEOI, check for badint

$INCLUDE(Lark.d)
$INCLUDE(8086LIB.D)

; interrupt data

SLRType	EQU	070H			; IR0
SLTType	EQU	071H
EncType	EQU	072H
SIOType	EQU	073H
AlAType	EQU	074H
AlBType	EQU	075H
AlCType	EQU	076H
AlDType	EQU	077H

ei70ip	EQU	01C0H
ei70cs	EQU	01C2H
ei71ip	EQU	01C4H
ei71cs	EQU	01C6H
ei72ip	EQU	01C8H
ei72cs	EQU	01CAH
ei73ip	EQU	01CCH
ei73cs	EQU	01CEH
ei74ip	EQU	01D0H
ei74cs	EQU	01D2H
ei75ip	EQU	01D4H
ei75cs	EQU	01D6H
ei76ip	EQU	01D8H
ei76cs	EQU	01DAH
ei77ip	EQU	01DCH
ei77cs	EQU	01DEH

C←CODE	SEGMENT

C←DATA	SEGMENT

EXTRN	←stackLimit:WORD

lenStatics EQU 267
intpv		LABEL	WORD
←SLRInt	DW	?
←SLTInt	DW	?
←EncInt	DW	?
←SIOInt	DW	?
←AlAInt	DW	?
←AlBInt	DW	?
←AlCInt	DW	?
←AlDInt	DW	?
←wdc		DW	0
←OStack	DW	0
←IStack	DW	256 DUP (?)
←ISTop	DW	0

C←DATA	ENDS

EXTRN	←CallDebugger:NEAR
EXTRN	←Call0:NEAR
EXTRN	←Zero:NEAR

ASSUME CS:C←CODE, DS:C←DATA

; Enable interrupts
←IntOn	PROC	NEAR
	MOV	←wdc,0
	STI
	RET
←IntOn	ENDP

; Disable interrupts
←IntOff	PROC	NEAR
	MOV	←wdc,8000
	CLI
	RET
←IntOff	ENDP

; Analog D (IR7)
AlDInt:
	PUSH	BX
	MOV	BX,←AlDInt
	JMP	←intcom

; Analog C (IR6)
AlCInt:
	PUSH	BX
	MOV	BX,←AlCInt
	JMP	←intcom

; Analog B (IR5)
AlBInt:
	PUSH	BX
	MOV	BX,←AlBInt
	JMP	←intcom

; Analog A (IR4)
AlAInt:
	PUSH	BX
	MOV	BX,←AlAInt
	JMP	←intcom

; 8274 (IR3)
SIOInt:
	PUSH	BX
	MOV	BX,←SIOInt
	JMP	←intcom

; Encryption (IR2)
EncInt:
	PUSH	BX
	MOV	BX,←EncInt
	JMP	←intcom

; SLT (IR1)
SLTInt:
	PUSH	BX
	MOV	BX,←SLTInt
	JMP	←intcom

; SLR (IR0)
SLRInt:
	PUSH	BX
	MOV	BX,←SLRInt
	JMP	←intcom
	CALL	←intcom	; for symbol! never executed

←intcom:
	PUSH	AX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DI
	PUSH	BP
; check ISR
	MOV	AL,00BH
	OUT	intctl,AL
	IN	AL,intctl
	OR	AL,AL
	JNZ	hndokb
	MOV	BX,0800CH
	CALL	←CallDebugger
	JMP	iretr
hndokb:
; check handler
	OR	BX,BX
	JNZ	hndok
	MOV	BX,08002H
;
; if this happens, the interrupt type will be in AL
;
	CALL	←CallDebugger
	JMP	iretr
hndok:

	MOV	←OStack,SP	; save old stack
	MOV	SP,OFFSET ←ISTop
	PUSH	←stackLimit
	MOV	AX,OFFSET ←IStack+20
	MOV	←stackLimit,AX
	INC	←wdc
	CALL	←Call0
	DEC	←wdc
	POP	←stackLimit
	MOV	SP,←OStack
iretr:
; interrupt handlers should return true if they want an EOI
	OR	BX,BX
	JE	noeoi
	MOV	AL,020H
	OUT	intctl,AL
noeoi:
	POP	BP
	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	AX
	POP	BX
	IRET

; Send EOI to the PIC
←DoEOI	PROC	NEAR
	MOV	AL,020H
	OUT	intctl,AL
	RET
←DoEOI	ENDP

; Set up interrupt vectors
←IntInit	PROC	NEAR
	MOV	CX,OFFSET intpv
	MOV	BX,lenStatics
	CALL	←Zero
; now set up actual handlers
	MOV	CX,ei70ip
	MOV	BX,16
	CALL	←Zero
	XOR	BX,BX
	MOV	[ei70ip+BX],OFFSET SLRInt
	MOV	[ei71ip+BX],OFFSET SLTInt
	MOV	[ei72ip+BX],OFFSET EncInt
	MOV	[ei73ip+BX],OFFSET SIOInt
	MOV	[ei74ip+BX],OFFSET AlAInt
	MOV	[ei75ip+BX],OFFSET AlBInt
	MOV	[ei76ip+BX],OFFSET AlCInt
	MOV	[ei77ip+BX],OFFSET AlDInt
	RET
←IntInit	ENDP

; Set 8259 mask, 1's indicate channels to be enabled
←IntMask	PROC	NEAR
	MOV	AL,BL
	XOR	AL,0FFH
	OUT	intdata,AL
	RET
←IntMask	ENDP

; read 8259 mask, 1's indicate enabled channels
←ReadIMask	PROC	NEAR
	IN	AL,intdata
	XOR	AL,0FFH
	MOV	BL,AL
	XOR	BH,BH
	RET
←ReadIMask	ENDP

; EnableInt(proc, type)
; where type is in 0..7

←EnableInt	PROC	NEAR
	AND	BX,7
	MOV	SI,OFFSET intpv
	ADD	SI,BX
	ADD	SI,BX
	MOV	WORD PTR [SI],CX
	MOV	CX,BX
	MOV	AX,1
	SAL	AX,CX
	MOV	BX,AX
; enable mask bits given in BL
	IN	AL,intdata
	XOR	BL,0FFH
	AND	AL,BL
	OUT	intdata,AL
	RET
←EnableInt	ENDP

; disable interrupt type given in BL
←DisableInt	PROC	NEAR
	AND	BX,7
	MOV	SI,OFFSET intpv
	ADD	SI,BX
	ADD	SI,BX	; word offset
	MOV	WORD PTR [SI],0
	MOV	CX,BX
	MOV	AX,1
	SAL	AX,CX
	MOV	BX,AX
	IN	AL,intdata
	OR	AL,BL
	OUT	intdata,AL
	RET
←DisableInt	ENDP

; read 8259 IRR
←ReadIRR	PROC	NEAR
	MOV	AL,00AH
	OUT	intctl,AL
	IN	AL,intctl
	MOV	BL,AL
	XOR	BH,BH
	RET
←ReadIRR	ENDP

; read 8259 ISR
←ReadISR	PROC	NEAR
	MOV	AL,00BH
	OUT	intctl,AL
	IN	AL,intctl
	MOV	BL,AL
	XOR	BH,BH
	RET
←ReadISR	ENDP

; increment wakeup disable counter
←IWDC	PROC	NEAR
; added check
	MOV	AX,←wdc
	OR	AX,AX
	JNS	iwok
	MOV	BX,08003H
	CALL	←CallDebugger
iwok:
; end added check
	INC	←wdc
	CLI
	RET
←IWDC	ENDP

; decrement wakeup disable counter
←DWDC	PROC	NEAR
	DEC	←wdc
	MOV	AX,←wdc
	OR	AX,AX
; added check
	JNS	dwok
	MOV	BX,08003H
	CALL	←CallDebugger
	OR	AX,AX
dwok:
; end added check
	JNZ	dwdcr
	STI
dwdcr:
	RET
←DWDC	ENDP

; return wakeup disable counter
←GetWDC	PROC	NEAR
	MOV	BX,←wdc
	RET
←GetWDC	ENDP

PUBLIC	←IntInit
PUBLIC	←IntOn
PUBLIC	←IntOff
PUBLIC	←IntMask
PUBLIC	←ReadIMask
PUBLIC	←DoEOI
PUBLIC	←EnableInt
PUBLIC	←DisableInt
PUBLIC	←ReadIRR
PUBLIC	←ReadISR
PUBLIC	←wdc
PUBLIC	←IWDC
PUBLIC	←DWDC
PUBLIC	←GetWDC

C←CODE	ENDS
	END