;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; RDOS operating system
; Copyright (C) 1988-2000, Leif Ekblad
;
; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version. The only exception to this rule
; is for commercial usage in embedded systems. For information on
; usage in commercial embedded systems, contact embedded@rdos.net
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
;
; The author of this program may be contacted at leif@rdos.net
;
; WD.ASM
; Software watchdog support
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

INCLUDE ..\..\kernel\user.def
INCLUDE ..\..\kernel\os.def
INCLUDE ..\..\kernel\os.inc
INCLUDE ..\..\kernel\user.inc
INCLUDE ..\..\kernel\driver.def
INCLUDE ..\..\kernel\os\system.def
INCLUDE ..\..\kernel\os\state.def
INCLUDE ..\..\kernel\os\protseg.def

FAULT_SIGN  EQU 0AC92BE63h

fault_sector_seg STRUC

fss_sign        DD ?
fss_state       action_state_struc <>
fss_tss         DD ?

fault_sector_seg ENDS


data    SEGMENT byte public 'DATA'

wd_tics         DD ?

fault_disc          DB ?
fault_start_sector      DD ?
fault_sectors       DD ?

data    ENDS

    .386p

code    SEGMENT byte public use16 'CODE'

    assume cs:code
    
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           WdTimeout
;
;           DESCRIPTION:    Watchdog timeout - do reset
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

WdTimeout:
    SoftReset
    jmp WdTimeout

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           StartWatchdog
;
;           DESCRIPTION:    Start watchdog
;
;       PARAMETERS:     EAX      Timeout in milliseconds 
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

start_watchdog_name DB 'Start Watchdog', 0

start_watchdog   Proc far
    push es
    pushad
;   
    mov bx,SEG data
    mov es,bx
    mov edx,1193
    mul edx
    mov es:wd_tics,eax
;       
    GetSystemTime
    add eax,es:wd_tics
    adc edx,0
;
    mov bx,cs
    mov es,bx
    mov di,OFFSET WdTimeout
    mov bx,SEG data
    StartTimer
;
    popad
    pop es      
    retf32
start_watchdog   Endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       
;
;   NAME:           ReadFlatAppDword
;
;   DESCRIPTION:    Read flat app dword
;
;   PARAMETERS:     DS  Thread
;                   ESI Offset
;
;   RETURNS:        NC
;                       EAX Data
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ReadFlatAppDword    Proc near
    push ebx
    push ecx
    push edx
    push esi
;
    add esi,3
    xor ecx,ecx
    mov edx,flat_data_sel
    mov bx,ds
    ReadThreadSelector
    jc rfadDone
;
    dec esi
    mov cl,al
    ReadThreadSelector
    jc rfadDone
;
    shl ecx,8
    mov cl,al
;
    dec esi
    mov cl,al
    ReadThreadSelector
    jc rfadDone
;
    shl ecx,8
    mov cl,al
;
    dec esi
    mov cl,al
    ReadThreadSelector
    jc rfadDone
;
    shl ecx,8
    mov cl,al
    mov eax,ecx
    clc

rfadDone:
    pop esi
    pop edx
    pop ecx
    pop ebx
    ret
ReadFlatAppDword    Endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;       
;
;   NAME:           ProbeFlatAppCode
;
;   DESCRIPTION:    Proble flat app code
;
;   PARAMETERS:     DS  Thread
;                   ESI Offset
;
;   RETURNS:        NC   OK
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

ProbeFlatAppCode    Proc near
    push eax
    push ebx
    push edx
;
    mov edx,flat_data_sel
    mov bx,ds
    ReadThreadSelector
    jc pfacDone
;    
    GetThreadSelectorPage
    jc pfacDone
;
    test al,2
    jz pfacDone
;
    stc

pfacDone:
    pop edx
    pop ebx
    pop eax
    ret
ProbeFlatAppCode    Endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           KickWatchdog
;
;           DESCRIPTION:    Kick watchdog
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

kick_watchdog_name DB 'Kick Watchdog', 0

kick_watchdog   Proc far
    push ds
    push es
    push fs
    pushad
;    
    GetDebugThreadSel
    or ax,ax
    jz kw_kick
;
    mov bp,ax
    mov bx,SEG data
    mov fs,bx
    mov ecx,fs:fault_sectors
    or ecx,ecx
    jz kw_done
;    
    mov fs:fault_sectors,0
    mov edx,fs:fault_start_sector
;
    mov bx,fault_sector_sel
    mov es,bx
    GetDebugThreadSel

kw_save_loop:
    mov ds,ax
    mov bx,ds:p_id
    mov di,OFFSET fss_tss
    GetThreadTss
;
    mov es:fss_sign,FAULT_SIGN
    mov ax,ds:p_id
    mov es:fss_state.ast_id,ax
;
    push cx
    mov si,OFFSET thread_name
    mov cx,32
    mov di,OFFSET fss_state.ast_name
    rep movsb
;
    mov cx,32
    mov di,OFFSET fss_state.ast_list
    mov al,' '
    rep stosb   
    pop cx
;    
    push cx
    mov si,OFFSET p_action_text
    mov cx,32
    mov di,OFFSET ast_action
    rep movsb
    pop cx
;       
    mov eax,ds:p_msb_tics
    mov es:fss_state.ast_time,eax
    mov eax,ds:p_lsb_tics
    mov es:fss_state.ast_time+4,eax
;
    mov dword ptr es:fss_state.ast_pos.sep_offs,0
    mov dword ptr es:fss_state.ast_pos.sep_offs+4,0
    mov es:fss_state.ast_pos.sep_sel,0
    mov es:fss_state.ast_count,0
;
    push fs
    push ecx
    push edx
;        
    test word ptr ds:p_rflags+2,2
    jnz kw_user_done
;
    mov ax,ds:p_cs
    cmp ax,flat_code_sel
    jne kw_not_app
;   
    mov edx,OFFSET fss_state.ast_user
    mov eax,dword ptr ds:p_rbp    
    jmp kw_user_loop

kw_not_app:    
    test ax,7
    jnz kw_user_done
;
    mov ax,ds:p_ss
    mov fs,ax
    mov ecx,dword ptr ds:p_rsp
    cmp ecx,stack0_size
    jae kw_user_done
;
    mov ecx,stack0_size
    mov eax,fs:[ecx-4]
    cmp eax,flat_data_sel    
    jne kw_user_done
;    
    mov eax,fs:[ecx-12]
    cmp eax,flat_code_sel
    jne kw_user_done
;
    mov edx,OFFSET fss_state.ast_user
    mov eax,fs:[ecx-12]
    mov es:[edx].sep_sel,ax
    mov eax,fs:[ecx-16]
    mov dword ptr es:[edx].sep_offs,eax
    mov dword ptr es:[edx].sep_offs+4,0
    add edx,SIZE state_ep
    inc es:fss_state.ast_count
;
    mov esi,fs:[ecx-8]
    call ReadFlatAppDword
    jc kw_user_done

kw_user_loop:
    mov esi,eax
    push esi
    add esi,24
    call ReadFlatAppDword
    pop esi
    jc kw_user_done
;
    push esi
    mov esi,eax
    call ProbeFlatAppCode
    pop esi
    jnc kw_user_save
;    
    push esi
    add esi,20
    call ReadFlatAppDword
    pop esi
    jc kw_user_done
;
    push esi
    mov esi,eax
    call ProbeFlatAppCode
    pop esi
    jnc kw_user_save
;
    xor eax,eax
    
kw_user_save:    
    mov es:[edx].sep_sel,flat_code_sel
    mov dword ptr es:[edx].sep_offs,eax
    mov dword ptr es:[edx].sep_offs+4,0
    add edx,SIZE state_ep
    mov ax,es:fss_state.ast_count
    inc ax
    mov es:fss_state.ast_count,ax
    cmp ax,64
    jae kw_user_done
;
    call ReadFlatAppDword
    or eax,eax
    jnz kw_user_loop
        
kw_user_done:    
    mov ax,es:fss_state.ast_count
    cmp ax,2
    jb kw_user_ok
;
    sub edx,SIZE state_ep
    mov eax,dword ptr es:[edx].sep_offs
    or eax,dword ptr es:[edx].sep_offs+4
    jnz kw_user_ok
;
    dec es:fss_state.ast_count        

kw_user_ok:    
    pop edx
    pop ecx
    pop fs
;
    push cx
    mov al,fs:fault_disc
    mov cx,512
    xor di,di       
    WriteShortDisc
    inc edx
;    
    mov al,fs:fault_disc
    mov cx,512
    mov di,200h
    WriteShortDisc
    inc edx
;    
    pop cx
;
    DebugNext    
    GetDebugThreadSel
    cmp ax,bp
    je kw_done
;
    sub ecx,2
    jnz kw_save_loop    
;
    jmp kw_done    
    
kw_kick:
    GetSystemTime
    mov bx,SEG data
    mov es,bx
    add eax,es:wd_tics
    adc edx,0
;
    mov bx,cs
    mov es,bx
    mov di,OFFSET WdTimeout
    mov bx,SEG data
    StopTimer
    StartTimer

kw_done:
    popad       
    pop fs
    pop es
    pop ds
    retf32
kick_watchdog   Endp

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           StopWatchdog
;
;           DESCRIPTION:    Stop watchdog
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

stop_watchdog_name DB 'Stop Watchdog', 0

stop_watchdog   Proc far
    push es
    push bx    
;    
    mov bx,SEG data
    mov es,bx
    StopTimer
    mov es:wd_tics,0    
;
    pop bx
    pop es
    retf32
stop_watchdog   Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           GetWatchdogTics
;
;           DESCRIPTION:    Get watchdog tics
;
;       RETURNS:    EAX == 0 not running
;               EAX != 0, EAX tics
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_watchdog_tics_name DB 'Get Watchdog Tics', 0

get_watchdog_tics   Proc far
    push es
    push bx    
;    
    mov bx,SEG data
    mov es,bx
    mov eax,es:wd_tics
;
    pop bx
    pop es
    retf32
get_watchdog_tics   Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           DefineFaultSave
;
;           DESCRIPTION:    Define fault save position on disc
;
;       PARAMETERS:     AL      Disc #
;               EDX     Start sector #
;               ECX     Number of available sectors
;                           
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

define_fault_save_name  DB 'Define Fault Save',0

define_fault_save       PROC far
    push ds
    push bx
;
    mov bx,SEG data
    mov ds,bx
    mov ds:fault_disc,al
    mov ds:fault_start_sector,edx
    mov ds:fault_sectors,ecx
;    
    pop bx
    pop ds
    retf32
define_fault_save   Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           ClearFaultSave
;
;           DESCRIPTION:    Clear fault save data
;                           
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

clear_fault_save_name   DB 'Clear Fault Save',0

clear_fault_save    PROC far
    push ds
    push es
    pushad
;    
    mov ax,SEG data
    mov ds,ax
    mov ax,fault_sector_sel
    mov es,ax
    xor di,di
    mov cx,512
    xor al,al
    rep stosb
;
    mov ecx,ds:fault_sectors
    mov edx,ds:fault_start_sector

cfsLoop:
    or ecx,ecx
    jz cfsDone
;
    push cx
    mov al,ds:fault_disc
    mov cx,512
    xor di,di
    WriteShortDisc
    pop cx
;
    inc edx
    dec ecx
    jmp cfsLoop 

cfsDone:   
    popad
    pop es
    pop ds
    retf32
clear_fault_save   Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           GetFaultThreadState
;
;           DESCRIPTION:    Get fault thread state
;
;       PARAMETERS:     AX      Thread #
;               ES:E(DI)    State buffer
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_fault_thread_state_name     DB 'Get Fault Thread State',0

get_fault_thread_state  PROC near
    push ds
    push es
    push fs
    pushad
;   
    mov bp,es
    mov fs,bp
    mov ebp,edi
;    
    movzx eax,ax
    mov bx,SEG data
    mov ds,bx
    mov bx,fault_sector_sel
    mov es,bx
;
    mov ecx,ds:fault_sectors
    cmp eax,ecx
    jae gfsFail
;
    mov edx,ds:fault_start_sector
    add edx,eax
    add edx,eax
;    
    mov al,ds:fault_disc
    mov cx,512
    xor di,di
    ReadShortDisc
;    
    mov al,ds:fault_disc
    mov cx,512
    mov di,200h
    inc edx
    ReadShortDisc
;    
    mov eax,es:fss_sign
    cmp eax,FAULT_SIGN
    jne gfsFail
;
    mov ax,es
    mov ds,ax
    mov esi,OFFSET fss_state
    mov ax,fs
    mov es,ax
    mov edi,ebp
    mov ecx,SIZE action_state_struc
    rep movs byte ptr es:[edi],ds:[esi]
    clc
    jmp gfsEnd    
    
gfsFail:
    stc

gfsEnd:
    popad
    pop fs
    pop es
    pop ds
    ret
get_fault_thread_state   Endp

get_fault_thread_state16    Proc far
    push edi
    movzx edi,di
    call get_fault_thread_state
    pop edi
    retf32
get_fault_thread_state16    Endp

get_fault_thread_state32    Proc far
    call get_fault_thread_state
    Retf32
get_fault_thread_state32    Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           GetFaultThreadTss
;
;           DESCRIPTION:    Get fault thread tss
;
;       PARAMETERS:     AX      Thread #
;               ES:E(DI)    Tss buffer
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

get_fault_thread_tss_name       DB 'Get Fault Thread Tss',0

get_fault_thread_tss    PROC near
    push ds
    push es
    push fs
    pushad
;   
    mov bp,es
    mov fs,bp
    mov ebp,edi
;    
    movzx eax,ax
    mov bx,SEG data
    mov ds,bx
    mov bx,fault_sector_sel
    mov es,bx
;
    mov ecx,ds:fault_sectors
    cmp eax,ecx
    jae gftFail
;
    mov edx,ds:fault_start_sector
    add edx,eax
    add edx,eax
;    
    mov al,ds:fault_disc
    mov cx,512
    xor di,di
    ReadShortDisc
;    
    inc edx
    mov al,ds:fault_disc
    mov cx,512
    mov di,200h
    ReadShortDisc
;    
    mov eax,es:fss_sign
    cmp eax,FAULT_SIGN
    jne gftFail
;
    mov ax,es
    mov ds,ax
    mov esi,OFFSET fss_tss
    mov ax,fs
    mov es,ax
    mov edi,ebp
    mov ecx,SIZE user_tss_struc
    rep movs byte ptr es:[edi],ds:[esi]
    clc
    jmp gftEnd    
    
gftFail:
    stc

gftEnd:
    popad
    pop fs
    pop es
    pop ds
    ret
get_fault_thread_tss   Endp

get_fault_thread_tss16  Proc far
    push edi
    movzx edi,di
    call get_fault_thread_tss
    pop edi
    retf32
get_fault_thread_tss16  Endp

get_fault_thread_tss32  Proc far
    call get_fault_thread_tss
    Retf32
get_fault_thread_tss32  Endp


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
;
;           NAME:           Init
;
;           DESCRIPTION:    Initialize module
;
;           PARAMETERS:         
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

init    Proc far
    mov bx,SEG data
    mov es,bx
    mov es:wd_tics,0
    mov es:fault_sectors,0
;
    mov eax,1024
    mov bx,fault_sector_sel
    AllocateFixedSystemMem
;
    mov ax,cs
    mov ds,ax
    mov es,ax
;
    mov esi,OFFSET start_watchdog
    mov edi,OFFSET start_watchdog_name
    xor dx,dx
    mov ax,start_watchdog_nr
    RegisterBimodalUserGate
;
    mov esi,OFFSET kick_watchdog
    mov edi,OFFSET kick_watchdog_name
    xor dx,dx
    mov ax,kick_watchdog_nr
    RegisterBimodalUserGate
;
    mov esi,OFFSET stop_watchdog
    mov edi,OFFSET stop_watchdog_name
    xor dx,dx
    mov ax,stop_watchdog_nr
    RegisterBimodalUserGate
;
    mov esi,OFFSET get_watchdog_tics
    mov edi,OFFSET get_watchdog_tics_name
    xor dx,dx
    mov ax,get_watchdog_tics_nr
    RegisterBimodalUserGate
;
    mov esi,OFFSET define_fault_save
    mov edi,OFFSET define_fault_save_name
    xor dx,dx
    mov ax,define_fault_save_nr
    RegisterBimodalUserGate
;
    mov esi,OFFSET clear_fault_save
    mov edi,OFFSET clear_fault_save_name
    xor dx,dx
    mov ax,clear_fault_save_nr
    RegisterBimodalUserGate
;
    mov ebx,OFFSET get_fault_thread_state16
    mov esi,OFFSET get_fault_thread_state32
    mov edi,OFFSET get_fault_thread_state_name
    mov dx,virt_es_in
    mov ax,get_fault_thread_state_nr
    RegisterUserGate
;
    mov ebx,OFFSET get_fault_thread_tss16
    mov esi,OFFSET get_fault_thread_tss32
    mov edi,OFFSET get_fault_thread_tss_name
    mov dx,virt_es_in
    mov ax,get_fault_thread_tss_nr
    RegisterUserGate
    ret
init    Endp

code    ENDS

    END init