git @ Cat's Eye Technologies BefOS / master src / kernel / interrupt.s
master

Tree @master (Download .tar.gz)

interrupt.s @masterraw · history · blame

;--- BEGIN ---------------------------------------------------;

;--- DATA ----------------------------------------------------;

SEGMENT	.data

timerSegment:	dw 0
timerOffset:	dw 0
comSegment:	dw 0
comOffset:	dw 0
breakSegment:	dw 0
breakOffset:	dw 0
prtscSegment:	dw 0
prtscOffset:	dw 0

;--- CODE ----------------------------------------------------;

SEGMENT	.text

		;;--------------------------------------------;
		;; Install an interrupt handler.
		;; bl: interrupt number -> GARBAGE
		;; cx: segment of interrupt handler routine -> GARBAGE
		;; di: offset of interrupt handler routine -> GARBAGE
		;; ax: * -> GARBAGE
		;; bh: * -> GARBAGE
WriteIntr:	push	es

		xor	bh, bh
		shl	bx, 2		; bx = zero page intr loc

		xor	ax, ax
		mov	es, ax

		cli			; disable interrupts
					; poke vector into zero page

		mov	[es:0000h + bx], di
		mov	[es:0002h + bx], cx

		sti			; enable interrupts

		pop	es
		ret


		;;--------------------------------------------;
		;; Retrieve an interrupt handler.
		;; bl: interrupt number -> GARBAGE
		;; cx: * -> segment of interrupt handler routine
		;; di: * -> offset of interrupt handler routine
		;; ax: * -> GARBAGE
		;; bh: * -> GARBAGE
ReadIntr:	push	es

		xor	bh, bh
		shl	bx, 2		; bx = zero page intr loc
					; peek vector from zero page

		xor	ax, ax
		mov	es, ax

		mov	di, [es:0000h + bx]
		mov	cx, [es:0002h + bx]

		pop	es
		ret


PlugClock:	call	WorkLight

		mov	bl, 1ch
		call	ReadIntr

		mov	[timerSegment], cx
		mov	[timerOffset], di

		mov	cx, cs
		mov	di, ClockISR
		mov	bl, 1ch		; user clock interrupt
		call	WriteIntr

		jmp	OKLight



UnplugClock:	call	WorkLight
		mov	cx, [timerSegment]
		cmp	cx, 0
		je	.Fail
		mov	[timerSegment], word 0
		mov	di, [timerOffset]
		mov	bl, 1ch		; user clock interrupt
		call	WriteIntr
		call	OKLight
		ret
.Fail:		jmp	BadLight



ClockISR:	push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di

		mov	ax, 0040h
		mov	ds, ax
		mov	cx, [006ch]		; get timer value from BIOS
		mov	ax, cs
		mov	ds, ax
		call	TextVidBase		; since we have no assurance
						; that es=screen during intr
		call	StatusWord

		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax

		iret



PlugBreak:	call	WorkLight

		mov	bl, 1bh
		call	ReadIntr

		mov	[breakSegment], cx
		mov	[breakOffset], di

		mov	cx, cs
		mov	di, BreakISR
		mov	bl, 1bh		; user clock interrupt
		call	WriteIntr

		jmp	OKLight



UnplugBreak:	call	WorkLight
		mov	cx, [breakSegment]
		cmp	cx, 0
		je	.Fail
		mov	[breakSegment], word 0
		mov	di, [breakOffset]
		mov	bl, 1bh		; user clock interrupt
		call	WriteIntr
		jmp	OKLight
.Fail:		jmp	BadLight



;	This is a *very* special kind of ISR; it takes a very
;	proactive approach to resetting BefOS.

BreakISR:	mov	ax, cs
		mov	ds, ax

		call	UnplugClock
		;call	UnplugCom
		call	UnplugBreak
		call	UnplugPrtSc

		xor	al, al
		mov	[flags], al		; clear modes

		sti

;	At this point, we can't even get back to the caller,
;	so dismiss the idea of ending this with 'iret' or 'retf'.
;	Instead we shall use a far jump.

		jmp	BEFOS_SEG:BEFOS_OFF



PlugPrtSc:	call	WorkLight

		mov	bl, 05h
		call	ReadIntr

		mov	[prtscSegment], cx
		mov	[prtscOffset], di

		mov	cx, cs
		mov	di, PrtScISR
		mov	bl, 05h		; prtsc interrupt
		call	WriteIntr

		jmp	OKLight



UnplugPrtSc:	call	WorkLight
		mov	cx, [prtscSegment]
		cmp	cx, 0
		je	.Fail
		mov	[prtscSegment], word 0
		mov	di, [prtscOffset]
		mov	bl, 05h		; prtsc interrupt
		call	WriteIntr
		jmp	OKLight
.Fail:		jmp	BadLight


PrtScISR:	push	ax
		push	bx
		push	cx
		push	dx
		push	ds
		push	es
		push	di

		call	TextVidBase		; since we have no assurance
						; that es=screen during intr
		mov	ax, 1234h
		call	Light

		pop	di
		pop	es
		pop	ds
		pop	dx
		pop	cx
		pop	bx
		pop	ax

		iret