; intml.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

$INCLUDE(Lark.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	←wdc:WORD
EXTRN	←stackLimit:WORD
EXTRN	←IStack:WORD
EXTRN	←ISTop:WORD

←AlAInt	DW	?
←AlBInt	DW	?
←AlCInt	DW	?
←AlDInt	DW	?
←SIOInt	DW	?
←EncInt	DW	?
←SLTInt	DW	?
←SLRInt	DW	?
←OStack	DW	0
IStack	DW	256 DUP (?)
ISTop	DW	0

C←DATA	ENDS

EXTRN	←CallDebugger:NEAR
EXTRN	←PortStr:NEAR
EXTRN	←Call0: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
	OR	BX,BX
	JNZ	hndok
	MOV	BX,08002H
	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:
	MOV	AL,020H
	OUT	intctl,AL
	POP	BP
	POP	DI
	POP	SI
	POP	DX
	POP	CX
	POP	AX
	POP	BX
	IRET

; All other interrupts
uimore:
	PUSH	AX
	PUSH	CX
	PUSH	DX
	PUSH	SI
	PUSH	DI
	PUSH	BP
	MOV	BH,081H
	CALL	←CallDebugger
	JMP	iretr

UnkInt:
; in principle, CS contains the interrupt type and IP has 
; whatever it takes to get control here.
	PUSH	BX
	MOV	BX,CS
	DB	0EAH	; long jump to
	DW	OFFSET uimore	; uimore
	DW	0

; set up 8259
; Mask all interrupts
←I8259	DB	intctl
	DB	1
	DB	01BH		; icw1 = level trigger, single, icw4

	DB	intdata
	DB	3
	DB	070H		; icw2 = interrupt vector base
	DB	001H		; icw3 = 8088 mode
	DB	0FFH

; end of string
	DB	0FFH

; Set up interrupt vectors
←IntInit	PROC	NEAR
	MOV	←IStack,OFFSET IStack
	MOV	←ISTop,OFFSET ISTop
	XOR	AX,AX
	XOR	BX,BX
	MOV	←AlAInt,AX
	MOV	←AlBInt,AX
	MOV	←AlCInt,AX
	MOV	←AlDInt,AX
	MOV	←SIOInt,AX
	MOV	←EncInt,AX
	MOV	←SLTInt,AX
	MOV	←SLRInt,AX
; set up all interrupts to point to UnkInt
; interrupts 0 through 5 are handled by the monitor
; The idea is that the interrupt type is encoded in the CS:IP pair
; so that CS holds the type and IP holds UnkInt-16*CS
	MOV	CX,249
	MOV	DI,018H
	MOV	BX,6
	MOV	DX,OFFSET UnkInt
	SUB	DX,050H
	CLD
suih:
	MOV	AX,DX
	STOSW
	MOV	AX,BX
	STOSW
	INC	BX
	SUB	DX,010H
	LOOP	suih
; now set up actual handlers
	XOR	AX,AX
	XOR	BX,BX
	MOV	[ei70cs+BX],AX
	MOV	[ei71cs+BX],AX
	MOV	[ei72cs+BX],AX
	MOV	[ei73cs+BX],AX
	MOV	[ei74cs+BX],AX
	MOV	[ei75cs+BX],AX
	MOV	[ei76cs+BX],AX
	MOV	[ei77cs+BX],AX

	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
	MOV	BX,OFFSET ←I8259
	CALL	←PortStr
	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

; enable mask bits given in BL
←EnableInt	PROC	NEAR
	IN	AL,intdata
	XOR	BL,0FFH
	AND	AL,BL
	OUT	intdata,AL
	XOR	AL,0FFH
	MOV	BL,AL
	XOR	BH,BH
	RET
←EnableInt	ENDP

; disable mask bits given in BL
←DisableInt	PROC	NEAR
	IN	AL,intdata
	OR	AL,BL
	OUT	intdata,AL
	XOR	AL,0FFH
	MOV	BL,AL
	XOR	BH,BH
	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

PUBLIC	←IntInit
PUBLIC	←IntOn
PUBLIC	←IntOff
PUBLIC	←AlAInt
PUBLIC	←AlBInt
PUBLIC	←AlCInt
PUBLIC	←AlDInt
PUBLIC	←SIOInt
PUBLIC	←EncInt
PUBLIC	←SLTInt
PUBLIC	←SLRInt
PUBLIC	←IntMask
PUBLIC	←ReadIMask
PUBLIC	←EnableInt
PUBLIC	←DisableInt
PUBLIC	←ReadIRR
PUBLIC	←ReadISR

C←CODE	ENDS
	END