; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; watchdog source

        [ NewErrorSystem

watchdogguard   DCD     &E240569E

        [ WatchdogTimer

BreakWatchdogHandler
        Push    "R0-R1"

       |

BreakWatchdogHandler

        TEQ     R0,#Event_Keyboard
        MOVNE   PC,lr
        TEQ     R1,#1                   ; only interested in key down
        MOVNE   PC,lr
        [ SnapShot
        TEQ     R2,#13
        BEQ     capturescreen
        ]
        TEQ     R2,#15                  ; break key
        MOVNE   PC,lr
        Push    "R0-R1"
        ]

        [ No32bitCode
        MOV     R0,PC
        TEQP    PC,#SVC_mode
        NOP
        |
        MRS     R0,CPSR
        ORR     R1,R0,#SVC_mode
        BIC     R1,R1,#I32_bit+F32_bit
        MSR     CPSR_c,R1
        ]

        Push    "R0-R2,LR"
        LDR     R0,watchdogcodew
        TEQ     R0,#0
        BNE     watchdogend
        LDR     R0,watchdogarea
        LDR     R1,watchdogguard
        CMP     R0,R1
        BEQ     watchdogend

        [ WatchdogTimer
; the event based system has already checked for break key.

        MOV     R0,#121
        MOV     R1,#44:EOR:128                         ; Break
        SWI     XOS_Byte
        CMP     R1,#&ff
        BNE     watchdogend
        ]

        MOV     R0,#121
        MOV     R1,#2:EOR:128                          ; Alt
        SWI     XOS_Byte
        CMP     R1,#&ff
        BNE     watchdogend
        MOV     R0,#121
        MOV     R1,#1:EOR:128                          ; Ctrl
        SWI     XOS_Byte
        CMP     R1,#&ff
        BEQ     watchdogend                            ; only Break
        MOV     R0,#121
        MOV     R1,#0:EOR:128                          ; Shift
        SWI     XOS_Byte
        CMP     R1,#&ff
        BEQ     watchdogend

        LDR     R1,watchdogguard
        STR     R1,watchdogarea
        LDR     R1,taskhandle
        STR     R1,watchdogtask
        MOV     R1,#-1
        STR     R1,watchdogtaskno
        ADR     R0,watchdogcallback
        MOV     R1,R12
        SWI     XOS_AddCallBack
        MOV     R0,#124
        SWI     XOS_Byte                                ; clear escape condition
watchdogend
        Pull    "R0-R2,LR"
        [ No32bitCode
        TEQP    PC,R0
        NOP
        |
        MSR     CPSR_c,R0
        ]
        Pull    "R0-R1,PC"

        LTORG

kill_labels
        DCB     "Watchdog:Stop,Cancel,Next Task"
        DCB     0

	ALIGN
watchdogcallback
        Push    "R0-R7,R14"

        LDR     R0,watchdogtask                 ; R0 = task handle
        LDR     R1,[wsptr,R0]                   ; R1 -> task record
        TEQ     R1,#task_unused
        LDRNE   R7,taskhandle                   ; save this as we may have to page
        STRNE   R0,taskhandle
;
        BLNE    fulltaskhandle
        STRNE   R7,taskhandle                   ; put it back just in case
        MOVNE   R0,R14
        MOVEQ   R0,#0
; setup meaningful task handle =0 if none, else current

        SWI     XTaskManager_TaskNameFromHandle       ; get task name
        ADRVS   R0,notaskname

        MOV     R4,R0

        LDR     R0,commandflag
        TEQ     R0,#cf_active

        ADRNE   R0,killapptoken
        ADREQ   R0,killprogtoken

        ADRL    R2,watchdogerrtxt
        MOV     R3,#?watchdogerrtxt
        MOV     R5,#0
        BL      LookupToken

        ADRL    R0,watchdogerror
        LDR     R1,=&050DEAD0                   ; user1
        STR     R1,[R0]
        MOV     R1,#256+2048+512                   ; new bits
        ADR     R2,watchdogappname
        MOV     R3,#0
        MOV     R4,#1
        SUB     SP,SP,#64
        Push    "R0-R4"
        ADR     R0,kill_labels
        ADD     R2,SP,#20
        MOV     R3,#64
        BL      LookupToken1
        MOV     R5,R2

        MOV     R0,#124
        SWI     XOS_Byte                        ; BASIC may have caused an escape condition

        Pull    "R0-R4"
        SWI     XWimp_ReportError
        ADD     SP,SP,#64
        CMP     R1,#5                           ; next
        BNE     watchdognext
taskloop
        LDR     R0,watchdogtaskno
        ADD     R0,R0,#1
        CMP     R0,#maxtasks
        BEQ     watchdognext
        STR     R0,watchdogtaskno
        ADRL    R3,taskpointers
        ADD     R0,R3,R0, LSL #2
        LDR     R2,[R0]
        TEQ     R2,#task_unused
        BEQ     taskloop
        SUB     R0,R0,wsptr
        STR     R0,watchdogtask
        ADR     R0,watchdogcallback
        MOV     R1,R12
        SWI     XOS_AddCallBack
      [ NCErrorBox
        ADRL    R1, ptrpreserveflag
        MOV     R0, #1
        STR     R0, [R1]                         ; note not to move the pointer
      ]
        Pull    "R0-R7,PC"
watchdognext
        CMP     R1,#3                            ; kill
        CMPNE   R1,#1                            ; ok if text mode
        STR     R1,watchdogarea

        Pull    "R0-R7,PC",NE

        LDR     R0,watchdogtask
        STR     R0,newtaskhandle
        BL      printjobrunning

        LDR     R14,taskhandle

        TEQ     R0,R14                  ; current task going to die?
        BEQ     %FT05

        MOV     R7, R14                 ; keep [taskhandle] so we can restore it later
        STR     R0, taskhandle
        BL      fulltaskhandle          ; R14 = full task handle for watchdogtask
        STR     R7, taskhandle

        MOV     R0, R14
        LDR     R1, taskidentifier5
        SWI     XWimp_CloseDown         ; kill the selected task (!= current task)

        Pull    "R0-R7,PC"

taskidentifier5 DCB "TASK"

05
        SWI     XHourglass_Smash        ; turn off hourglass (if displayed)
                                        ; If kill message was textual, this wont have
                                        ; been done

                                        ; errorstack held the most recently used sprite area
        LDR     R0,errorstack-8
        CMP     R0,#&8000               ; were we in a sprite ?

        Pull    "R0-R7" ,LO

        SWILO   OS_Exit                 ; can safely exit
        LDR     R14,orig_applicationspacesize
        CMP     R0,R14

        Pull    "R0-R7",HS

        SWIHS   OS_Exit                 ; outside app space

        MOV     R0,#SpriteReason_SwitchOutputToSprite
        MOV     R1,#0
        MOV     R2,#0
        MOV     R3,#0
        SWI     XOS_SpriteOp            ; make sure output is switched to the screen

        Pull    "R0-R7"

        SWI     OS_Exit

        LTORG

killapptoken
        DCB     "KillApp",0

        ALIGN

killprogtoken
        DCB     "KillProg",0  ; we're in command mode

        ALIGN

notaskname
        DCB     "Unknown",0

        ALIGN

watchdogappname
        DCB     "Window Manager",0
        ALIGN

printjobrunning Entry R0
        LDR     R14,taskhandle
        TEQ     R0,R14                  ; killing current task ?
        EXIT    NE
        SWI     XPDriver_CurrentJob
        EXIT    VS
        TEQ     R0,#0
        EXIT    EQ
        SWI     XPDriver_AbortJob
        EXIT


        ]

        LTORG

SWIWimp_SetWatchdogState
        MyEntry "SetWatchdogState"

        [ NewErrorSystem
        TEQ     R0,#0
        BNE     %FT01
        LDR     R14,watchdogcodew
        TEQ     R14,#0                          ; already disabled ?
        EOREQ   R1,R1,R12
        STREQ   R1,watchdogcodew
        BEQ     ExitWimp
01
        LDR     R0,watchdogcodew
        EOR     R0,R0,R12
        EORS    R0,R0,R1
        STREQ   R0,watchdogcodew
        ]
        B       ExitWimp

        [ SnapShot
capturescreen
        Push    "R0-R1"
        [ No32bitCode
        MOV     R0,PC
        TEQP    PC,#SVC_mode                            ; need a stack!!!
        NOP
        |
        MRS     R0,CPSR
        BIC     R1,R0,#I32_bit+F32_bit
        ORR     R1,R1,#SVC_mode
        MSR     CPSR_c,R1
        ]

        Push    "R0-R2,LR"
        MOV     R0,#121
        MOV     R1,#2:EOR:128                          ; Alt
        SWI     XOS_Byte
        CMP     R1,#&ff
        ADREQ   R0,screen_callback
        SWIEQ   XOS_AddCallBack
        B       watchdogend

screen_callback
        Push    "R0-R3,lr"
        MOV     R3,#1
        ADR     R2,scrn_pathname
        MOV     R0,#SpriteReason_ScreenSave
        SWI     XOS_SpriteOp
        MOVVS   R1,#1
        MOVVS   R2,#0
        SWIVS   XWimp_ReportError
        Pull    "R0-R3,PC"

scrn_pathname
        DCB     "<Wimp$scrapdir>.!!Screen!!",0

        ALIGN
 ]

        END