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