~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/krnl386.exe16/int67.c

Version: ~ [ wine-1.5.31 ] ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Int67 (EMS) emulation
  3  *
  4  * Copyright 2002 Jukka Heinonen
  5  *
  6  * This library is free software; you can redistribute it and/or
  7  * modify it under the terms of the GNU Lesser General Public
  8  * License as published by the Free Software Foundation; either
  9  * version 2.1 of the License, or (at your option) any later version.
 10  *
 11  * This library is distributed in the hope that it will be useful,
 12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 14  * Lesser General Public License for more details.
 15  *
 16  * You should have received a copy of the GNU Lesser General Public
 17  * License along with this library; if not, write to the Free Software
 18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 19  */
 20 
 21 #include <assert.h>
 22 #include "wine/winbase16.h"
 23 #include "dosexe.h"
 24 #include "wine/debug.h"
 25 
 26 WINE_DEFAULT_DEBUG_CHANNEL(int);
 27 
 28 /*
 29  * EMS page size == 16 kilobytes.
 30  */
 31 #define EMS_PAGE_SIZE (16*1024)
 32 
 33 /*
 34  * Linear address of EMS page.
 35  */
 36 #define EMS_PAGE_ADDRESS(base,page) (((char*)base) + EMS_PAGE_SIZE * page)
 37 
 38 /*
 39  * Maximum number of pages that can be allocated using EMS.
 40  */
 41 #define EMS_MAX_PAGES 1024
 42 
 43 /*
 44  * Maximum number of EMS handles (allocated blocks).
 45  */
 46 #define EMS_MAX_HANDLES 256
 47 
 48 /*
 49  * Global EMM Import Record.
 50  * Applications can get address of this record
 51  * and directly access allocated memory if they use
 52  * IOCTL interface.
 53  *
 54  * FIXME: Missing lots of fields, packing is not correct.
 55  */
 56 
 57 static struct {
 58   struct {
 59     UCHAR hindex;  /* handle number */
 60     BYTE  flags;   /* bit 0: normal handle rather than system handle */
 61     char  name[8]; /* handle name */
 62     WORD  pages;   /* allocated pages */
 63     void *address; /* physical address*/
 64   } handle[EMS_MAX_HANDLES];
 65 
 66   /* Wine specific fields... */
 67 
 68   int   used_pages;     /* Number of allocated pages. */
 69   void *frame_address;  /* Address of 64k EMS page frame */
 70   WORD  frame_selector; /* Segment of 64k EMS page frame */
 71 
 72   struct {
 73     UCHAR hindex;       /* handle number */
 74     WORD  logical_page; /* logical page */
 75   } mapping[4];
 76 
 77   struct {
 78     UCHAR hindex;       /* handle number */
 79     WORD  logical_page; /* logical page */
 80   } mapping_save_area[EMS_MAX_HANDLES][4];
 81 
 82 } *EMS_record;
 83 
 84 /**********************************************************************
 85  *          EMS_init
 86  *
 87  * Allocates and initialized page frame and EMS global import record.
 88  */
 89 static void EMS_init(void)
 90 {
 91   /*
 92    * Start of 64k EMS frame.
 93    */
 94   ULONG base = 0xc0000;
 95 
 96   if(EMS_record)
 97     return;
 98 
 99   EMS_record = HeapAlloc(GetProcessHeap(),
100                          HEAP_ZERO_MEMORY,
101                          sizeof(*EMS_record));
102 
103   EMS_record->frame_address = (void *)base;
104   EMS_record->frame_selector = base >> 4;
105 }
106 
107 /**********************************************************************
108  *          EMS_alloc
109  *
110  * Get handle and allocate memory.
111  */
112 static void EMS_alloc( CONTEXT86 *context )
113 {
114   int hindex = 1; /* handle zero is reserved for system */
115 
116   while(hindex < EMS_MAX_HANDLES && EMS_record->handle[hindex].address)
117     hindex++;
118 
119   if(hindex == EMS_MAX_HANDLES) {
120     SET_AH( context, 0x85 ); /* status: no more handles available */
121   } else {
122     int   pages = BX_reg(context);
123     void *buffer = HeapAlloc( GetProcessHeap(), 0, pages * EMS_PAGE_SIZE );
124 
125     if(!buffer) {
126       SET_AH( context, 0x88 ); /* status: insufficient pages available */
127     } else {
128       EMS_record->handle[hindex].address = buffer;
129       EMS_record->handle[hindex].pages = pages;
130       EMS_record->used_pages += pages;
131 
132       SET_DX( context, hindex ); /* handle to allocated memory*/
133       SET_AH( context, 0 );      /* status: ok */
134     }
135   }
136 }
137 
138 /**********************************************************************
139  *          EMS_access_name
140  *
141  * Get/set handle name.
142  */
143 static void EMS_access_name( CONTEXT86 *context )
144 {
145   char *ptr;
146   int hindex = DX_reg(context);
147   if(hindex < 0 || hindex >= EMS_MAX_HANDLES) {
148     SET_AH( context, 0x83 ); /* invalid handle */
149     return;
150   }
151 
152   switch AL_reg(context) {
153   case 0x00: /* get name */
154     ptr = PTR_REAL_TO_LIN(context->SegEs, DI_reg(context));
155     memcpy(ptr, EMS_record->handle[hindex].name, 8);
156     SET_AH( context, 0 );
157     break;
158 
159   case 0x01: /* set name */
160     ptr = PTR_REAL_TO_LIN(context->SegDs, SI_reg(context));
161     memcpy(EMS_record->handle[hindex].name, ptr, 8);
162     SET_AH( context, 0 );
163     break;
164 
165   default:
166     INT_BARF(context,0x67);
167     break;
168   }
169 }
170 
171 /**********************************************************************
172  *          EMS_map
173  *
174  * Map logical page into physical page.
175  */
176 static BYTE EMS_map( WORD physical_page, WORD new_hindex, WORD new_logical_page )
177 {
178   int   old_hindex;
179   int   old_logical_page;
180   void *physical_address;
181 
182   if(physical_page > 3)
183     return 0x8b; /* status: invalid physical page */
184 
185   old_hindex = EMS_record->mapping[physical_page].hindex;
186   old_logical_page = EMS_record->mapping[physical_page].logical_page;
187   physical_address = EMS_PAGE_ADDRESS(EMS_record->frame_address, physical_page);
188 
189   /* unmap old page */
190   if(old_hindex) {
191     void *ptr = EMS_PAGE_ADDRESS(EMS_record->handle[old_hindex].address,
192                                  old_logical_page);
193     memcpy(ptr, physical_address, EMS_PAGE_SIZE);
194   }
195 
196   /* map new page */
197   if(new_hindex && new_logical_page != 0xffff) {
198     void *ptr = EMS_PAGE_ADDRESS(EMS_record->handle[new_hindex].address,
199                                  new_logical_page);
200 
201     if(new_hindex >= EMS_MAX_HANDLES || !EMS_record->handle[new_hindex].address)
202       return 0x83; /* status: invalid handle */
203 
204     if(new_logical_page >= EMS_record->handle[new_hindex].pages)
205       return 0x8a; /* status: invalid logical page */
206 
207     memcpy(physical_address, ptr, EMS_PAGE_SIZE);
208     EMS_record->mapping[physical_page].hindex = new_hindex;
209     EMS_record->mapping[physical_page].logical_page = new_logical_page;
210   } else {
211     EMS_record->mapping[physical_page].hindex = 0;
212     EMS_record->mapping[physical_page].logical_page = 0;
213   }
214 
215   return 0; /* status: ok */
216 }
217 
218 /**********************************************************************
219  *          EMS_map_multiple
220  *
221  * Map multiple logical pages into physical pages.
222  */
223 static void EMS_map_multiple( CONTEXT86 *context )
224 {
225   WORD *ptr = PTR_REAL_TO_LIN(context->SegDs, SI_reg(context));
226   BYTE  status = 0;
227   int   i;
228 
229   for(i=0; i<CX_reg(context) && !status; i++, ptr += 2)
230     switch(AL_reg(context)) {
231     case 0x00:
232       status = EMS_map( ptr[1],
233                        DX_reg(context), ptr[0] );
234       break;
235     case 0x01:
236       status = EMS_map( (ptr[1] - EMS_record->frame_selector) >> 10,
237                        DX_reg(context), ptr[0] );
238       break;
239     default:
240       status = 0x8f; /* status: undefined subfunction */
241     }
242 
243   SET_AH( context, status );
244 }
245 
246 /**********************************************************************
247  *          EMS_free
248  *
249  * Free memory and release handle.
250  */
251 static void EMS_free( CONTEXT86 *context )
252 {
253   int hindex = DX_reg(context);
254   int i;
255 
256   if(hindex < 0 || hindex >= EMS_MAX_HANDLES) {
257     SET_AH( context, 0x83 ); /* status: invalid handle */
258     return;
259   }
260 
261   if(!EMS_record->handle[hindex].address) {
262     SET_AH( context, 0 ); /* status: ok */
263     return;
264   }
265 
266   EMS_record->used_pages -= EMS_record->handle[hindex].pages;
267 
268   /* unmap pages */
269   for(i=0; i<4; i++)
270     if(EMS_record->mapping[i].hindex == hindex)
271       EMS_record->mapping[i].hindex = 0;
272 
273   /* free block */
274   HeapFree( GetProcessHeap(), 0, EMS_record->handle[hindex].address );
275   EMS_record->handle[hindex].address = 0;
276 
277   SET_AH( context, 0 );    /* status: ok */
278 }
279 
280 /**********************************************************************
281  *          EMS_save_context
282  *
283  * Save physical page mappings into handle specific save area.
284  */
285 static void EMS_save_context( CONTEXT86 *context )
286 {
287   WORD h = DX_reg(context);
288   int  i;
289 
290   for(i=0; i<4; i++) {
291     EMS_record->mapping_save_area[h][i].hindex = EMS_record->mapping[i].hindex;
292     EMS_record->mapping_save_area[h][i].logical_page = EMS_record->mapping[i].logical_page;
293   }
294 
295   SET_AX( context, 0 ); /* status: ok */
296 }
297 
298 
299 /**********************************************************************
300  *          EMS_restore_context
301  *
302  * Restore physical page mappings from handle specific save area.
303  */
304 static void EMS_restore_context( CONTEXT86 *context )
305 {
306   WORD handle = DX_reg(context);
307   int  i;
308 
309   for(i=0; i<4; i++) {
310     int hindex       = EMS_record->mapping_save_area[handle][i].hindex;
311     int logical_page = EMS_record->mapping_save_area[handle][i].logical_page;
312 
313     if(EMS_map( i, hindex, logical_page )) {
314       SET_AX( context, 0x8e ); /* status: restore of mapping context failed */
315       return;
316     }
317   }
318 
319   SET_AX( context, 0 ); /* status: ok */
320 }
321 
322 /**********************************************************************
323  *          DOSVM_Int67Handler
324  *
325  * Handler for interrupt 67h EMS routines.
326  */
327 void WINAPI DOSVM_Int67Handler( CONTEXT86 *context )
328 {
329   switch AH_reg(context) {
330 
331   case 0x40: /* EMS - GET MANAGER STATUS */
332     SET_AH( context, 0 ); /* status: ok */
333     break;
334 
335   case 0x41: /* EMS - GET PAGE FRAME SEGMENT */
336     EMS_init();
337     SET_BX( context, EMS_record->frame_selector ); /* segment of page frame */
338     SET_AH( context, 0 );                          /* status: ok */
339     break;
340 
341   case 0x42: /* EMS - GET NUMBER OF PAGES */
342     EMS_init();
343     /* unallocated 16k pages */
344     SET_BX( context, EMS_MAX_PAGES - EMS_record->used_pages );
345     /* total number of 16k pages */
346     SET_DX( context, EMS_MAX_PAGES );
347     /* status: ok */
348     SET_AH( context, 0 );
349     break;
350 
351   case 0x43: /* EMS - GET HANDLE AND ALLOCATE MEMORY */
352     EMS_init();
353     EMS_alloc(context);
354     break;
355 
356   case 0x44: /* EMS - MAP MEMORY */
357     EMS_init();
358     SET_AH( context, EMS_map( AL_reg(context), DX_reg(context), BX_reg(context) ) );
359     break;
360 
361   case 0x45: /* EMS - RELEASE HANDLE AND MEMORY */
362     EMS_init();
363     EMS_free(context);
364     break;
365 
366   case 0x46: /* EMS - GET EMM VERSION */
367     SET_AL( context, 0x40 ); /* version 4.0 */
368     SET_AH( context, 0 );    /* status: ok */
369     break;
370 
371   case 0x47: /* EMS - SAVE MAPPING CONTEXT */
372     EMS_init();
373     EMS_save_context(context);
374     break;
375 
376   case 0x48: /* EMS - RESTORE MAPPING CONTEXT */
377     EMS_init();
378     EMS_restore_context(context);
379     break;
380 
381   case 0x49: /* EMS - reserved - GET I/O PORT ADDRESSES */
382   case 0x4a: /* EMS - reserved - GET TRANSLATION ARRAY */
383     INT_BARF(context,0x67);
384     break;
385 
386   case 0x4b: /* EMS - GET NUMBER OF EMM HANDLES */
387     SET_BX( context, EMS_MAX_HANDLES ); /* EMM handles */
388     SET_AH( context, 0 );               /* status: ok */
389     break;
390 
391   case 0x4c: /* EMS - GET PAGES OWNED BY HANDLE */
392   case 0x4d: /* EMS - GET PAGES FOR ALL HANDLES */
393   case 0x4e: /* EMS - GET OR SET PAGE MAP */
394   case 0x4f: /* EMS 4.0 - GET/SET PARTIAL PAGE MAP */
395     INT_BARF(context,0x67);
396     break;
397 
398   case 0x50: /* EMS 4.0 - MAP/UNMAP MULTIPLE HANDLE PAGES */
399     EMS_init();
400     EMS_map_multiple(context);
401     break;
402 
403   case 0x51: /* EMS 4.0 - REALLOCATE PAGES */
404   case 0x52: /* EMS 4.0 - GET/SET HANDLE ATTRIBUTES */
405     INT_BARF(context,0x67);
406     break;
407 
408   case 0x53: /* EMS 4.0 - GET/SET HANDLE NAME */
409     EMS_init();
410     EMS_access_name(context);
411     break;
412 
413   case 0x54: /* EMS 4.0 - GET HANDLE DIRECTORY */
414   case 0x55: /* EMS 4.0 - ALTER PAGE MAP AND JUMP */
415   case 0x56: /* EMS 4.0 - ALTER PAGE MAP AND CALL */
416   case 0x57: /* EMS 4.0 - MOVE/EXCHANGE MEMORY REGION */
417   case 0x58: /* EMS 4.0 - GET MAPPABLE PHYSICAL ADDRESS ARRAY */
418     INT_BARF(context,0x67);
419     break;
420 
421   case 0x59: /* EMS 4.0 - GET EXPANDED MEMORY HARDWARE INFORMATION */
422     if(AL_reg(context) == 0x01) {
423       EMS_init();
424       /* unallocated raw pages */
425       SET_BX( context, EMS_MAX_PAGES - EMS_record->used_pages );
426       /* total number raw pages */
427       SET_DX( context, EMS_MAX_PAGES );
428       /* status: ok */
429       SET_AH( context, 0 );
430     } else
431       INT_BARF(context,0x67);
432     break;
433 
434   case 0x5a: /* EMS 4.0 - ALLOCATE STANDARD/RAW PAGES */
435   case 0x5b: /* EMS 4.0 - ALTERNATE MAP REGISTER SET */
436   case 0x5c: /* EMS 4.0 - PREPARE EXPANDED MEMORY HARDWARE FOR WARM BOOT */
437   case 0x5d: /* EMS 4.0 - ENABLE/DISABLE OS FUNCTION SET FUNCTIONS */
438     INT_BARF(context,0x67);
439     break;
440 
441   case 0xde: /* Virtual Control Program Interface (VCPI) */
442     if(AL_reg(context) == 0x00) {
443       /*
444        * VCPI INSTALLATION CHECK
445        * (AH_reg() != 0) means VCPI is not present
446        */
447       TRACE("- VCPI installation check\n");
448       return;
449     } else
450       INT_BARF(context,0x67);
451     break;
452 
453   default:
454     INT_BARF(context,0x67);
455   }
456 }
457 
458 
459 /**********************************************************************
460  *          EMS_Ioctl_Handler
461  *
462  * Handler for interrupt 21h IOCTL routine for device "EMMXXXX0".
463  */
464 void EMS_Ioctl_Handler( CONTEXT86 *context )
465 {
466   assert(AH_reg(context) == 0x44);
467 
468   switch AL_reg(context) {
469   case 0x00: /* IOCTL - GET DEVICE INFORMATION */
470       RESET_CFLAG(context); /* operation was successful */
471       SET_DX( context, 0x4080 ); /* bit 14 (support ioctl read) and
472                                  * bit 7 (is_device) */
473       break;
474 
475   case 0x02: /* EMS - GET MEMORY MANAGER INFORMATION */
476       /*
477        * This is what is called "Windows Global EMM Import Specification".
478        * Undocumented of course! Supports three requests:
479        * GET API ENTRY POINT
480        * GET EMM IMPORT STRUCTURE ADDRESS
481        * GET MEMORY MANAGER VERSION
482        */
483       INT_BARF(context,0x21);
484       break;
485 
486   case 0x07: /* IOCTL - GET OUTPUT STATUS */
487       RESET_CFLAG(context); /* operation was successful */
488       SET_AL( context, 0xff ); /* device is ready */
489       break;
490 
491   default:
492       INT_BARF(context,0x21);
493       break;
494   }
495 }
496 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.