Added special case for "display" in DRIVER_GetDriverName so that
[wine] / dlls / winedos / timer.c
1 /*
2  * 8253/8254 Programmable Interval Timer (PIT) emulation
3  *
4  * Copyright 2003 Jukka Heinonen
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include "dosexe.h"
24 #include "wine/debug.h"
25 #include "wingdi.h"
26 #include "winuser.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(int);
29
30 /*
31  * FIXME: Move timer ioport handling here and remove 
32  *        Dosvm.GetTimer/Dosvm.SetTimer.
33  * FIXME: Use QueryPerformanceCounter for
34  *        more precise GetTimer implementation.
35  * FIXME: Use QueryPerformanceCounter (or GetTimer implementation)
36  *        in timer tick routine to compensate for lost ticks. 
37  *        This should also make it possible to
38  *        emulate really fast timers.
39  * FIXME: Support special timer modes in addition to periodic mode.
40  * FIXME: Make sure that there are only limited number
41  *        of pending timer IRQ events queued. This makes sure that
42  *        timer handling does not eat all available memory even
43  *        if IRQ handling stops for some reason (suspended process?). 
44  *        This is easy to do by using DOSRELAY parameter.
45  * FIXME: Use timeSetEvent, NtSetEvent or timer thread for more precise
46  *        timing.
47  * FIXME: Move Win16 timer emulation code here.
48  */
49
50 /* The PC clocks ticks at 1193180 Hz. */
51 #define TIMER_FREQ 1193180
52
53 /* Unique system timer identifier. */
54 static UINT_PTR TIMER_id = 0;
55
56 /* Time when timer IRQ was last queued. */
57 static DWORD TIMER_stamp = 0;
58
59 /* Timer ticks between timer IRQs. */
60 static UINT TIMER_ticks = 0;
61
62
63 /***********************************************************************
64  *              TIMER_TimerProc
65  */
66 static void CALLBACK TIMER_TimerProc( HWND     hwnd,
67                                       UINT     uMsg,
68                                       UINT_PTR idEvent,
69                                       DWORD    dwTime )
70 {
71     TIMER_stamp = dwTime;
72     DOSVM_QueueEvent( 0, DOS_PRIORITY_REALTIME, NULL, NULL );
73 }
74
75
76 /***********************************************************************
77  *              TIMER_DoSetTimer
78  */
79 static void WINAPI TIMER_DoSetTimer( ULONG_PTR arg )
80 {
81     INT millis = MulDiv( arg, 1000, TIMER_FREQ );
82
83     /* sanity check - too fast timer */
84     if (millis < 1)
85         millis = 1;
86
87     TRACE_(int)( "setting timer tick delay to %d ms\n", millis );
88
89     if (TIMER_id)
90         KillTimer( NULL, TIMER_id );
91
92     TIMER_id = SetTimer( NULL, 0, millis, TIMER_TimerProc );
93     TIMER_stamp = GetTickCount();
94     TIMER_ticks = arg;
95 }
96
97
98 /***********************************************************************
99  *              GetTimer (WINEDOS.@)
100  */
101 UINT WINAPI DOSVM_GetTimer( void )
102 {
103     if (!DOSVM_IsWin16())
104     {
105         DWORD millis = GetTickCount() - TIMER_stamp;
106         INT   ticks = MulDiv( millis, TIMER_FREQ, 1000 );
107
108         /* sanity check - tick wrap or suspended process or update race */
109         if (ticks < 0 || ticks >= TIMER_ticks)
110             ticks = 0;
111
112         return ticks;
113     }
114
115     return 0;
116 }
117
118
119 /***********************************************************************
120  *              SetTimer (WINEDOS.@)
121  */
122 void WINAPI DOSVM_SetTimer( UINT ticks )
123 {
124     if (!DOSVM_IsWin16())
125         MZ_RunInThread( TIMER_DoSetTimer, ticks );
126 }