Removed some of the XXX_reg macros now that we are using the standard
[wine] / misc / system.c
1 /*
2  * SYSTEM DLL routines
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include "windef.h"
8 #include "wingdi.h"
9 #include "wine/winbase16.h"
10 #include "wine/winuser16.h"
11 #include "services.h"
12 #include "callback.h"
13 #include "stackframe.h"
14 #include "builtin16.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(system)
18
19 typedef struct
20 {
21     SYSTEMTIMERPROC callback;  /* NULL if not in use */
22     INT     rate;
23     INT     ticks;
24 } SYSTEM_TIMER;
25
26 #define NB_SYS_TIMERS   8
27 #define SYS_TIMER_RATE  54925
28
29 static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
30 static int SYS_NbTimers = 0;
31 static HANDLE SYS_Service = INVALID_HANDLE_VALUE;
32
33
34 /***********************************************************************
35  *           SYSTEM_TimerTick
36  */
37 static void CALLBACK SYSTEM_TimerTick( ULONG_PTR arg )
38 {
39     int i;
40
41     for (i = 0; i < NB_SYS_TIMERS; i++)
42     {
43         if (!SYS_Timers[i].callback) continue;
44         if ((SYS_Timers[i].ticks -= SYS_TIMER_RATE) <= 0)
45         {
46             SYS_Timers[i].ticks += SYS_Timers[i].rate;
47             SYS_Timers[i].callback( i+1 );
48         }
49     }
50 }
51
52 /**********************************************************************
53  *           SYSTEM_StartTicks
54  *
55  * Start the system tick timer.
56  */
57 static void SYSTEM_StartTicks(void)
58 {
59     if ( SYS_Service == INVALID_HANDLE_VALUE )
60         SYS_Service = SERVICE_AddTimer( (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0L );
61 }
62
63
64 /**********************************************************************
65  *           SYSTEM_StopTicks
66  *
67  * Stop the system tick timer.
68  */
69 static void SYSTEM_StopTicks(void)
70 {
71     if ( SYS_Service != INVALID_HANDLE_VALUE )
72     {
73         SERVICE_Delete( SYS_Service );
74         SYS_Service = INVALID_HANDLE_VALUE;
75     }
76 }
77
78
79 /***********************************************************************
80  *           InquireSystem   (SYSTEM.1)
81  *
82  * Note: the function always takes 2 WORD arguments, contrary to what
83  *       "Undocumented Windows" says.
84   */
85 DWORD WINAPI InquireSystem16( WORD code, WORD arg )
86 {
87     WORD drivetype;
88
89     switch(code)
90     {
91     case 0:  /* Get timer resolution */
92         return SYS_TIMER_RATE;
93
94     case 1:  /* Get drive type */
95         drivetype = GetDriveType16( arg );
96         return MAKELONG( drivetype, drivetype );
97
98     case 2:  /* Enable one-drive logic */
99         FIXME("Case %d: set single-drive %d not supported\n", code, arg );
100         return 0;
101     }
102     WARN("Unknown code %d\n", code );
103     return 0;
104 }
105
106
107 /***********************************************************************
108  *           CreateSystemTimer   (SYSTEM.2)
109  */
110 WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
111 {
112     int i;
113     for (i = 0; i < NB_SYS_TIMERS; i++)
114         if (!SYS_Timers[i].callback)  /* Found one */
115         {
116             SYS_Timers[i].rate = (UINT)rate * 1000;
117             if (SYS_Timers[i].rate < SYS_TIMER_RATE)
118                 SYS_Timers[i].rate = SYS_TIMER_RATE;
119             SYS_Timers[i].ticks = SYS_Timers[i].rate;
120             SYS_Timers[i].callback = callback;
121             if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
122             return i + 1;  /* 0 means error */
123         }
124     return 0;
125 }
126
127 static void SYSTEM_CallSystemTimerProc( FARPROC16 proc, WORD timer )
128 {
129     CONTEXT86 context;
130     memset( &context, '\0', sizeof(context) );
131
132     context.SegCs = SELECTOROF( proc );
133     context.Eip   = OFFSETOF( proc );
134     context.Ebp   = OFFSETOF( NtCurrentTeb()->cur_stack )
135                           + (WORD)&((STACK16FRAME*)0)->bp;
136
137     AX_reg( &context ) = timer;
138
139     CallTo16RegisterShort( &context, 0 );
140 }
141
142 WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc )
143 {
144     FARPROC thunk = THUNK_Alloc( proc, (RELAY)SYSTEM_CallSystemTimerProc );
145     WORD timer = CreateSystemTimer( rate, (SYSTEMTIMERPROC)thunk );
146     if (!timer) THUNK_Free( thunk );
147     return timer;
148 }
149
150
151 /***********************************************************************
152  *           KillSystemTimer   (SYSTEM.3)
153  *
154  * Note: do not confuse this function with USER.182
155  */
156 WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
157 {
158     if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback ) 
159         return timer;  /* Error */
160
161     THUNK_Free( (FARPROC)SYS_Timers[timer-1].callback );
162     SYS_Timers[timer-1].callback = NULL;
163
164     if (!--SYS_NbTimers) SYSTEM_StopTicks();
165     return 0;
166 }
167
168
169 /***********************************************************************
170  *           EnableSystemTimers   (SYSTEM.4)
171  */
172 void WINAPI EnableSystemTimers16(void)
173 {
174     if ( SYS_Service != INVALID_HANDLE_VALUE )
175         SERVICE_Enable( SYS_Service );
176 }
177
178
179 /***********************************************************************
180  *           DisableSystemTimers   (SYSTEM.5)
181  */
182 void WINAPI DisableSystemTimers16(void)
183 {
184     if ( SYS_Service != INVALID_HANDLE_VALUE )
185         SERVICE_Disable( SYS_Service );
186 }
187
188
189 /***********************************************************************
190  *           Get80x87SaveSize16   (SYSTEM.7)
191  */
192 WORD WINAPI Get80x87SaveSize16(void)
193 {
194     return 94;
195 }
196
197
198 /***********************************************************************
199  *           Save80x87State16   (SYSTEM.8)
200  */
201 void WINAPI Save80x87State16( char *ptr )
202 {
203 #ifdef __i386__
204     __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
205 #endif
206 }
207
208
209 /***********************************************************************
210  *           Restore80x87State16   (SYSTEM.9)
211  */
212 void WINAPI Restore80x87State16( const char *ptr )
213 {
214 #ifdef __i386__
215     __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
216 #endif
217 }
218