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