Watt-32 tcp/ip  2.2 dev-rel.10
powerpak.c
Go to the documentation of this file.
1 
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 
19 #include "wattcp.h"
20 #include "printk.h"
21 #include "misc.h"
22 #include "wdpmi.h"
23 #include "powerpak.h"
24 
25 #if (DOSX & POWERPAK) && defined(BORLAND386)
26 
27 extern int _ostype;
28 
29 /* Don't include <windows.h> because of conflicting types etc.
30  */
31 #define WINAPI __stdcall __import
32 
33 extern void * WINAPI GetModuleHandleA (const char *module);
34 extern void * WINAPI GetProcAddress (void *module, const char *func);
35 
36 /* these are missing in Win32, damn...
37  */
38 static UINT (WINAPI* _AllocSelector) (UINT);
39 static UINT (WINAPI* _FreeSelector) (UINT);
40 
41 BOOL powerpak_init (void)
42 {
43  void *mod;
44 
45  if (_ostype == 2) /* plain DOS */
46  return (TRUE);
47 
48  mod = GetModuleHandleA ("kernel32.dll");
49  if (!mod)
50  return (FALSE);
51 
52  _AllocSelector = (UINT (WINAPI*)(UINT)) GetProcAddress (mod, "AllocSelector");
53  _FreeSelector = (UINT (WINAPI*)(UINT)) GetProcAddress (mod, "FreeSelector");
54  return (_AllocSelector && _FreeSelector);
55 }
56 
57 WORD dpmi_create_dos_selector (void)
58 {
59  WORD sel;
60 
61  if (_ostype != 2) /* Not plain DOS */
62  return (*_AllocSelector) (0);
63 
64  __dpmi_errno = 0;
65  _EAX = 0; /* DPMI 0: create selector */
66  _ECX = 1;
67  geninterrupt (0x31);
68  if (_FLAGS & CARRY_BIT)
69  {
70  __dpmi_errno = _AX;
71  return (0);
72  }
73  sel = _AX;
74  _EAX = 8; /* DPMI 8: set limit 1MByte */
75  _BX = sel;
76  _CX = 0x0F;
77  _DX = 0xFFFF;
78  geninterrupt (0x31);
79  if (_FLAGS & CARRY_BIT)
80  {
81  __dpmi_errno = _AX;
82  return (0);
83  }
84  return (sel);
85 }
86 
87 int dpmi_free_dos_selector (WORD sel)
88 {
89  if (_ostype != 2) /* Not plain DOS */
90  return (*_FreeSelector) (sel);
91 
92  __dpmi_errno = 0;
93  _EAX = 1;
94  _BX = sel;
95  geninterrupt (0x31);
96  if (_FLAGS & CARRY_BIT)
97  {
98  __dpmi_errno = _AX;
99  return (0);
100  }
101  return (1);
102 }
103 
104 void ReadRealMem (void *dst, REALPTR rp, unsigned size)
105 {
106  DWORD lin = (RP_SEG(rp) << 4) + RP_OFF(rp);
107 
108  __asm {
109  push ds
110  push edi
111  push esi
112  mov ds, _watt_dos_ds
113  mov esi, lin
114  mov edi, dst
115  mov ecx, size
116  shr ecx, 2
117  cld
118  db 0F3h, 0A5h /* rep movsd */
119  mov ecx, size
120  and ecx, 3
121  rep movsb /* move rest */
122  pop esi
123  pop edi
124  pop ds
125  }
126 }
127 
128 void WriteRealMem (REALPTR rp, const void *src, int size)
129 {
130  DWORD lin = (RP_SEG(rp) << 4) + RP_OFF(rp);
131 
132  __asm {
133  push es
134  push edi
135  push esi
136  mov es, _watt_dos_ds
137  mov edi, lin
138  mov esi, src
139  mov ecx, size
140  shr ecx, 2
141  cld
142  db 0F3h, 0A5h /* rep movsd */
143  mov ecx, size
144  and ecx, 3
145  rep movsb /* move rest */
146  pop esi
147  pop edi
148  pop es
149  }
150 }
151 
152 BYTE _farpeekb (WORD sel, DWORD ofs)
153 {
154  __asm {
155  push es
156  mov ax, sel
157  mov edx, ofs
158  mov es, ax
159  mov al, es:[edx]
160  pop es
161  }
162  return (_AL);
163 }
164 
165 WORD _farpeekw (WORD sel, DWORD ofs)
166 {
167  __asm {
168  push es
169  mov ax, sel
170  mov edx, ofs
171  mov es, ax
172  mov ax, es:[edx]
173  pop es
174  }
175  return (_AX);
176 }
177 
178 DWORD _farpeekl (WORD sel, DWORD ofs)
179 {
180  __asm {
181  push es
182  mov ax, sel
183  mov edx, ofs
184  mov es, ax
185  mov eax, es:[edx]
186  pop es
187  }
188  return (_EAX);
189 }
190 
191 void _farpokeb (WORD sel, DWORD ofs, BYTE val)
192 {
193  __asm {
194  push es
195  mov ax, sel
196  mov edx, ofs
197  mov es, ax
198  mov al, val
199  mov es:[edx], al
200  pop es
201  }
202 }
203 
204 void _farpokew (WORD sel, DWORD ofs, WORD val)
205 {
206  __asm {
207  push es
208  mov ax, sel
209  mov edx, ofs
210  mov es, ax
211  mov ax, val
212  mov es:[edx], ax
213  pop es
214  }
215 }
216 
217 void _farpokel (WORD sel, DWORD ofs, DWORD val)
218 {
219  __asm {
220  push es
221  mov ax, sel
222  mov edx, ofs
223  mov es, ax
224  mov eax, val
225  mov es:[edx], eax
226  pop es
227  }
228 }
229 
230 int dpmi_getvect (int intr, WORD *sel, DWORD *ofs)
231 {
232  __asm {
233  push ebx
234  push es
235  mov ah, 0x35
236  mov al, byte ptr intr
237  int 0x21
238  mov ax, es
239  pop es
240  mov edx, sel
241  mov [edx], ax
242  mov edx, ofs
243  mov [edx], ebx
244  pop ebx
245  }
246  return (1);
247 }
248 
249 int dpmi_setvect (int intr, WORD sel, DWORD ofs)
250 {
251  __asm {
252  push ds
253  mov edx, ofs
254  mov ax, sel
255  mov ds, ax
256  mov ah, 0x25
257  mov al, byte ptr intr
258  int 0x21
259  pop ds
260  }
261  return (1);
262 }
263 
264 #if !defined(USE_FAST_PKT)
265 
266 /* Some code below borrowed from djgpp, some heavily modified */
267 
268 /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
269 /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */
270 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
271 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
272 
273 /* This code really can't be nested since the RMCB structure isn't copied,
274  * so the stack check isn't really useful. But someone may fix it someday.
275  * On entry CS is known to be ours, ES is probably ours (since we passed it),
276  * SS:ESP is locked 4K stack. ES:EDI is regs structure, DS:ESI is RM SS:SP.
277  * Do NOT enable interrupts in the user routine. Thanks to ctm@ardi.com for
278  * the improvements. C. Sandmann 3/95
279  */
280 
281 #define FILL 0x00
282 
283 static BYTE wrapper_code[] = {
284 /* 00 */ 0x06, /* push es */
285 /* 01 */ 0x1E, /* push ds */
286 /* 02 */ 0x06, /* push es */
287 /* 03 */ 0x1F, /* pop ds */
288 /* 04 */ 0x66, 0xB8, /* mov ax, */
289 /* 06 */ FILL, FILL, /* _our_selector */
290 /* 08 */ 0x8E, 0xD8, /* mov ds, ax */
291 /* 0A */ 0xFF, 0x05, /* incl */
292 /* 0C */ FILL, FILL, FILL, FILL, /* _call_count */
293 /* 10 */ 0x83, 0x3D, /* cmpl */
294 /* 12 */ FILL, FILL, FILL, FILL, /* _in_this_handler */
295 /* 16 */ 0x00, /* $0 */
296 /* 17 */ 0x75, /* jne */
297 /* 18 */ 0x33, /* out */
298 /* 19 */ 0xC6, 0x05, /* movb */
299 /* 1B */ FILL, FILL, FILL, FILL, /* _in_this_handler */
300 /* 1F */ 0x01, /* $1 */
301 /* 20 */ 0x8E, 0xC0, /* mov es, ax */
302 /* 22 */ 0x8E, 0xE0, /* mov fs, ax */
303 /* 24 */ 0x8E, 0xE8, /* mov gs, ax */
304 /* 26 */ 0xBB, /* mov ebx, */
305 /* 27 */ FILL, FILL, FILL, FILL, /* _local_stack */
306 /* 2B */ 0xFC, /* cld */
307 /* 2C */ 0x89, 0xE1, /* mov ecx, esp */
308 /* 2E */ 0x8C, 0xD2, /* mov dx, ss */
309 /* 30 */ 0x8E, 0xD0, /* mov ss, ax */
310 /* 32 */ 0x89, 0xDC, /* mov esp, ebx */
311 /* 34 */ 0x52, /* push edx */
312 /* 35 */ 0x51, /* push ecx */
313 /* 36 */ 0x56, /* push esi */
314 /* 37 */ 0x57, /* push edi */
315 /* 38 */ 0xE8, /* call */
316 /* 39 */ FILL, FILL, FILL, FILL, /* _rmcb */
317 /* 3D */ 0x5F, /* pop edi */
318 /* 3E */ 0x5E, /* pop esi */
319 /* 3F */ 0x58, /* pop eax */
320 /* 40 */ 0x5B, /* pop ebx */
321 /* 41 */ 0x8E, 0xD3, /* mov ss, bx */
322 /* 43 */ 0x89, 0xC4, /* mov esp, eax */
323 /* 45 */ 0xC6, 0x05, /* movb */
324 /* 47 */ FILL, FILL, FILL, FILL, /* _in_this_handler */
325 /* 4B */ 0x00, /* $0 */
326 /* 4C */ 0x1F, /* out:pop ds */
327 /* 4D */ 0x07, /* pop es */
328 /* 4E */ 0x8B, 0x06, /* mov eax,[esi] */
329 /* 50 */ 0x26, 0x89, 0x47,0x2A, /* mov es:[edi+42],eax */
330 /* 54 */ 0x66, 0x26, 0x83,0x47,0x2E,4, /* add es:[edi+46],0x4 */
331  0xCF /* iret */
332  };
333 
334 #define RMCB_STACK_SIZE (4*1024)
335 
336 static REALPTR alloc_callback (void (*callback)(void), REAL_regs *regs)
337 {
338  __asm { /* I had to use assembly here because int386x() crashed */
339  mov __dpmi_errno, 0
340  push es
341  push ds
342  push edi
343  push esi
344  mov ax, ds
345 
346  mov edi, regs
347  mov es, ax /* ES:EDI = DS:regs */
348 
349  mov ax, cs
350  mov ds, ax
351  mov esi, callback /* DS:ESI = CS:callback */
352 
353  mov ax, 303h
354  int 31h
355  pop esi
356  pop edi
357  pop ds
358  pop es
359  jc fail:
360  }
361  return (_CX << 16) + _DX;
362 
363 fail:
364  __dpmi_errno = _AX;
365  return (0);
366 }
367 
368 REALPTR dpmi_alloc_callback_retf (DPMI_callback *cb)
369 {
370  REALPTR rmcb;
371  BYTE *wrapper = calloc (sizeof(wrapper_code) + RMCB_STACK_SIZE, 1);
372  BYTE *stack = wrapper + sizeof(wrapper_code);
373 
374  if (!wrapper)
375  return (0);
376 
377  memcpy (wrapper, wrapper_code, sizeof(wrapper_code));
378 
379  if (!dpmi_lock_region(&cb->rm_regs, sizeof(cb->rm_regs)) ||
380  !dpmi_lock_region(wrapper, sizeof(wrapper_code) + RMCB_STACK_SIZE))
381  {
382  fprintf (stderr, "dpmi_lock_region: DPMI error %04Xh\n", __dpmi_errno);
383  free (wrapper);
384  free (stack);
385  return (0);
386  }
387 
388  *(short*)(wrapper+0x06) = _DS;
389  *(long*) (wrapper+0x0C) = (long) stack + 8;
390  *(long*) (wrapper+0x12) = (long) stack + 4;
391  *(long*) (wrapper+0x1B) = (long) stack + 4;
392  *(long*) (wrapper+0x27) = (long) stack + RMCB_STACK_SIZE; /* !! was -4 */
393  *(long*) (wrapper+0x39) = (long) cb->pm_func - ((long)wrapper + 0x3D);
394  *(long*) (wrapper+0x47) = (long) stack + 4;
395 
396  rmcb = alloc_callback ((void(*)(void))wrapper, &cb->rm_regs);
397  if (!rmcb)
398  {
399  free (wrapper);
400  fprintf (stderr, "dpmi_alloc_callback: DPMI error %04Xh\n", __dpmi_errno);
401  return (0);
402  }
403  cb->wrapper = wrapper;
404  cb->rm_addr = rmcb;
405  return (1);
406 }
407 
408 int dpmi_free_callback_retf (DPMI_callback *cb)
409 {
410  union REGS r;
411 
412  if (!cb || !cb->wrapper)
413  return (0);
414 
415  free (cb->wrapper);
416  cb->wrapper = NULL;
417  cb->pm_func = NULL;
418 
419  __dpmi_errno = 0;
420  r.w.ax = 0x304;
421  r.w.cx = RP_SEG (cb->rm_addr);
422  r.w.dx = RP_OFF (cb->rm_addr);
423  int386 (0x31, &r, &r);
424  if (r.w.cflag & 1)
425  {
426  __dpmi_errno = r.w.ax;
427  return (0);
428  }
429  return (1);
430 }
431 #endif /* USE_FAST_PKT */
432 #endif /* (DOSX & POWERPAK) && BORLAND386 */
433 
Core definitions.
Definition: ah.h:48
static struct RMCB_record rmcb[MAX_WRAPPERS]
Definition: x32vm.c:47