]> 4ch.mooo.com Git - 16.git/blob - src/lib/exmm/EMM_ALL.TXT
9291eb62bd63b1ddda663a930ee0051da1000ffb
[16.git] / src / lib / exmm / EMM_ALL.TXT
1 //      Author:  Chris Somers\r
2 \r
3 AJR:\r
4   This file contains 3 .h files and two .c files, and some notes\r
5   all glued together. you'll have to cut them apart to compile.\r
6 \r
7 //      Author:  Chris Somers\r
8 \r
9 To use memory.c, a few notes are in order. This file was originally used\r
10 in an event-driven windowing environment, so there are several headers you\r
11 won't need (so I didn't include 'em).\r
12 \r
13 AJR - I nuked all uneeded references from the code\r
14 \r
15 This code was written for Borland C/C++ v3.1 and has _not_ been tested\r
16 under any other version. The first set of conventional memory calls\r
17 (those flanked by #ifndef USEBORLIB) are to replace Borland's malloc\r
18 library when using 3rd party libraries or APIs which called DOS's malloc.\r
19 Add a -DUSEBORLIB to the compile command line to remove this code.\r
20 \r
21 The file, tasks.h (application specific - not included), optionally\r
22 #define'd EMM_SUPPORT and TCPCOM. #define the first and not the second.\r
23 \r
24 AJR - I modified these sources so this isn't neccessary - all\r
25       references to TCPCOM have been deleted.\r
26 \r
27 Add memory.p to your application to have access to the EMM calls. Don't\r
28 include memory.h - it's got static calls and variables you don't want\r
29 direct access to.\r
30 \r
31 AJR - I added memory.p to memory.c, and cleaned up memory.h so it can\r
32       be included.\r
33 \r
34       Please see emm.c for an example.\r
35 \r
36 returns.h and sizes.h just have the #defines for (duh!) return codes\r
37 and size constants. Unfortunately, the values used for some of the\r
38 return codes may not be safely changed. If they clash with codes in your\r
39 program, it might be safer to rename them than to change their values\r
40 and try to see where the EMM code got broken.\r
41 \r
42 AJR: I renamed returns.h to emmret.h and sizes.h to emmsize.h\r
43      to avoid file name clashes.\r
44 \r
45 Here are some notes on the calls:\r
46 \r
47 OpenEMM()  - call this first, period.\r
48 CloseEMM() - call this last. It'll even free any EMS you forgot to free\r
49              in your program (this isn't like conventional memory, y'know)\r
50 EMMInstalled() - returns TRUE or FALSE. Use only after OpenEMM() is called.\r
51 EMMalloc() - returns a pointer to the first EMM page (EMMSeg:0000 hex).\r
52              Also stuffs a new handle into *Handle (*Handle == NULL is not\r
53              checked for, so be careful or fix the code). You gotta supply\r
54              Pages (i.e. number of 16K blocks).\r
55 EMMRealloc() - increases/decreases number of pages allocated to your handle.\r
56 EMMFree()  - frees all the pages and voids the handle.\r
57 MapEMM()   - places 1 to 4 Pages into the page frame starting with page, Start.\r
58 UnmapEMM() - removes the pages from the page frame so nothing else trashes\r
59              your data.\r
60 UseEMM()   - same as MapEMM() but saves the frame state before mapping.\r
61 SaveEMM()  - same as UnmapEMM() but restores a saved frame state after unmapping.\r
62 EMMCoreLeft() - returns the number of bytes of EMM left to allocate.\r
63 \r
64 The comments in the MapEMM() and UseEMM() (and UnmapEMM() and SaveEMM()) speak\r
65 of 'applications' and 'devices'. These refer to layers in the development\r
66 environment using this .c file. The application layer could use EMS as long\r
67 as it kept track of it's own usage. So it wouldn't have to keep track of the\r
68 environment's usage, 'devices' (i.e. lower layers) saved the page frame\r
69 state to use EMS themselves, so as not to trash the application layer's data,\r
70 and restored the original state upon returning.\r
71 \r
72 \r
73 \r
74 More notes:\r
75 Alexander J Russell wrote:\r
76 \r
77 >How do you USE emm memory?\r
78 >With xms it is obvious - you copy mem back and forth.\r
79 >What the parameters for mapemm() etc... mean isn't documented well enough\r
80 >for a newbie to use it.\r
81 \r
82 EMM is alot like XMS except that the EMM driver does the copying for you,\r
83 without really copying (the 386's LDTs are used to point to appropriate\r
84 parts of physical memory when mapping EMM). Here's how it works.\r
85 EMM has a 64K (typically) page frame in conventional memory, often at\r
86 E000-EFFF. The page frame consists of four 16K pages. When you call\r
87 EMMalloc(), you supply the number of 16K pages you need and it\r
88 returns 1) a handle, and 2) a pointer to the page frame (i.e. E000:0000).\r
89 This memory is allocated somewhere in extended memory but still\r
90 unavailable. To use it, you must 'map' it into the page frame so\r
91 conventional memory pointers can access it. The MapEMM() function\r
92 maps the pages you need (up to four) associated with that handle \r
93 into the page frame. You can now use your alloc'd memory at E000.\r
94 When you're finished accessing the memory, you can unmap it using\r
95 UnmapEMM(). This removes the mapping from the page frame so you can\r
96 map other allocations or just protect what you've already written\r
97 (i.e. writing to the page frame segment won't touch your data).\r
98 N.B. You never *have to* unmap your pages. Mapping new pages\r
99 automagically unmaps existing mappings - but it's good practice\r
100 to unmap when you're finished.\r
101 \r
102 Another way to look at EMS is to consider the page frame as a window\r
103 over the extended memory area. Mapping is like moving the window to\r
104 some area of XMS and making it available with a conventional memory\r
105 pointer - at the page frame address, which never changes. \r
106 In other words, EMS 'bank switches' segments of XMS memory into\r
107 conventional memory.\r
108 \r
109 >I think I call openemm() the use map and unmap to utilize the mem.\r
110 >what does map do, what do the parms mean? Once mapped how is the mem used.\r
111 \r
112 Pretty close. OpenEMM() makes sure the driver is loaded and gets the\r
113 page frame address (EMMSeg:0000). Then EMMalloc() reserves the specified\r
114 number of 16K pages, associates them to a handle, and gives your app the\r
115 page frame address. Then MapEMM() lets you use up to four pages at a time\r
116 (at the address returned by EMMalloc()). The parameters for MapEMM() are:\r
117 - the handle you got from EMMalloc()\r
118 - the memory page # to map to the first page frame page.\r
119 - the number of pages to map to the page frame (max. of 4)\r
120 BTW, all numbering is zero-based.\r
121 \r
122 >Could you send a quick overview of how you actually use emm mem in a dos\r
123 >program.\r
124 \r
125  -------------------- see emm.c for example ---------------\r
126 \r
127 \r
128 >Can I re-post your code and notes on my page?\r
129 Yup. Leaving my name in the comments at the top would be much appreciated.\r
130 \r
131 I learnt most of this from DOS Programmer's Reference by Terry Dettmann\r
132 from Que publishing (it's (C)1989 and I *still* use it!). You can check out\r
133 other references dealing with int67h (the EMS API) too.\r
134 \r
135 Hope I didn't leave anything out. Email me again if any points aren't clear.\r
136 \r
137 Chris S.\r
138 \r
139 AJR adds:\r
140 \r
141 memory.c, and the h files all you need to use emm!\r
142 emm.c is just a test program to show how it is used.\r
143 \r
144 \r
145 /*\r
146    *********************************************************************\r
147    *********************************************************************\r
148 \r
149                                next file\r
150 \r
151    *********************************************************************\r
152    *********************************************************************\r
153 */\r
154 \r
155 // Cut this out as emmsize.h\r
156 \r
157 /*      File:       EmmSize.h\r
158  *      Module:     All Modules\r
159  *      Author(s):  Chris Somers\r
160  *      Date:       May 8, 1992\r
161  *      Version:    V.1.0\r
162  */\r
163 \r
164 #ifndef _EMMSIZES_DEF\r
165 #define _EMMSIZES_DEF 1\r
166 \r
167 \r
168 /* Module size constants */\r
169 \r
170 #define     MAXACTIONS          29\r
171 #define     MAXCHANNELS          4\r
172 #define     MAXFOCUS             3\r
173 #define     MAXBUFTYPES         64\r
174 #define     MAXEMHANDLES        64      /* up to a max of 255 */\r
175 #define     MAXTIMERS           32\r
176 #define     MAXTITEMS          128\r
177 #define     MAXQUEUES           24\r
178 #ifdef PRINTER\r
179 #define     MAXPRNS              4\r
180 #else\r
181 #define     MAXPRNS              0\r
182 #endif\r
183 #ifdef UTSCOM\r
184 #define     MAXUTSSCRNS          2\r
185 #else\r
186 #define     MAXUTSSCRNS          0\r
187 #endif\r
188 #ifdef CAPTURE\r
189 #define     MAXCAPTURE           1\r
190 #else\r
191 #define     MAXCAPTURE           0\r
192 #endif\r
193 #define     MAXIRQS             10\r
194 #define     MAXTCPDSCPTITEMS    16     /*max # of TCP connections*/\r
195 \r
196 #define FREEBUFF        1   /* CallIODevice flag for BuffSize arrays */\r
197 #define DSCONLY         2   /* allocate a BufDscpt, only - no buffer */\r
198 \r
199 #define     EMMPAGESIZE     0x4000     /* 16K EMM page size */\r
200 #define     SETUPLEN            32\r
201 #define     NAMELEN             40\r
202 #define     UNIXLEN             32\r
203 #define     ADDRLEN             16\r
204 #define     TITLELEN           128\r
205 #define     TSLEN               80\r
206 #define     COMMENTLEN          65\r
207 #define     PALSIZE            768\r
208 #define     QSTRLEN            254\r
209 #define     PRNBUFSIZ         2048\r
210 #define     TXTSCRNSIZE       4096\r
211 #define     UTSBUFSIZ         4096\r
212 #define     UTSSCRNSIZ        1920\r
213 #define     QMEMSIZE            15\r
214 #define     KBUFLEN             16\r
215 #define     GXBUFFSIZE      0x4000\r
216 #define     TCPNDBUFFSIZE   0x1000      /*router auto-allocation buff size*/\r
217                                         /* graphics printing scale values */\r
218 #define     SCALE_HALF           1      /* value must not change */\r
219 #define     SCALE_ONE            2\r
220 #define     SCALE_QUART          3      /* value must not change */\r
221 \r
222 #define     SIXTH_SECOND         3L     /* shade over 1/6 of a second*/\r
223 #define     HALF_SECOND          9L\r
224 #define     ONE_SECOND          18L\r
225 #define     TWO_SECONDS         36L\r
226 #define     FIVE_SECONDS        91L\r
227 #define     TEN_SECONDS        182L\r
228 #define     HALF_MINUTE      182*3L     /* same as 18.2*30, right? */\r
229 #define     ONE_MINUTE       182*6L     /* same as 18.2*60, right? */\r
230 #define     TWO_MINUTES     182*12L     /* same as 18.2*120, right? */\r
231 #define     FIVE_MINUTES    182*30L     /* same as 18.2*300, right? */\r
232 #define     TEN_MINUTES     182*60L     /* same as 18.2*600, right? */\r
233 #define     HALF_HOUR      182*180L     /* same as 18.2*1800, right? */\r
234 #define     ONE_HOUR       182*360L     /* same as 18.2*3600, right? */\r
235 \r
236 #define MAXROUTMOVES            24      /*max # of routing moves at one time*/\r
237                                         /*also max # of Move Complete Events*/\r
238 /* Event Channel Defines */\r
239 \r
240 #define MAXRECALLEVENTS    1   /*max nm of Recall Event Channels*/\r
241 #define MAXKBDEVENTS       1   /*max nm of Kbd Event Channels*/\r
242 #define MAXPRNEVENTS       4   /*max nm of Prt Prog & Prt Cmplte Event Chan*/\r
243 #define MAXUTSRCVEVENTS    MAXUTSSCRNS       /*max nm of Uts Rx Event Chans*/\r
244 #define MAXUTSXMTEVENTS    MAXUTSSCRNS       /*max nm of Uts Tx Event Chans*/\r
245 #define MAXCAPEVENTS       2   /* max number of capture event channels */\r
246 #define MAXOP1CMPLTEVENTS  1   /*max nm of Operation 1 Cmplt Event Channels*/\r
247 #define MAXOP2CMPLTEVENTS  1   /*max nm of Operation 2 Cmplt Event Channels*/\r
248 #define MAXOP3CMPLTEVENTS  MAXTCPDSCPTITEMS  /*max nm of Op 3 Event Chans*/\r
249 #define MAXTCPEVENTS       MAXTCPDSCPTITEMS  /* max nm of TCP Event types */\r
250 \r
251 #endif\r
252 \r
253 /*\r
254    *********************************************************************\r
255    *********************************************************************\r
256 \r
257                                next file\r
258 \r
259    *********************************************************************\r
260    *********************************************************************\r
261 */\r
262 \r
263 // AJR notes: some of these are not used by the emm code\r
264 \r
265 // Cut this out as emmret.h\r
266 \r
267 /*      File:       EmmRet.h\r
268  *      Module:     All Modules\r
269  *      Author(s):  Chris Somers\r
270  *      Date:       May 8, 1992\r
271  *      Version:    V.1.0\r
272  */\r
273 \r
274 #ifndef _EMM_RETURNS_DEF\r
275 #define _EMM_RETURNS_DEF 1\r
276 \r
277 /* Module return values */\r
278 \r
279 /* Return Values */\r
280 \r
281 #define     START                8\r
282 #define     END                  7\r
283 #define     MOVABORT             6\r
284 #define     PRN_COMPLETE         5\r
285 #define     PRN_PROGRESS         4\r
286 #define     INCOMPLETE           3\r
287 #define     HAVEROOM             2\r
288 #define     SUCCESS              1\r
289 #define     TRUE                 1\r
290 #define     YES                  1\r
291 #define     FALSE                0\r
292 #define     NO                   0\r
293 #define     NOTREADY             0\r
294 #define     NO_DATA              0\r
295 #define     NONE                -1\r
296 \r
297 /* Start of Recoverable error codes */\r
298 \r
299 #define     NO_SPACE            -1001\r
300 #define     NOTPOLLING          -1002\r
301 #define     ALREADYDONE         -1003\r
302 #define     NO_PRN_DEV          -1004\r
303 #define     OUTF_PAPER          -1005\r
304 #define     NO_VIDEO            -1006\r
305 #define     TIMEOUT             -1007\r
306 #define     FILENOPEN           -1008\r
307 #define     ABORT_REQ           -1009\r
308 #define     DEV_IOERR           -1010\r
309 \r
310 #define     MAXRERR                10\r
311 #define     RECOVERABLE         -1999   /* all above errors are recoverable */\r
312 \r
313 /* Start of Threadfatal error codes */\r
314 \r
315 #define     NOT_OPEN            -2001\r
316 #define     NOT_ATTACHED        -2002\r
317 #define     NO_CONNECTION       -2003\r
318 #define     INSUFF_MEM          -2004\r
319 #define     NR_TIMEOUT          -2005\r
320 \r
321 #define     MAXTERR                 5\r
322 #define     THREADFATAL         -2999   /* above errors force task to cancel */\r
323 \r
324 /* Start of Systemfatal error codes */\r
325 \r
326 #define     BAD_TASKNUM         -3001\r
327 #define     BAD_HANDLE          -3002\r
328 #define     BAD_HARDWARE        -3003\r
329 #define     INVALIDACTION       -3004\r
330 #define     NOFREEITEMS         -3005\r
331 #define     NO_MEMORY           -3006\r
332 #define     NO_EMS              -3007\r
333 #define     VALUE_OUTF_RANGE    -3008\r
334 #define     BAD_MODE            -3009\r
335 #define     NO_PALETTE          -3010\r
336 #define     BAD_DISPPAGE        -3011\r
337 #define     NO_TSR              -3012\r
338 #define     BUFTOOSMALL         -3013\r
339 #define     BAD_NAME            -3014\r
340 #define     BAD_DISPHW          -3015\r
341 #define     NO_FLOPPY           -3016\r
342 \r
343 #define     MAXSERR                16\r
344 #define     SYSTEMFATAL         -3999   /* above errors are fatal to system */\r
345 \r
346 #endif\r
347 \r
348 /*\r
349    *********************************************************************\r
350    *********************************************************************\r
351 \r
352                                next file\r
353 \r
354    *********************************************************************\r
355    *********************************************************************\r
356 */\r
357 \r
358 // Cut this out as memory.h\r
359 \r
360 /*      File:       Memory.h\r
361  *      Module:     All Modules\r
362  *      Author(s):  Chris Somers\r
363  *      Date:       August 5, 1993\r
364  *      Version:    V.1.1\r
365 \r
366         modified by Alex Russell to simplify.\r
367  */\r
368 \r
369 \r
370 #ifndef _MEMORY_DEF\r
371 #define _MEMORY_DEF 1\r
372 \r
373 #include "emmret.h"\r
374 #include "emmsize.h"\r
375 \r
376 #define     CMM                  0\r
377 #define     EMM                  1\r
378 \r
379 extern int      OpenEMM(void);\r
380 extern void     CloseEMM(void);\r
381 extern int      EMMInstalled(void);\r
382 extern void far *EMMalloc(int *Handle, int Pages);\r
383 extern int      EMMRealloc(int Handle, int Pages);\r
384 extern void     EMMFree(int Handle);\r
385 extern int      MapEMM(int Handle, int Start, int Pages);\r
386 extern void     UnmapEMM(int Handle, int Start, int Pages);\r
387 extern int      UseEMM(int Handle, int Start, int Pages);\r
388 extern void     SaveEMM(int Handle, int Start, int Pages);\r
389 extern unsigned long EMMCoreLeft(void);\r
390 \r
391 #endif\r
392 \r
393 /*\r
394    *********************************************************************\r
395    *********************************************************************\r
396 \r
397                                next file\r
398 \r
399    *********************************************************************\r
400    *********************************************************************\r
401 */\r
402 \r
403 \r
404 /*      File:       Memory.c\r
405  *      Module:     All Modules\r
406  *      Author(s):  Chris Somers\r
407  *      Date:       December 1, 1992\r
408  *      Version:    V.1.1\r
409 \r
410         minor mods by Alex Russell to simplify\r
411 \r
412         Must use memory model with FAR code\r
413 \r
414  */\r
415 \r
416 \r
417 \r
418 #if !defined(__LARGE__) && !defined(__COMPACT__) && !defined(__HUGE__)\r
419 #error Invalid memory model for compiling MEMORY.C\r
420 #endif\r
421 \r
422 #include <stdio.h>\r
423 #include <dos.h>\r
424 #include <mem.h>\r
425 \r
426 #include "memory.h"\r
427 \r
428 // static globals --------------------------------\r
429 \r
430 static int  ActiveEMList[MAXEMHANDLES];\r
431 static unsigned int  EMMSeg;\r
432 \r
433 // forward declarations ---------------------------------\r
434 \r
435 static int  EMPresent(void);\r
436 static int  EMReady(void);\r
437 static unsigned int  GetEMMSeg(void);\r
438 static int  GetEMHandle(int NumPages);\r
439 static int  EMMap(int Handle, int LogPg, int PhyPg);\r
440 static int  FreeEMHandle(int Handle);\r
441 static int  GetNumPages(int Handle);\r
442 static int  EMStateSave(int Handle);\r
443 static void EMStateRestore(int Handle);\r
444 \r
445 \r
446 /********************************************************************/\r
447 int\r
448 OpenEMM(void)\r
449 {\r
450     if (!EMPresent() || !EMReady()) return(NOTREADY);\r
451     if (!(EMMSeg = GetEMMSeg())) return(NOTREADY);  /*lint !e720 */\r
452     return(SUCCESS);\r
453 }               /* End of OpenEMM() */\r
454 \r
455 /********************************************************************/\r
456 \r
457 void\r
458 CloseEMM(void)\r
459 {\r
460     int     i;\r
461 \r
462     if (!EMMSeg) return;\r
463     for (i = 0; i < MAXEMHANDLES; i++) {\r
464         if (ActiveEMList[i]) {\r
465             FreeEMHandle(ActiveEMList[i]);\r
466             ActiveEMList[i] = 0;\r
467         }\r
468     }\r
469     EMMSeg = 0;\r
470 }               /* End of CloseEMM() */\r
471 \r
472 /********************************************************************/\r
473 \r
474 int\r
475 EMMInstalled(void)\r
476 {\r
477     return((EMMSeg) ? TRUE : FALSE);        /* successfully opened? */\r
478 }               /* End of EMMInstalled() */\r
479 \r
480 /********************************************************************/\r
481 \r
482 unsigned long\r
483 EMMCoreLeft(void)\r
484 {\r
485     unsigned      Pages;\r
486     unsigned long RtnVal = 0UL;\r
487 \r
488     _asm {\r
489         mov     ah,0x42             /* get EMM free page count */\r
490         int     0x67\r
491         or      ah,ah\r
492         js      InternalError       /* returns 80, 81, or 84 hex on error */\r
493         mov     Pages,bx            /* number of unallocated 16K pages */\r
494     }\r
495     RtnVal = ((unsigned long)Pages << 14);  /* Pages * 16K rtns bytes*/\r
496 \r
497 InternalError:\r
498 \r
499     return(RtnVal);\r
500 }               /* End of EMMCoreLeft() */\r
501 \r
502 /********************************************************************/\r
503 \r
504 void far *\r
505 EMMalloc(int *Handle, int Pages)\r
506 {\r
507     int     i;\r
508     char    *RtnPtr = NULL;\r
509 \r
510     if (!EMMSeg) {\r
511         *Handle = NOTREADY;\r
512         return(NULL);\r
513     }\r
514     if ((Pages < 1) || (Pages > 1020)) {\r
515         *Handle = VALUE_OUTF_RANGE;\r
516         return (NULL);\r
517     }\r
518     for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i]); i++) ;\r
519     if (i == MAXEMHANDLES) {\r
520         *Handle = NOFREEITEMS;\r
521         return (NULL);\r
522     }\r
523     if ((ActiveEMList[i] = GetEMHandle(Pages)) > 0) {\r
524         RtnPtr = MK_FP(EMMSeg, 0);\r
525     }\r
526     *Handle = ActiveEMList[i];\r
527     return((void far *)RtnPtr);\r
528 }               /* End of EMMalloc() */\r
529 \r
530 /********************************************************************/\r
531 \r
532 int\r
533 EMMRealloc(int Handle, int Pages)\r
534 {\r
535     int     RtnCode = FALSE;\r
536 \r
537     if (!EMMSeg || (Pages < 0) || (Pages > 1020)) {\r
538         return (FALSE);\r
539     }\r
540     _asm {\r
541         mov     ah,0x51             /* change # of pages */\r
542         mov     bx,Pages\r
543         mov     dx,Handle\r
544         int     0x67\r
545         or      ah,ah\r
546         js      NoGo                /* returns 80 to 88 hex on error */\r
547     }\r
548     RtnCode = TRUE;\r
549 \r
550 NoGo:\r
551 \r
552     return(RtnCode);\r
553 }               /* End of EMMRealloc() */\r
554 \r
555 /********************************************************************/\r
556 \r
557 void\r
558 EMMFree(int Handle)\r
559 {\r
560     int     i, j;\r
561 \r
562     if (!EMMSeg) return;\r
563     for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
564     if (i >= MAXEMHANDLES) return;\r
565     j = 16;\r
566     while (j--) {\r
567         if (FreeEMHandle(ActiveEMList[i])) break;\r
568     }\r
569     ActiveEMList[i] = 0;\r
570 }               /* End of EMMFree() */\r
571 \r
572 /********************************************************************/\r
573 \r
574 int                                         /* EMM map for application */\r
575 MapEMM(int Handle, int Start, int Pages)\r
576 {\r
577     int     i;\r
578 \r
579     if (!EMMSeg) return(NOTREADY);\r
580     for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
581     if (i == MAXEMHANDLES) return (NO_DATA);\r
582     if ((GetNumPages(Handle) < Pages) || (Pages < 1) || (Pages > 4)) {\r
583         return (VALUE_OUTF_RANGE);\r
584     }\r
585     for (i = Start; i < Start + Pages; i++) {\r
586         if (!EMMap(Handle, i, i - Start)) return(NO_DATA);\r
587     }\r
588     return(SUCCESS);\r
589 }               /* End of MapEMM() */\r
590 \r
591 /********************************************************************/\r
592 \r
593 void                                        /* EMM unmap for application */\r
594 UnmapEMM(int Handle, int Start, int Pages)\r
595 {\r
596     int     i, j;\r
597 \r
598     if (!EMMSeg) return;\r
599     for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
600     if (i == MAXEMHANDLES) return;\r
601     j = Start + Pages;\r
602     if ((Pages < 1) || (j > 4)) return;\r
603 \r
604     for (i = Start; i < j; i++) {\r
605         EMMap(Handle, NONE, i);\r
606     }\r
607 }               /* End of UnmapEMM() */\r
608 \r
609 /********************************************************************/\r
610 \r
611 int                     /* EMM map for devices - saves EMM state */\r
612 UseEMM(int Handle, int Start, int Pages)\r
613 {\r
614     EMStateSave(Handle);\r
615     return(MapEMM(Handle, Start, Pages));\r
616 }               /* End of UseEMM() */\r
617 \r
618 /********************************************************************/\r
619 \r
620 void                    /* EMM unmap for devices - restores EMM state */\r
621 SaveEMM(int Handle, int Start, int Pages)\r
622 {\r
623     UnmapEMM(Handle, Start, Pages);\r
624     EMStateRestore(Handle);\r
625 }               /* End of SaveEMM() */\r
626 \r
627 /********************************************************************/\r
628 \r
629 static int\r
630 EMPresent(void)\r
631 {\r
632     int     i, Segment;\r
633     char    EMName[] = "EMMXXXX0";\r
634     char    *s, *t;\r
635 \r
636     _asm {                      /* can be replaced with getvect() */\r
637         push    es\r
638         mov     ax,0x3567       /* get vector for int 67h */\r
639         int     0x21\r
640         mov     ax,es\r
641         mov     Segment,ax\r
642         pop     es\r
643     }\r
644     t = MK_FP(Segment, 0x0A);   /* point to driver name */\r
645     s = EMName;\r
646     for (i = 0; (i < 8) && (*s++ == *t++); i++) ;   /* strncmp equivalent */\r
647 \r
648     if (i == 8) return(TRUE);\r
649     return(FALSE);\r
650 }               /*End of EMPresent() */\r
651 \r
652 /********************************************************************/\r
653 \r
654 static int\r
655 EMReady(void)\r
656 {\r
657     _asm {\r
658         mov     ah,0x40             /* get EM Manager Status */\r
659         int     0x67\r
660         or      ah,ah\r
661         jns     Ready               /* returns 80, 81, or 84 hex on error */\r
662     }\r
663     return(FALSE);\r
664 \r
665 Ready:\r
666     return(TRUE);\r
667 }               /* End of EMReady() */\r
668 \r
669 /********************************************************************/\r
670 \r
671 static unsigned int\r
672 GetEMMSeg(void)\r
673 {\r
674     unsigned int     EMSegment;\r
675 \r
676     _asm {\r
677         mov     ah,0x41             /* get EMM page frame segment */\r
678         int     0x67\r
679         or      ah,ah\r
680         js      NotReady            /* returns 80, 81, or 84 hex on error */\r
681         mov     EMSegment,bx\r
682     }\r
683     return(EMSegment);              /*lint !e530 */\r
684 \r
685 NotReady:\r
686     return(NOTREADY);\r
687 }               /* End of GetEMMSeg() */\r
688 \r
689 /********************************************************************/\r
690 \r
691 static int\r
692 GetEMHandle(int NumPages)\r
693 {\r
694     int     NewHandle;\r
695 \r
696     _asm {\r
697         mov     ah,0x43             /* get handle and allocate EM */\r
698         mov     bx,NumPages         /* number of 16K pages to allocate */\r
699         int     0x67\r
700         or      ah,ah               /* returns 80 to 89 hex on error */\r
701         js      NoHandle\r
702         mov     NewHandle,dx        /* retrieve handle */\r
703     }\r
704     return(NewHandle);\r
705 \r
706 NoHandle:\r
707     return(NO_DATA);\r
708 }               /* End of GetEMHandle() */\r
709 \r
710 /********************************************************************/\r
711 \r
712 static int\r
713 EMMap(int Handle, int LogPg, int PhyPg)\r
714 {\r
715     int     RtnCode = NO_DATA;\r
716 \r
717     _asm {\r
718         mov     ax,PhyPg            /* physical page: 0 - 3 in AL only */\r
719         mov     ah,0x44             /* map logical to physical page */\r
720         mov     bx,LogPg            /* logical page: 0 - 1020 */\r
721         mov     dx,Handle\r
722         int     0x67\r
723         or      ah,ah               /* returns 80 to 8B hex on error */\r
724         js      NoMapping\r
725     }\r
726     RtnCode = SUCCESS;\r
727 \r
728 NoMapping:\r
729     return(RtnCode);\r
730 }               /* End of EMMap() */\r
731 \r
732 /********************************************************************/\r
733 \r
734 static int\r
735 FreeEMHandle(int Handle)\r
736 {\r
737     _asm {\r
738         mov     ah,0x45             /* free handle and deallocate EM */\r
739         mov     dx,Handle\r
740         int     0x67\r
741         or      ah,ah               /* returns 80 to 86 hex on error */\r
742         js      NotFreed\r
743     }\r
744     return(SUCCESS);\r
745 \r
746 NotFreed:                           /* must retry if unsuccessful */\r
747     return(NO_DATA);\r
748 }               /* End of FreeEMHandle() */\r
749 \r
750 /********************************************************************/\r
751 \r
752 static int\r
753 GetNumPages(int Handle)\r
754 {\r
755     int     NumPages = 0;\r
756 \r
757     _asm {\r
758         mov     ah,0x4C             /* get allocated pages for Handle */\r
759         mov     dx,Handle\r
760         int     0x67\r
761         or      ah,ah               /* returns 80 to 84 hex on error */\r
762         js      BadHandle\r
763         mov     NumPages,bx\r
764     }\r
765 BadHandle:\r
766 \r
767     return(NumPages);\r
768 }               /* End of GetNumPages() */\r
769 \r
770 /********************************************************************/\r
771 \r
772 static int\r
773 EMStateSave(int Handle)\r
774 {\r
775     int     RtnCode = NO_MEMORY;\r
776     _asm {\r
777         mov     ah,0x47             /* save page map under Handle */\r
778         mov     dx,Handle\r
779         int     0x67\r
780         or      ah,ah\r
781         js      Unsaved             /* out of save space error */\r
782     }\r
783     RtnCode = SUCCESS;\r
784 \r
785 Unsaved:\r
786     return(RtnCode);\r
787 }               /* End of EMStateSave() */\r
788 \r
789 /********************************************************************/\r
790 \r
791 static void\r
792 EMStateRestore(int Handle)\r
793 {\r
794     _asm {\r
795         mov     ah,0x48             /* restore page map for Handle */\r
796         mov     dx,Handle\r
797         int     0x67                /* ignore error */\r
798     }\r
799 }               /* End of EMStateRestore() */\r
800 \r
801 /********************************************************************/\r
802 \r
803 /*\r
804    *********************************************************************\r
805    *********************************************************************\r
806 \r
807                                next file\r
808 \r
809    *********************************************************************\r
810    *********************************************************************\r
811 */\r
812 \r
813 // Cut this out as emm.c\r
814 \r
815 /*      File:       emm.c\r
816  *      Module:     All Modules\r
817  *      Author(s):  Chris Somers\r
818  *      Date:       December 1, 1992\r
819  *      Version:    V.1.1\r
820 \r
821         minor mods by Alex Russell to simplify\r
822 \r
823         Must use memory model with FAR code\r
824 \r
825  */\r
826 \r
827 \r
828 #include <stdio.h>\r
829 #include <stdlib.h>\r
830 #include <mem.h>\r
831 \r
832 #include "memory.h"\r
833 \r
834 void TransformData(char *pEmmData, unsigned int len)\r
835 {\r
836    while ( len )\r
837       {\r
838       (*pEmmData)++;\r
839       pEmmData++;\r
840 \r
841       len--;\r
842       }\r
843 }\r
844 \r
845 void main(void)\r
846 {\r
847    char    *pEmmData;\r
848    int     hEData;\r
849 \r
850    if ( OpenEMM() != SUCCESS )\r
851       {     // make sure we got EMM\r
852       printf("EMM unavailable.\n");\r
853       exit(1);\r
854       }\r
855    else\r
856       printf("Emm available\n");\r
857 \r
858    pEmmData = EMMalloc(&hEData, 6);  // get 6 * 16K bytes - 96K\r
859    if ( pEmmData == NULL )\r
860       {\r
861       printf("Not enough EMM or out of handles.\n");\r
862       exit(2);\r
863       }\r
864    else\r
865       printf("emm alloced OK\n");\r
866 \r
867 \r
868    printf("Map 1st 4 pages\n");\r
869    MapEMM(hEData, 0, 4);   // load 1st 4 pages into page frame: 0-3\r
870 \r
871    memset(pEmmData, 0x0e, 64000u);\r
872    UnmapEMM(hEData, 0, 4);          // not absolutely necessary\r
873    \r
874    printf("Map next 2 pages\n");\r
875    MapEMM(hEData, 4, 2);            // map last 2 pages: 4-5\r
876    memset(pEmmData, 0x0e, 32768u);\r
877 \r
878    MapEMM(hEData, 0, 4);\r
879    // do some stuff with the first 64K of file data.\r
880    printf("Transform data\n");\r
881    TransformData(pEmmData, 64000UL);\r
882    MapEMM(hEData, 4, 2);  // only unmaps 1st two pages of prior 64k mapping\r
883    // do stuff with remaining 32K of data\r
884    TransformData(pEmmData, 32768UL);\r
885    UnmapEMM(hEData, 0, 4);  // should unmap before freeing\r
886 \r
887    printf("Close emm\n");\r
888    EMMFree(hEData);     // finished with the file data\r
889    CloseEMM();\r
890 }\r
891 \r