View Source Document

interrupt.s

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