;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 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 ; ; TIMER.ASM ; PIT interface & emulation ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INCLUDE protseg.def INCLUDE ..\driver.def INCLUDE ..\user.def INCLUDE ..\os.def INCLUDE system.inc INCLUDE ..\user.inc INCLUDE ..\os.inc timer_lsb EQU 0 timer_msb EQU 1 timer_struc STRUC timer_state DB ? timer_transfer DB ? timer_period DW ? timer_count DW ? timer_resvd DW ? timer_time DD ?,? timer_struc ENDS proc_timer_seg STRUC timer0 timer_struc <> timer_int_offs DW ? timer_int_seg DW ? timer_tics_offs DW ? timer_tics_seg DW ? timer_thread DW ? timer_int16_offs DW ? timer_int16_sel DW ? timer_tics16_offs DW ? timer_tics16_sel DW ? timer_thread16 DW ? proc_timer_seg ENDS .386p code SEGMENT byte public use16 'CODE' assume cs:code reload_timer PROC near push edx mov ax,[bx].timer_period mov [bx].timer_count,ax GetSystemTime mov [bx+4].timer_time,edx mov [bx].timer_time,eax pop edx ret reload_timer ENDP set_period PROC near cmp [bx].timer_transfer,timer_msb je out_msb mov byte ptr [bx].timer_period,al test [bx].timer_state,20h jnz out_msb_next call reload_timer ret out_msb_next: mov [bx].timer_transfer,timer_msb ret out_msb: mov byte ptr [bx].timer_period+1,al test [bx].timer_state,10h jnz out_lsb_next call reload_timer ret out_lsb_next: mov [bx].timer_transfer,timer_lsb call reload_timer ret set_period ENDP get_period PROC near cmp [bx].timer_transfer,timer_msb je in_msb mov al,byte ptr [bx].timer_period test [bx].timer_state,20h jnz in_msb_next ret in_msb_next: mov [bx].timer_transfer,timer_msb ret in_msb: mov al,byte ptr [bx].timer_period+1 test [bx].timer_state,10h jnz in_lsb_next ret in_lsb_next: mov [bx].timer_transfer,timer_lsb ret get_period ENDP in_timer0 PROC far mov bx,pcbios_proc_sel mov ds,bx mov bx,OFFSET timer0 call get_period retf32 in_timer0 ENDP out_timer0 PROC far mov bx,pcbios_proc_sel mov ds,bx mov bx,OFFSET timer0 call set_period retf32 out_timer0_not_msb: retf32 out_timer0 ENDP in_timer1 PROC far in al,41h retf32 in_timer1 ENDP out_timer1 PROC far retf32 out_timer1 ENDP in_timer2 PROC far xor al,al retf32 in_timer2 ENDP out_timer2 PROC far retf32 out_timer2 ENDP in_speaker_control PROC far in al,61h retf32 in_speaker_control Endp out_speaker_control Proc far retf32 out_speaker_control Endp in_control PROC far retf32 in_control ENDP out_control PROC far mov bx,pcbios_proc_sel mov ds,bx mov bl,al and bl,0C0h shr bl,6 cmp bl,3 je out_control_done xor bh,bh shl bx,4 mov [bx].timer_state,al test al,10h jz control_msb mov [bx].timer_transfer,timer_lsb retf32 control_msb: mov [bx].timer_transfer,timer_lsb retf32 out_control_done: retf32 out_control ENDP get_tics0 PROC far push bx push eax push edx GetSystemTime shr eax,16 mov bl,al pop edx pop eax mov al,bl pop bx ret get_tics0 ENDP get_tics1 PROC far push bx push eax push edx GetSystemTime shr eax,24 mov bl,al pop edx pop eax mov al,bl pop bx ret get_tics1 ENDP get_tics2 PROC far push bx push eax push edx GetSystemTime mov bl,dl pop edx pop eax mov al,bl pop bx ret get_tics2 ENDP get_tics3 PROC far push bx push eax push edx GetSystemTime mov bl,dh pop edx pop eax mov al,bl pop bx ret get_tics3 ENDP timer_name DB 'Timer Emulator',0 timer_pr: mov eax,stack0_size mov esp,eax ; mov ax,pcbios_proc_sel mov ds,ax GetThread mov ds:timer_thread,ax GetSystemTime mov ds:timer0.timer_time,eax mov ds:timer0.timer_time+4,edx mov eax,110h AllocateVMLinear add edx,10h shr edx,4 ; gs push 0 push 0F000h ; fs push 0 push 0F000h ; ds push 0 push 0F000h ; es push 0 push 0F000h ; ss push edx ; esp push 0 push 0FAh ; eflags push 2 push 200h ; cs push 0 push 0 ; eip push 0 push 0 ; sub esp,4 push ebp mov ebp,esp push eax push ebx push word ptr 0 push ds sub esp,10 timer_tics_entry: SimSti mov ax,pcbios_proc_sel mov ds,ax GetThread cmp ax,ds:timer_thread je timer_wait_loop TerminateThread timer_wait_loop: mov eax,ds:timer0.timer_time mov edx,ds:timer0.timer_time+4 movzx ecx,ds:timer0.timer_period mov ds:timer0.timer_count,cx add ecx,eax mov ds:timer0.timer_time,ecx mov ecx,0 adc ecx,edx mov ds:timer0.timer_time+4,ecx WaitUntil ; mov ax,ds:timer_int_seg cmp ax,0E000h jz timer_tics mov [ebp].trap_cs,ax mov ax,ds:timer_int_offs mov [ebp].trap_eip,ax ; mov ax,flat_sel mov ds,ax movzx edx,word ptr [ebp].trap_ss shl edx,4 mov word ptr [edx+0FAh],8*4 mov word ptr [edx+0FCh],0E000h mov word ptr [edx+0FEh],200h mov word ptr [ebp].trap_esp,0FAh add sp,10 pop ds pop ax pop ebx pop eax pop ebp add sp,4 iretd timer_int_entry: SimSti mov ax,pcbios_proc_sel mov ds,ax GetThread cmp ax,ds:timer_thread je timer_tics TerminateThread timer_tics: mov ax,ds:timer_tics_seg cmp ax,0E000h jz timer_wait_loop ; mov [ebp].trap_cs,ax mov ax,ds:timer_tics_offs mov [ebp].trap_eip,ax ; mov ax,flat_sel mov ds,ax movzx edx,word ptr [ebp].trap_ss shl edx,4 mov word ptr [edx+0FAh],1Ch*4 mov word ptr [edx+0FCh],0E000h mov word ptr [edx+0FEh],200h mov word ptr [ebp].trap_esp,0FAh add esp,10 pop ds pop ax pop ebx pop eax pop ebp add esp,4 iretd ; jmp timer_tics_entry check_timer_state PROC near cmp ds:timer_int_seg,0E000h jnz check_timer_on cmp ds:timer_tics_seg,0E000h jnz check_timer_on check_timer_off: mov ds:timer_thread,0 ret check_timer_on: cmp ds:timer_thread,0 jz check_timer_start ret check_timer_start: dec ds:timer_thread push ds push es pusha mov ax,cs mov ds,ax mov es,ax mov si,OFFSET timer_pr mov di,OFFSET timer_name mov cx,stack0_size mov ax,3 CreateThread popa pop es pop ds ret check_timer_state ENDP get_vm_timer PROC far mov bx,pcbios_proc_sel mov ds,bx mov bx,ds:timer_int_offs mov dx,ds:timer_int_seg retf32 get_vm_timer ENDP set_vm_timer PROC far push ax mov ax,pcbios_proc_sel mov ds,ax pop ax mov ds:timer_int_offs,bx mov ds:timer_int_seg,dx call check_timer_state retf32 set_vm_timer ENDP get_vm_timer_tick PROC far mov bx,pcbios_proc_sel mov ds,bx mov bx,ds:timer_tics_offs mov dx,ds:timer_tics_seg retf32 get_vm_timer_tick ENDP set_vm_timer_tick PROC far push ax mov ax,pcbios_proc_sel mov ds,ax pop ax mov ds:timer_tics_offs,bx mov ds:timer_tics_seg,dx call check_timer_state retf32 set_vm_timer_tick ENDP timer16_pr: mov ax,pcbios_proc_sel mov ds,ax GetThread mov ds:timer_thread16,ax GetSystemTime mov ds:timer0.timer_time,eax mov ds:timer0.timer_time+4,edx mov eax,100h AllocateLocalMem ; ss push 0 push es ; esp push 0 push 0FAh ; eflags push 0 push 200h ; cs push 0 push 0 ; eip push 0 push 0 ; sub sp,4 push ebp mov ebp,esp push eax push ebx push word ptr 0 push ds sub sp,10 timer_tics16_entry: mov ax,pcbios_proc_sel mov ds,ax GetThread cmp ax,ds:timer_thread16 je timer_wait16_loop TerminateThread timer_wait16_loop: mov eax,ds:timer0.timer_time mov edx,ds:timer0.timer_time+4 movzx ecx,ds:timer0.timer_period mov ds:timer0.timer_count,cx add ecx,eax mov ds:timer0.timer_time,ecx mov ecx,0 adc ecx,edx mov ds:timer0.timer_time+4,ecx WaitUntil ; mov ax,ds:timer_int16_sel cmp ax,callb_int16_sel jz timer_tics16 mov [ebp].trap_cs,ax mov ax,ds:timer_int16_offs mov [ebp].trap_eip,ax ; mov ds,[ebp].trap_ss xor bx,bx mov word ptr [bx+0FAh],8*4 mov word ptr [bx+0FCh],callb_int16_sel mov word ptr [bx+0FEh],200h mov word ptr [ebp].trap_esp,0FAh add sp,10 pop ds pop ax pop ebx pop eax pop bp add sp,4 iretd ; timer_int16_entry: mov ax,pcbios_proc_sel mov ds,ax GetThread cmp ax,ds:timer_thread16 je timer_tics16 TerminateThread timer_tics16: mov ax,ds:timer_tics16_sel cmp ax,callb_int16_sel jz timer_wait16_loop mov [ebp].trap_cs,ax mov ax,ds:timer_tics16_offs mov [ebp].trap_eip,ax ; mov ds,[ebp].trap_ss xor bx,bx mov word ptr [bx+0FAh],1Ch*4 mov word ptr [bx+0FCh],callb_int16_sel mov word ptr [bx+0FEh],200h mov word ptr [ebp].trap_esp,0FAh add sp,10 pop ds pop ax pop ebx pop eax pop bp add sp,4 iretd jmp timer_tics16_entry check_timer16_state PROC near cmp ds:timer_int16_sel,callb_int16_sel jnz check_timer16_on cmp ds:timer_tics16_sel,callb_int16_sel jnz check_timer16_on check_timer16_off: mov ds:timer_thread16,0 ret check_timer16_on: cmp ds:timer_thread16,0 jz check_timer16_start ret check_timer16_start: dec ds:timer_thread16 push ds push es pusha mov ax,cs mov ds,ax mov es,ax mov si,OFFSET timer16_pr mov di,OFFSET timer_name mov cx,stack0_size mov ax,3 CreateThread popa pop es pop ds ret check_timer16_state ENDP get_pm_timer PROC far mov bx,pcbios_proc_sel mov ds,bx mov bx,ds:timer_int16_offs mov dx,ds:timer_int16_sel retf32 get_pm_timer ENDP set_pm_timer PROC far push ax mov ax,pcbios_proc_sel mov ds,ax pop ax mov ds:timer_int16_offs,bx mov ds:timer_int16_sel,dx call check_timer16_state retf32 set_pm_timer ENDP get_pm_timer_tick PROC far mov bx,pcbios_proc_sel mov ds,bx mov di,ds:timer_tics16_offs mov es,ds:timer_tics16_sel retf32 get_pm_timer_tick ENDP set_pm_timer_tick PROC far push ax mov ax,pcbios_proc_sel mov ds,ax pop ax mov ds:timer_tics16_offs,di mov ds:timer_tics16_sel,es call check_timer16_state retf32 set_pm_timer_tick ENDP init_timer_process PROC far mov ax,pcbios_proc_sel mov ds,ax GetSystemTime mov ds:timer0.timer_state,36h mov ds:timer0.timer_transfer,timer_lsb mov ds:timer0.timer_period,0FFFFh mov ds:timer0.timer_count,0FFFFh mov ds:timer0.timer_time,eax mov ds:timer0.timer_time+4,edx mov ds:timer_int_seg,0E000h mov ds:timer_int_offs,8*4 mov ds:timer_tics_seg,0E000h mov ds:timer_tics_offs,1Ch*4 mov ds:timer_thread,0 mov ds:timer_int16_sel,callb_int16_sel mov ds:timer_int16_offs,8*4 mov ds:timer_tics16_sel,callb_int16_sel mov ds:timer_tics16_offs,1Ch*4 mov ds:timer_thread16,0 retf32 init_timer_process ENDP public init_timer init_timer PROC near mov eax,SIZE proc_timer_seg mov bx,pcbios_proc_sel AllocateFixedProcessMem ; mov ax,cs mov ds,ax mov es,ax mov edi,OFFSET init_timer_process HookCreateProcess ; mov edi,OFFSET in_timer0 mov dx,40h HookIn ; mov edi,OFFSET out_timer0 mov dx,40h HookOut ; mov edi,OFFSET in_timer1 mov dx,41h HookIn ; mov edi,OFFSET out_timer1 mov dx,41h HookOut ; mov edi,OFFSET in_timer2 mov dx,42h HookIn ; mov edi,OFFSET out_timer2 mov dx,42h HookOut ; mov edi,OFFSET in_control mov dx,43h HookIn ; mov edi,OFFSET out_control mov dx,43h HookOut ; mov edi,OFFSET in_speaker_control mov dx,61h HookIn ; mov edi,OFFSET out_speaker_control mov dx,61h HookOut ; mov edi,OFFSET get_vm_timer mov al,8 HookGetVMInt ; mov edi,OFFSET set_vm_timer mov al,8 HookSetVMInt ; mov edi,OFFSET get_vm_timer_tick mov al,1Ch HookGetVMInt ; mov edi,OFFSET set_vm_timer_tick mov al,1Ch HookSetVMInt ; mov edi,OFFSET get_pm_timer mov al,8 HookGetProt16Int ; mov edi,OFFSET set_pm_timer mov al,8 HookSetProt16Int ; mov edi,OFFSET get_pm_timer_tick mov al,1Ch HookGetProt16Int ; mov edi,OFFSET set_pm_timer_tick mov al,1Ch HookSetProt16Int ; mov di,OFFSET get_tics0 mov bx,6Ch HookGetBiosData ; mov di,OFFSET get_tics1 mov bx,6Dh HookGetBiosData ; mov di,OFFSET get_tics2 mov bx,6Eh HookGetBiosData ; mov di,OFFSET get_tics3 mov bx,6Fh HookGetBiosData ; mov ax,cs mov ds,ax ; mov edi,OFFSET timer_int_entry mov al,8 HookVMInt ; mov edi,OFFSET timer_tics_entry mov al,1Ch HookVMInt ; mov edi,OFFSET timer_int16_entry mov al,8 HookProt16Int ; mov edi,OFFSET timer_tics16_entry mov al,1Ch HookProt16Int ret init_timer ENDP code ENDS END