blob: 98b420dc06af656181bdd35a8d488c6ecae9a1cf [file] [log] [blame]
Alexandre Julliardef702d81996-05-28 18:54:58 +00001/*
2 * SYSTEM DLL routines
3 *
4 * Copyright 1996 Alexandre Julliard
5 */
6
Jeremy Whited3e22d92000-02-10 19:03:02 +00007#include "windef.h"
8#include "wingdi.h"
Marcus Meissner04c3e1d1999-02-19 10:37:02 +00009#include "wine/winbase16.h"
10#include "wine/winuser16.h"
Ulrich Weigand06bcab81999-04-11 15:04:00 +000011#include "services.h"
Ulrich Weigand974fd101999-09-20 18:45:53 +000012#include "callback.h"
13#include "stackframe.h"
14#include "builtin16.h"
Alexandre Julliard61fece01999-06-26 19:09:08 +000015#include "debugtools.h"
Alexandre Julliard641ee761997-08-04 16:34:36 +000016
Dimitrie O. Paun529da542000-11-27 23:54:25 +000017DEFAULT_DEBUG_CHANNEL(system);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000018
Alexandre Julliard641ee761997-08-04 16:34:36 +000019typedef struct
20{
Ulrich Weigandf6c48281998-12-10 10:44:38 +000021 SYSTEMTIMERPROC callback; /* NULL if not in use */
Alexandre Julliarda3960291999-02-26 11:11:13 +000022 INT rate;
23 INT ticks;
Alexandre Julliard641ee761997-08-04 16:34:36 +000024} SYSTEM_TIMER;
25
26#define NB_SYS_TIMERS 8
27#define SYS_TIMER_RATE 54925
28
29static SYSTEM_TIMER SYS_Timers[NB_SYS_TIMERS];
30static int SYS_NbTimers = 0;
Ulrich Weigand06bcab81999-04-11 15:04:00 +000031static HANDLE SYS_Service = INVALID_HANDLE_VALUE;
Alexandre Julliard641ee761997-08-04 16:34:36 +000032
Ulrich Weigandf6c48281998-12-10 10:44:38 +000033
Alexandre Julliard641ee761997-08-04 16:34:36 +000034/***********************************************************************
35 * SYSTEM_TimerTick
36 */
Ulrich Weigand06bcab81999-04-11 15:04:00 +000037static void CALLBACK SYSTEM_TimerTick( ULONG_PTR arg )
Alexandre Julliard641ee761997-08-04 16:34:36 +000038{
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;
Ulrich Weigandf6c48281998-12-10 10:44:38 +000047 SYS_Timers[i].callback( i+1 );
Alexandre Julliard641ee761997-08-04 16:34:36 +000048 }
49 }
50}
51
Alexandre Julliard641ee761997-08-04 16:34:36 +000052/**********************************************************************
53 * SYSTEM_StartTicks
54 *
55 * Start the system tick timer.
56 */
57static void SYSTEM_StartTicks(void)
58{
Ulrich Weigand06bcab81999-04-11 15:04:00 +000059 if ( SYS_Service == INVALID_HANDLE_VALUE )
Alexandre Julliard8c8237b2000-05-10 04:43:32 +000060 SYS_Service = SERVICE_AddTimer( (SYS_TIMER_RATE+500)/1000, SYSTEM_TimerTick, 0L );
Alexandre Julliard641ee761997-08-04 16:34:36 +000061}
62
63
64/**********************************************************************
65 * SYSTEM_StopTicks
66 *
67 * Stop the system tick timer.
68 */
69static void SYSTEM_StopTicks(void)
70{
Ulrich Weigand06bcab81999-04-11 15:04:00 +000071 if ( SYS_Service != INVALID_HANDLE_VALUE )
72 {
73 SERVICE_Delete( SYS_Service );
74 SYS_Service = INVALID_HANDLE_VALUE;
75 }
Alexandre Julliard641ee761997-08-04 16:34:36 +000076}
Alexandre Julliardef702d81996-05-28 18:54:58 +000077
78
79/***********************************************************************
80 * InquireSystem (SYSTEM.1)
Alexandre Julliard641ee761997-08-04 16:34:36 +000081 *
82 * Note: the function always takes 2 WORD arguments, contrary to what
83 * "Undocumented Windows" says.
84 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000085DWORD WINAPI InquireSystem16( WORD code, WORD arg )
Alexandre Julliardef702d81996-05-28 18:54:58 +000086{
87 WORD drivetype;
88
89 switch(code)
90 {
91 case 0: /* Get timer resolution */
Alexandre Julliard641ee761997-08-04 16:34:36 +000092 return SYS_TIMER_RATE;
Alexandre Julliardef702d81996-05-28 18:54:58 +000093
94 case 1: /* Get drive type */
Alexandre Julliard641ee761997-08-04 16:34:36 +000095 drivetype = GetDriveType16( arg );
Alexandre Julliardef702d81996-05-28 18:54:58 +000096 return MAKELONG( drivetype, drivetype );
97
98 case 2: /* Enable one-drive logic */
Alexandre Julliard61fece01999-06-26 19:09:08 +000099 FIXME("Case %d: set single-drive %d not supported\n", code, arg );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000100 return 0;
101 }
Alexandre Julliard61fece01999-06-26 19:09:08 +0000102 WARN("Unknown code %d\n", code );
Alexandre Julliardef702d81996-05-28 18:54:58 +0000103 return 0;
104}
Alexandre Julliard641ee761997-08-04 16:34:36 +0000105
106
107/***********************************************************************
108 * CreateSystemTimer (SYSTEM.2)
109 */
Ulrich Weigandf6c48281998-12-10 10:44:38 +0000110WORD WINAPI CreateSystemTimer( WORD rate, SYSTEMTIMERPROC callback )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000111{
112 int i;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000113 for (i = 0; i < NB_SYS_TIMERS; i++)
114 if (!SYS_Timers[i].callback) /* Found one */
115 {
Alexandre Julliarda3960291999-02-26 11:11:13 +0000116 SYS_Timers[i].rate = (UINT)rate * 1000;
Alexandre Julliard641ee761997-08-04 16:34:36 +0000117 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;
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000121 if (++SYS_NbTimers == 1) SYSTEM_StartTicks();
Alexandre Julliard641ee761997-08-04 16:34:36 +0000122 return i + 1; /* 0 means error */
123 }
124 return 0;
125}
126
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000127/**********************************************************************/
128
Ulrich Weigand974fd101999-09-20 18:45:53 +0000129static void SYSTEM_CallSystemTimerProc( FARPROC16 proc, WORD timer )
130{
131 CONTEXT86 context;
132 memset( &context, '\0', sizeof(context) );
133
Alexandre Julliardd8fab2e2000-09-25 23:53:07 +0000134 context.SegCs = SELECTOROF( proc );
135 context.Eip = OFFSETOF( proc );
136 context.Ebp = OFFSETOF( NtCurrentTeb()->cur_stack )
Ulrich Weigand974fd101999-09-20 18:45:53 +0000137 + (WORD)&((STACK16FRAME*)0)->bp;
138
139 AX_reg( &context ) = timer;
140
Alexandre Julliarde296bf32000-11-29 19:39:30 +0000141 wine_call_to_16_regs_short( &context, 0 );
Ulrich Weigand974fd101999-09-20 18:45:53 +0000142}
143
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000144/**********************************************************************/
145
Ulrich Weigand974fd101999-09-20 18:45:53 +0000146WORD WINAPI WIN16_CreateSystemTimer( WORD rate, FARPROC16 proc )
147{
148 FARPROC thunk = THUNK_Alloc( proc, (RELAY)SYSTEM_CallSystemTimerProc );
149 WORD timer = CreateSystemTimer( rate, (SYSTEMTIMERPROC)thunk );
150 if (!timer) THUNK_Free( thunk );
151 return timer;
152}
153
Alexandre Julliard641ee761997-08-04 16:34:36 +0000154
155/***********************************************************************
156 * KillSystemTimer (SYSTEM.3)
157 *
158 * Note: do not confuse this function with USER.182
159 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000160WORD WINAPI SYSTEM_KillSystemTimer( WORD timer )
Alexandre Julliard641ee761997-08-04 16:34:36 +0000161{
Ulrich Weigand974fd101999-09-20 18:45:53 +0000162 if ( !timer || timer > NB_SYS_TIMERS || !SYS_Timers[timer-1].callback )
163 return timer; /* Error */
164
165 THUNK_Free( (FARPROC)SYS_Timers[timer-1].callback );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000166 SYS_Timers[timer-1].callback = NULL;
Ulrich Weigand974fd101999-09-20 18:45:53 +0000167
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000168 if (!--SYS_NbTimers) SYSTEM_StopTicks();
Alexandre Julliard641ee761997-08-04 16:34:36 +0000169 return 0;
170}
171
172
173/***********************************************************************
174 * EnableSystemTimers (SYSTEM.4)
175 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000176void WINAPI EnableSystemTimers16(void)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000177{
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000178 if ( SYS_Service != INVALID_HANDLE_VALUE )
179 SERVICE_Enable( SYS_Service );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000180}
181
182
183/***********************************************************************
184 * DisableSystemTimers (SYSTEM.5)
185 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000186void WINAPI DisableSystemTimers16(void)
Alexandre Julliard641ee761997-08-04 16:34:36 +0000187{
Ulrich Weigand06bcab81999-04-11 15:04:00 +0000188 if ( SYS_Service != INVALID_HANDLE_VALUE )
189 SERVICE_Disable( SYS_Service );
Alexandre Julliard641ee761997-08-04 16:34:36 +0000190}
Alexandre Julliard4220b291999-07-11 17:20:01 +0000191
192
193/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000194 * Get80x87SaveSize (SYSTEM.7)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000195 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000196WORD WINAPI Get80x87SaveSize16(void)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000197{
198 return 94;
199}
200
201
202/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000203 * Save80x87State (SYSTEM.8)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000204 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000205void WINAPI Save80x87State16( char *ptr )
Alexandre Julliard4220b291999-07-11 17:20:01 +0000206{
207#ifdef __i386__
208 __asm__(".byte 0x66; fsave %0; fwait" : "=m" (ptr) );
209#endif
210}
211
212
213/***********************************************************************
Patrik Stridvall01d5e5b2001-07-02 19:59:40 +0000214 * Restore80x87State (SYSTEM.9)
Alexandre Julliard4220b291999-07-11 17:20:01 +0000215 */
Patrik Stridvallb8684a21999-07-31 17:32:05 +0000216void WINAPI Restore80x87State16( const char *ptr )
Alexandre Julliard4220b291999-07-11 17:20:01 +0000217{
218#ifdef __i386__
219 __asm__(".byte 0x66; frstor %0" : : "m" (ptr) );
220#endif
221}
222