Cleaned up CreateSystemTimer interface for use with 32-bit callbacks.
[wine] / misc / system.c
1 /*
2  * SYSTEM DLL routines
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include <stdlib.h>
8 #include <signal.h>
9 #include <time.h>
10 #include <sys/time.h>
11 #include <sys/timeb.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14
15 #include "windows.h"
16 #include "selectors.h"
17 #include "sig_context.h"
18 #include "miscemu.h"
19 #include "debug.h"
20
21 typedef struct
22 {
23     SYSTEMTIMERPROC callback;  /* NULL if not in use */
24     INT32     rate;
25     INT32     ticks;
26 } SYSTEM_TIMER;
27
28 #define NB_SYS_TIMERS   8
29 #define SYS_TIMER_RATE  54925
30
31 static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
32 static int SYS_NbTimers = 0;
33 static BOOL32 SYS_TimersDisabled = FALSE;
34
35
36 /***********************************************************************
37  *           SYSTEM_TimerTick
38  */
39 static HANDLER_DEF(SYSTEM_TimerTick)
40 {
41     int i;
42     HANDLER_INIT();
43
44     for (i = 0; i < NB_SYS_TIMERS; i++)
45     {
46         if (!SYS_Timers[i].callback) continue;
47         if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
48         {
49             SYS_Timers[i].ticks += SYS_Timers[i].rate;
50             SYS_Timers[i].callback( i+1 );
51         }
52     }
53 }
54
55 /**********************************************************************
56  *           SYSTEM_StartTicks
57  *
58  * Start the system tick timer.
59  */
60 static void SYSTEM_StartTicks(void)
61 {
62     static BOOL32 handler_installed = FALSE;
63
64     if (!handler_installed)
65     {
66         handler_installed = TRUE;
67         SIGNAL_SetHandler( SIGALRM, SYSTEM_TimerTick, 1 );
68     }
69 #ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
70     {
71         struct itimerval vt_timer;
72
73         vt_timer.it_interval.tv_sec = 0;
74         vt_timer.it_interval.tv_usec = 54929;
75         vt_timer.it_value = vt_timer.it_interval;
76         setitimer( ITIMER_REAL, &vt_timer, NULL );
77     }
78 #endif
79 }
80
81
82 /**********************************************************************
83  *           SYSTEM_StopTicks
84  *
85  * Stop the system tick timer.
86  */
87 static void SYSTEM_StopTicks(void)
88 {
89 #ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
90     struct itimerval vt_timer;
91
92     vt_timer.it_interval.tv_sec = 0;
93     vt_timer.it_interval.tv_usec = 0;
94     vt_timer.it_value = vt_timer.it_interval;
95     setitimer( ITIMER_REAL, &vt_timer, NULL );
96 #endif
97 }
98
99
100 /***********************************************************************
101  *           InquireSystem   (SYSTEM.1)
102  *
103  * Note: the function always takes 2 WORD arguments, contrary to what
104  *       "Undocumented Windows" says.
105   */
106 DWORD WINAPI InquireSystem( WORD code, WORD arg )
107 {
108     WORD drivetype;
109
110     switch(code)
111     {
112     case 0:  /* Get timer resolution */
113         return SYS_TIMER_RATE;
114
115     case 1:  /* Get drive type */
116         drivetype = GetDriveType16( arg );
117         return MAKELONG( drivetype, drivetype );
118
119     case 2:  /* Enable one-drive logic */
120         FIXME(system, "Case %d: set single-drive %d not supported\n", code, arg );
121         return 0;
122     }
123     WARN(system, "Unknown code %d\n", code );
124     return 0;
125 }
126
127
128 /***********************************************************************
129  *           CreateSystemTimer   (SYSTEM.2)
130  */
131 WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
132 {
133     int i;
134     for (i = 0; i < NB_SYS_TIMERS; i++)
135         if (!SYS_Timers[i].callback)  /* Found one */
136         {
137             SYS_Timers[i].rate = (UINT32)rate * 1000;
138             if (SYS_Timers[i].rate < SYS_TIMER_RATE)
139                 SYS_Timers[i].rate = SYS_TIMER_RATE;
140             SYS_Timers[i].ticks = SYS_Timers[i].rate;
141             SYS_Timers[i].callback = callback;
142             if ((++SYS_NbTimers == 1) && !SYS_TimersDisabled)
143                 SYSTEM_StartTicks();
144             return i + 1;  /* 0 means error */
145         }
146     return 0;
147 }
148
149
150 /***********************************************************************
151  *           KillSystemTimer   (SYSTEM.3)
152  *
153  * Note: do not confuse this function with USER.182
154  */
155 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
156 {
157     if (!timer || (timer > NB_SYS_TIMERS)) return timer;  /* Error */
158     SYS_Timers[timer-1].callback = NULL;
159     if ((!--SYS_NbTimers) && !SYS_TimersDisabled) SYSTEM_StopTicks();
160     return 0;
161 }
162
163
164 /***********************************************************************
165  *           EnableSystemTimers   (SYSTEM.4)
166  */
167 void WINAPI EnableSystemTimers(void)
168 {
169     SYS_TimersDisabled = FALSE;
170     if (SYS_NbTimers) SYSTEM_StartTicks();
171 }
172
173
174 /***********************************************************************
175  *           DisableSystemTimers   (SYSTEM.5)
176  */
177 void WINAPI DisableSystemTimers(void)
178 {
179     SYS_TimersDisabled = TRUE;
180     if (SYS_NbTimers) SYSTEM_StopTicks();
181 }