# timer.S86 - time handling routines for netboot boot images # # Copyright (C) 2003 Gero Kuhlmann # # 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 # any later version. # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # # $Id: timer.S86,v 1.1 2003/03/09 00:43:08 gkminix Exp $ # #==================================================================== # #include "common.i86" .file "timer.S86" .line 29 # #==================================================================== # # Some definitions which are local to this module # # Definitions to access the PC hardware timer TIMER_0 .equ H'40 # Timer 0 port number TIMER_MODE .equ H'43 # Timer mode port number TIMER_INT .equ 10 # Number of microseconds per tick TIMER_TICKS .equ 4 # Number of timer counts for a tick TICKS_PER_SEC .equ 18 # Number of system ticks per second .line 49 # #==================================================================== # # Define the text segment and all public entry points # \(.text) .global wait_usec .global set_ticks .global set_timeout .global chk_timeout # #==================================================================== # # Wait a number of microseconds (granularity of 10) # Input: AX - Number of microseconds to wait # Output: none # Registers changed: AX # wait_usec: pushf push bx push cx push dx add ax,TIMER_INT / 2 # round up to next multiple of 10 xor dx,dx mov bx,TIMER_INT # compute number of 10 microsecond div bx # intervalls or ax,ax jz waitu9 # check if we have to wait at all mov bx,ax waitu1: cli mov dx,TIMER_MODE xor al,al out dx,al # write timer 0 count mode jcxz waitu2 # wait a little bit to avoid a bug waitu2: jcxz waitu3 # in certain Neptune chipsets waitu3: mov dx,TIMER_0 in al,dx # read timer LSB mov cl,al in al,dx # read timer MSB mov ch,al sti waitu4: cli mov dx,TIMER_MODE xor al,al out dx,al # write timer 0 count mode jcxz waitu5 waitu5: jcxz waitu6 waitu6: mov dx,TIMER_0 in al,dx # read timer LSB mov ah,al in al,dx # read timer MSB xchg ah,al sti neg ax add ax,cx # check if timeout value reached cmp ax,TIMER_TICKS jb waitu4 # no, read timer again dec bx jnz waitu1 # check if number of loops reached waitu9: pop dx pop cx pop bx popf ret # #==================================================================== # # Set a timeout in timer ticks # Input: DX:AX - Number of ticks until timeout # Output: none # Registers changed: none # set_ticks: push bx push cx push dx push ax xor ah,ah # get current tick count from BIOS int 0x1A mov bx,dx pop ax add bx,ax # compute end count pop dx adc cx,dx mov word ptr [endval + 0],bx mov word ptr [endval + 2],cx pop cx pop bx ret # #==================================================================== # # Set a timeout in seconds # Input: AX - Number of seconds until timeout # Output: none # Registers changed: AX # set_timeout: push dx mov dx,ax mov ax,TICKS_PER_SEC mul dx # compute number of ticks to timeout call set_ticks # set end tick count pop dx ret # #==================================================================== # # Check if a timeout exceeded # Input: none # Output: Carry flag set if timeout exceeded # Registers changed: AX # chk_timeout: push ecx push dx xor ah,ah # get current tick count from BIOS int 0x1A shl ecx,16 mov cx,dx # check if timeout exceeded cmp ecx,[endval] cmc pop dx pop ecx ret # #==================================================================== # # Variable definitions # \(.bss) .lcomm endval,4 # timeout end tick value # #==================================================================== # .end