Watt-32 tcp/ip  2.2 dev-rel.10
pcintr.c
Go to the documentation of this file.
1 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <signal.h>
18 
19 #include "wattcp.h"
20 #include "strings.h"
21 #include "language.h"
22 #include "misc.h"
23 #include "run.h"
24 #include "pctcp.h"
25 #include "wdpmi.h"
26 #include "x32vm.h"
27 #include "powerpak.h"
28 
29 #if (DOSX & DJGPP)
30  #include <sys/time.h>
31 #elif (DOSX & PHARLAP)
32  #include <mw/exc.h> /* _dx_alloc_rmode_wrapper_iret() */
33 #endif
34 
35 #if defined(__MSDOS__)
36 
37 #define TIMER_INTR 0x08
38 #define STK_SIZE 1024
39 
40 void (W32_CALL *wintr_chain)(void) = NULL;
41 
42 static BOOL on_isr8;
43 
44 #if !(DOSX & POWERPAK)
45  static BOOL inside_isr8 = FALSE;
46  static WORD indos_flag_seg, indos_flag_ofs;
47  static WORD crit_err_seg, crit_err_ofs; /* only for DOS 3.1+ */
48 
49  static void find_DOS_flags (void);
50  static BOOL DOS_is_idle (void);
51 #endif
52 
53 #if (DOSX & DJGPP)
54  static void (*old_sigalrm) (int);
55 
56 #elif !(DOSX & (PHARLAP|X32VM|POWERPAK))
57  static UINT locstack [STK_SIZE];
58 
59  static void stack_probe (void)
60  {
61 #if defined(USE_DEBUG)
62  int used;
63  UINT *p;
64 
65  for (p = locstack, used = 0; *p && used < DIM(locstack); p++)
66  used++;
67  if (used >= DIM(locstack))
68  {
69  (*_printf) ("pcintr.c: Stack overflow. Increase STK_SIZE\n");
70  fflush (stdout);
71  exit (-1);
72  }
73 #endif
74  }
75 #endif
76 
77 BOOL wintr_enable (void)
78 {
79  BOOL old = on_isr8;
80  on_isr8 = TRUE;
81  return (old);
82 }
83 
84 void wintr_disable (void)
85 {
86  on_isr8 = FALSE;
87 }
88 
89 #if (DOSX & (PHARLAP|X32VM))
90  static REALPTR oldint, timer_cb;
91  static RMC_BLK rmRegs;
92 
93  static void NewTimer (void)
94  {
95  _dx_call_real (oldint, &rmRegs, 1);
96 
97  if (!inside_isr8)
98  {
99  inside_isr8 = TRUE;
100  if (on_isr8 && DOS_is_idle())
101  {
102  if (wintr_chain)
103  (*wintr_chain)();
104  tcp_tick (NULL);
105  }
106  inside_isr8 = FALSE;
107  }
108  }
109 
110  void wintr_shutdown (void)
111  {
112  if (oldint)
113  {
114  _dx_rmiv_set (TIMER_INTR, oldint);
115  _dx_free_rmode_wrapper (timer_cb);
116  oldint = 0;
117  }
118  }
119 
120  void wintr_init (void)
121  {
122  timer_cb = _dx_alloc_rmode_wrapper_iret ((pmodeHook)NewTimer, 80000);
123  if (!timer_cb)
124  {
125  outsnl (_LANG("Cannot allocate real-mode timer callback"));
126  exit (1);
127  }
128  find_DOS_flags();
129  _dx_rmiv_get (TIMER_INTR, &oldint);
130  _dx_rmiv_set (TIMER_INTR, timer_cb);
131  RUNDOWN_ADD (wintr_shutdown, -1); /* call it very early */
132  }
133 
134 #elif (DOSX & DJGPP)
135  static void NewTimer (int sig)
136  {
137  if (!inside_isr8)
138  {
139  inside_isr8 = TRUE;
140  if (old_sigalrm)
141  (*old_sigalrm) (sig);
142  if (on_isr8 && DOS_is_idle())
143  {
144  if (wintr_chain)
145  (*wintr_chain)();
146  tcp_tick (NULL);
147  }
148  inside_isr8 = FALSE;
149  }
150  }
151 
152  void wintr_shutdown (void)
153  {
154  struct itimerval tim;
155 
156  tim.it_interval.tv_sec = 0;
157  tim.it_interval.tv_usec = 0;
158  signal (SIGALRM, old_sigalrm);
159  setitimer (ITIMER_REAL, &tim, NULL);
160  }
161 
162  void wintr_init (void)
163  {
164  struct itimerval tim;
165 
166  find_DOS_flags();
167  tim.it_interval.tv_usec = 54945; /* 1000000/18.2 */
168  tim.it_interval.tv_sec = 0;
169  tim.it_value = tim.it_interval;
170  old_sigalrm = signal (SIGALRM, NewTimer);
171  setitimer (ITIMER_REAL, &tim, NULL);
172  }
173 
174 #elif defined(WATCOM386) && (DOSX & DOS4GW)
175  static void (__interrupt __far *oldint)();
176 
177  static void __interrupt __far NewTimer (void)
178  {
179  if (!inside_isr8)
180  {
181  inside_isr8 = TRUE;
182  if (on_isr8 && DOS_is_idle())
183  {
184  DISABLE();
185  STACK_SET (&locstack[STK_SIZE-1]);
186 
187  if (wintr_chain)
188  (*wintr_chain)();
189  tcp_tick (NULL);
190 
191  STACK_RESTORE();
192  ENABLE();
193  stack_probe();
194  }
195  inside_isr8 = FALSE;
196  }
197  _chain_intr (oldint);
198  }
199 
200  void wintr_shutdown (void)
201  {
202  if (oldint)
203  {
204  _dos_setvect (TIMER_INTR, oldint);
205  oldint = NULL;
206  }
207  }
208 
209  void wintr_init (void)
210  {
211  find_DOS_flags();
212  oldint = _dos_getvect (TIMER_INTR);
213  _dos_setvect (TIMER_INTR, NewTimer);
214  memset (&locstack, 0, sizeof(locstack));
215  RUNDOWN_ADD (wintr_shutdown, -1);
216  }
217 
218 #elif (DOSX & POWERPAK) && defined(NOT_YET)
219  static struct {
220  DWORD offset;
221  WORD selector;
222  } oldint;
223 
224  static WORD our_ds;
225 
226  void NewTimerPre (void);
227 
228  static void NewTimer (void)
229  {
230  __asm {
231  push es
232  push ds
233  mov ds, cs:[our_ds]
234  mov es, cs:[our_ds]
235  }
236 
237  if (!inside_isr8)
238  {
239  inside_isr8 = TRUE;
240  if (on_isr8 && DOS_is_idle())
241  {
242  DISABLE();
243  STACK_SET (offset locstack[STK_SIZE-1]);
244 
245  if (wintr_chain)
246  (*wintr_chain)();
247  tcp_tick (NULL);
248 
249  STACK_RESTORE();
250  ENABLE();
251  stack_probe();
252  }
253  inside_isr8 = FALSE;
254  }
255  dpmi_chain_intr (oldint.selector, oldint.offset);
256  }
257 
258  void wintr_shutdown (void)
259  {
260  if (oldint.selector)
261  {
262  dpmi_setvect (TIMER_INTR, oldint.selector, oldint.offset);
263  oldint.selector = NULL;
264  }
265  }
266 
267  void wintr_init (void)
268  {
269  find_DOS_flags();
270  our_ds = _DS;
271  dpmi_getvect (TIMER_INTR, &oldint.selector, &oldint.offset);
272  dpmi_setvect (TIMER_INTR, _CS, (DWORD)NewTimer);
273  memset (&locstack, 0, sizeof(locstack));
274  RUNDOWN_ADD (wintr_shutdown, -1);
275  }
276 
277 #elif (DOSX == 0) && !defined(NO_INLINE_ASM)
278 
279  static W32_IntrHandler oldint;
280 
281  static INTR_PROTOTYPE NewTimer (void)
282  {
283  (*oldint)(); /* chain now */
284 
285  if (!inside_isr8)
286  {
287  inside_isr8 = TRUE;
288 
289  if (on_isr8 && DOS_is_idle())
290  {
291  #ifdef __WATCOMC__
292  DISABLE();
293  STACK_SET (&locstack[STK_SIZE-1]);
294  #else
295  static UINT old_SP;
296  static WORD old_SS;
297  asm pushf
298  asm cli
299  asm mov ax, ss
300  asm mov old_SS, ax
301  asm mov ax, sp
302  asm mov old_SP, ax
303  asm mov ax, ds
304  asm mov ss, ax
305  asm lea sp, locstack[STK_SIZE-1]
306  #endif
307  ENABLE();
308 
309  if (wintr_chain)
310  (*wintr_chain)();
311  tcp_tick (NULL);
312 
313  DISABLE();
314  #ifdef __WATCOMC__
315  STACK_RESTORE();
316  #else
317  asm mov ax,old_SS
318  asm mov ss,ax
319  asm mov ax,old_SP
320  asm mov sp,ax
321  #endif
322  ENABLE();
323  stack_probe();
324  }
325  inside_isr8 = FALSE;
326  }
327  }
328 
329  void wintr_shutdown (void)
330  {
331  if (oldint)
332  {
333  setvect (TIMER_INTR, oldint);
334  oldint = NULL;
335  }
336  }
337 
338  void wintr_init (void)
339  {
340  find_DOS_flags();
341  oldint = getvect (TIMER_INTR);
342  setvect (TIMER_INTR, NewTimer);
343  memset (&locstack, 0, sizeof(locstack));
344  RUNDOWN_ADD (wintr_shutdown, -1);
345  }
346 #endif
347 
348 #if !(DOSX & POWERPAK)
349 static void find_DOS_flags (void)
350 {
351  IREGS regs;
352 
353  memset (&regs, 0, sizeof(regs));
354  regs.r_ax = 0x3400;
355 
356  GEN_INTERRUPT (0x21, &regs);
357  indos_flag_seg = regs.r_es;
358  indos_flag_ofs = regs.r_bx;
359  if (_watt_os_ver >= 0x0301)
360  {
361  crit_err_seg = regs.r_es;
362  crit_err_ofs = regs.r_bx - 1;
363  }
364 }
365 
366 static BOOL DOS_is_idle (void)
367 {
368  BYTE indos, crit = 0;
369 
370  indos = PEEKB (indos_flag_seg, indos_flag_ofs);
371  if (_watt_os_ver >= 0x0301)
372  crit = PEEKB (crit_err_seg, crit_err_ofs);
373  return (crit == 0 && indos == 0);
374 }
375 #endif
376 #endif /* __MSDOS__ */
377 
WORD _watt_os_ver
Definition: misc.c:61
Core definitions.
Definition: x32vm.h:30
WORD W32_CALL tcp_tick(sock_type *s)
Must be called periodically by user application (or BSD socket API).
Definition: pctcp.c:1389
Definition: misc.h:511