Release 980927
[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 "callback.h"
16 #include "windows.h"
17 #include "miscemu.h"
18 #include "selectors.h"
19 #include "sig_context.h"
20 #include "debug.h"
21
22 typedef struct
23 {
24     FARPROC16 callback;  /* NULL if not in use */
25     INT32     rate;
26     INT32     ticks;
27 } SYSTEM_TIMER;
28
29 #define NB_SYS_TIMERS   8
30 #define SYS_TIMER_RATE  54925
31
32 static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
33 static int SYS_NbTimers = 0;
34 static BOOL32 SYS_TimersDisabled = FALSE;
35
36 /***********************************************************************
37  *           SYSTEM_TimerTick
38  * FIXME: It is a very bad idea to call 16bit code in a signal handler:
39  *        If the signal reached us in 16 bit code, we could have a broken
40  *        %FS, which is in turned saved into the single global
41  *        CALLTO16_Current_fs temporary storage, so a single misplaced
42  *        signal crashes the whole WINE process.
43  *        This needs more thought. -MM
44  */
45 static HANDLER_DEF(SYSTEM_TimerTick)
46 {
47     int i;
48     HANDLER_INIT();
49
50     for (i = 0; i < NB_SYS_TIMERS; i++)
51     {
52         if (!SYS_Timers[i].callback) continue;
53         if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
54         {
55             SYS_Timers[i].ticks += SYS_Timers[i].rate;
56
57             if (SYS_Timers[i].callback == (FARPROC16)DOSMEM_Tick) {
58                 DOSMEM_Tick();
59             } else
60                 Callbacks->CallSystemTimerProc( SYS_Timers[i].callback );
61         }
62     }
63 }
64
65 /**********************************************************************
66  *           SYSTEM_StartTicks
67  *
68  * Start the system tick timer.
69  */
70 static void SYSTEM_StartTicks(void)
71 {
72     static BOOL32 handler_installed = FALSE;
73
74     if (!handler_installed)
75     {
76         handler_installed = TRUE;
77         SIGNAL_SetHandler( SIGALRM, SYSTEM_TimerTick, 1 );
78     }
79 #ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
80     {
81         struct itimerval vt_timer;
82
83         vt_timer.it_interval.tv_sec = 0;
84         vt_timer.it_interval.tv_usec = 54929;
85         vt_timer.it_value = vt_timer.it_interval;
86         setitimer( ITIMER_REAL, &vt_timer, NULL );
87     }
88 #endif
89 }
90
91
92 /**********************************************************************
93  *           SYSTEM_StopTicks
94  *
95  * Stop the system tick timer.
96  */
97 static void SYSTEM_StopTicks(void)
98 {
99 #ifndef __EMX__ /* FIXME: Time don't work... Use BIOS directly instead */
100     struct itimerval vt_timer;
101
102     vt_timer.it_interval.tv_sec = 0;
103     vt_timer.it_interval.tv_usec = 0;
104     vt_timer.it_value = vt_timer.it_interval;
105     setitimer( ITIMER_REAL, &vt_timer, NULL );
106 #endif
107 }
108
109
110 /***********************************************************************
111  *           InquireSystem   (SYSTEM.1)
112  *
113  * Note: the function always takes 2 WORD arguments, contrary to what
114  *       "Undocumented Windows" says.
115   */
116 DWORD WINAPI InquireSystem( WORD code, WORD arg )
117 {
118     WORD drivetype;
119
120     switch(code)
121     {
122     case 0:  /* Get timer resolution */
123         return SYS_TIMER_RATE;
124
125     case 1:  /* Get drive type */
126         drivetype = GetDriveType16( arg );
127         return MAKELONG( drivetype, drivetype );
128
129     case 2:  /* Enable one-drive logic */
130         FIXME(system, "Case %d: set single-drive %d not supported\n", code, arg );
131         return 0;
132     }
133     WARN(system, "Unknown code %d\n", code );
134     return 0;
135 }
136
137
138 /***********************************************************************
139  *           CreateSystemTimer   (SYSTEM.2)
140  */
141 WORD WINAPI CreateSystemTimer( WORD rate, FARPROC16 callback )
142 {
143     int i;
144
145     /* FIXME: HACK: do not create system timers due to problems mentioned
146      * above, except DOSMEM_Tick().
147      */
148     if (callback!=(FARPROC16)DOSMEM_Tick) {
149         FIXME(system,"are currently broken, returning 0.\n");
150         return 0;
151     }
152
153     for (i = 0; i < NB_SYS_TIMERS; i++)
154         if (!SYS_Timers[i].callback)  /* Found one */
155         {
156             SYS_Timers[i].rate = (UINT32)rate * 1000;
157             if (SYS_Timers[i].rate < SYS_TIMER_RATE)
158                 SYS_Timers[i].rate = SYS_TIMER_RATE;
159             SYS_Timers[i].ticks = SYS_Timers[i].rate;
160             SYS_Timers[i].callback = callback;
161             if ((++SYS_NbTimers == 1) && !SYS_TimersDisabled)
162                 SYSTEM_StartTicks();
163             return i + 1;  /* 0 means error */
164         }
165     return 0;
166 }
167
168
169 /***********************************************************************
170  *           KillSystemTimer   (SYSTEM.3)
171  *
172  * Note: do not confuse this function with USER.182
173  */
174 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
175 {
176     if (!timer || (timer > NB_SYS_TIMERS)) return timer;  /* Error */
177     SYS_Timers[timer-1].callback = NULL;
178     if ((!--SYS_NbTimers) && !SYS_TimersDisabled) SYSTEM_StopTicks();
179     return 0;
180 }
181
182
183 /***********************************************************************
184  *           EnableSystemTimers   (SYSTEM.4)
185  */
186 void WINAPI EnableSystemTimers(void)
187 {
188     SYS_TimersDisabled = FALSE;
189     if (SYS_NbTimers) SYSTEM_StartTicks();
190 }
191
192
193 /***********************************************************************
194  *           DisableSystemTimers   (SYSTEM.5)
195  */
196 void WINAPI DisableSystemTimers(void)
197 {
198     SYS_TimersDisabled = TRUE;
199     if (SYS_NbTimers) SYSTEM_StopTicks();
200 }