1 // Author: Chris Somers
\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
7 // Author: Chris Somers
\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
13 AJR - I nuked all uneeded references from the code
\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
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
24 AJR - I modified these sources so this isn't neccessary - all
\r
25 references to TCPCOM have been deleted.
\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
31 AJR - I added memory.p to memory.c, and cleaned up memory.h so it can
\r
34 Please see emm.c for an example.
\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
42 AJR: I renamed returns.h to emmret.h and sizes.h to emmsize.h
\r
43 to avoid file name clashes.
\r
45 Here are some notes on the calls:
\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
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
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
75 Alexander J Russell wrote:
\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
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
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
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
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
122 >Could you send a quick overview of how you actually use emm mem in a dos
\r
125 -------------------- see emm.c for example ---------------
\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
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
135 Hope I didn't leave anything out. Email me again if any points aren't clear.
\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
146 *********************************************************************
\r
147 *********************************************************************
\r
151 *********************************************************************
\r
152 *********************************************************************
\r
155 // Cut this out as emmsize.h
\r
158 * Module: All Modules
\r
159 * Author(s): Chris Somers
\r
160 * Date: May 8, 1992
\r
164 #ifndef _EMMSIZES_DEF
\r
165 #define _EMMSIZES_DEF 1
\r
168 /* Module size constants */
\r
170 #define MAXACTIONS 29
\r
171 #define MAXCHANNELS 4
\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
184 #define MAXUTSSCRNS 2
\r
186 #define MAXUTSSCRNS 0
\r
189 #define MAXCAPTURE 1
\r
191 #define MAXCAPTURE 0
\r
194 #define MAXTCPDSCPTITEMS 16 /*max # of TCP connections*/
\r
196 #define FREEBUFF 1 /* CallIODevice flag for BuffSize arrays */
\r
197 #define DSCONLY 2 /* allocate a BufDscpt, only - no buffer */
\r
199 #define EMMPAGESIZE 0x4000 /* 16K EMM page size */
\r
200 #define SETUPLEN 32
\r
204 #define TITLELEN 128
\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
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
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
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
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
254 *********************************************************************
\r
255 *********************************************************************
\r
259 *********************************************************************
\r
260 *********************************************************************
\r
263 // AJR notes: some of these are not used by the emm code
\r
265 // Cut this out as emmret.h
\r
268 * Module: All Modules
\r
269 * Author(s): Chris Somers
\r
270 * Date: May 8, 1992
\r
274 #ifndef _EMM_RETURNS_DEF
\r
275 #define _EMM_RETURNS_DEF 1
\r
277 /* Module return values */
\r
279 /* Return Values */
\r
284 #define PRN_COMPLETE 5
\r
285 #define PRN_PROGRESS 4
\r
286 #define INCOMPLETE 3
\r
297 /* Start of Recoverable error codes */
\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
311 #define RECOVERABLE -1999 /* all above errors are recoverable */
\r
313 /* Start of Threadfatal error codes */
\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
322 #define THREADFATAL -2999 /* above errors force task to cancel */
\r
324 /* Start of Systemfatal error codes */
\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
344 #define SYSTEMFATAL -3999 /* above errors are fatal to system */
\r
349 *********************************************************************
\r
350 *********************************************************************
\r
354 *********************************************************************
\r
355 *********************************************************************
\r
358 // Cut this out as memory.h
\r
361 * Module: All Modules
\r
362 * Author(s): Chris Somers
\r
363 * Date: August 5, 1993
\r
366 modified by Alex Russell to simplify.
\r
370 #ifndef _MEMORY_DEF
\r
371 #define _MEMORY_DEF 1
\r
373 #include "emmret.h"
\r
374 #include "emmsize.h"
\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
394 *********************************************************************
\r
395 *********************************************************************
\r
399 *********************************************************************
\r
400 *********************************************************************
\r
405 * Module: All Modules
\r
406 * Author(s): Chris Somers
\r
407 * Date: December 1, 1992
\r
410 minor mods by Alex Russell to simplify
\r
412 Must use memory model with FAR code
\r
418 #if !defined(__LARGE__) && !defined(__COMPACT__) && !defined(__HUGE__)
\r
419 #error Invalid memory model for compiling MEMORY.C
\r
426 #include "memory.h"
\r
428 // static globals --------------------------------
\r
430 static int ActiveEMList[MAXEMHANDLES];
\r
431 static unsigned int EMMSeg;
\r
433 // forward declarations ---------------------------------
\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
446 /********************************************************************/
\r
450 if (!EMPresent() || !EMReady()) return(NOTREADY);
\r
451 if (!(EMMSeg = GetEMMSeg())) return(NOTREADY); /*lint !e720 */
\r
453 } /* End of OpenEMM() */
\r
455 /********************************************************************/
\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
470 } /* End of CloseEMM() */
\r
472 /********************************************************************/
\r
477 return((EMMSeg) ? TRUE : FALSE); /* successfully opened? */
\r
478 } /* End of EMMInstalled() */
\r
480 /********************************************************************/
\r
486 unsigned long RtnVal = 0UL;
\r
489 mov ah,0x42 /* get EMM free page count */
\r
492 js InternalError /* returns 80, 81, or 84 hex on error */
\r
493 mov Pages,bx /* number of unallocated 16K pages */
\r
495 RtnVal = ((unsigned long)Pages << 14); /* Pages * 16K rtns bytes*/
\r
500 } /* End of EMMCoreLeft() */
\r
502 /********************************************************************/
\r
505 EMMalloc(int *Handle, int Pages)
\r
508 char *RtnPtr = NULL;
\r
511 *Handle = NOTREADY;
\r
514 if ((Pages < 1) || (Pages > 1020)) {
\r
515 *Handle = VALUE_OUTF_RANGE;
\r
518 for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i]); i++) ;
\r
519 if (i == MAXEMHANDLES) {
\r
520 *Handle = NOFREEITEMS;
\r
523 if ((ActiveEMList[i] = GetEMHandle(Pages)) > 0) {
\r
524 RtnPtr = MK_FP(EMMSeg, 0);
\r
526 *Handle = ActiveEMList[i];
\r
527 return((void far *)RtnPtr);
\r
528 } /* End of EMMalloc() */
\r
530 /********************************************************************/
\r
533 EMMRealloc(int Handle, int Pages)
\r
535 int RtnCode = FALSE;
\r
537 if (!EMMSeg || (Pages < 0) || (Pages > 1020)) {
\r
541 mov ah,0x51 /* change # of pages */
\r
546 js NoGo /* returns 80 to 88 hex on error */
\r
553 } /* End of EMMRealloc() */
\r
555 /********************************************************************/
\r
558 EMMFree(int Handle)
\r
562 if (!EMMSeg) return;
\r
563 for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;
\r
564 if (i >= MAXEMHANDLES) return;
\r
567 if (FreeEMHandle(ActiveEMList[i])) break;
\r
569 ActiveEMList[i] = 0;
\r
570 } /* End of EMMFree() */
\r
572 /********************************************************************/
\r
574 int /* EMM map for application */
\r
575 MapEMM(int Handle, int Start, int Pages)
\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
585 for (i = Start; i < Start + Pages; i++) {
\r
586 if (!EMMap(Handle, i, i - Start)) return(NO_DATA);
\r
589 } /* End of MapEMM() */
\r
591 /********************************************************************/
\r
593 void /* EMM unmap for application */
\r
594 UnmapEMM(int Handle, int Start, int Pages)
\r
598 if (!EMMSeg) return;
\r
599 for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;
\r
600 if (i == MAXEMHANDLES) return;
\r
602 if ((Pages < 1) || (j > 4)) return;
\r
604 for (i = Start; i < j; i++) {
\r
605 EMMap(Handle, NONE, i);
\r
607 } /* End of UnmapEMM() */
\r
609 /********************************************************************/
\r
611 int /* EMM map for devices - saves EMM state */
\r
612 UseEMM(int Handle, int Start, int Pages)
\r
614 EMStateSave(Handle);
\r
615 return(MapEMM(Handle, Start, Pages));
\r
616 } /* End of UseEMM() */
\r
618 /********************************************************************/
\r
620 void /* EMM unmap for devices - restores EMM state */
\r
621 SaveEMM(int Handle, int Start, int Pages)
\r
623 UnmapEMM(Handle, Start, Pages);
\r
624 EMStateRestore(Handle);
\r
625 } /* End of SaveEMM() */
\r
627 /********************************************************************/
\r
633 char EMName[] = "EMMXXXX0";
\r
636 _asm { /* can be replaced with getvect() */
\r
638 mov ax,0x3567 /* get vector for int 67h */
\r
644 t = MK_FP(Segment, 0x0A); /* point to driver name */
\r
646 for (i = 0; (i < 8) && (*s++ == *t++); i++) ; /* strncmp equivalent */
\r
648 if (i == 8) return(TRUE);
\r
650 } /*End of EMPresent() */
\r
652 /********************************************************************/
\r
658 mov ah,0x40 /* get EM Manager Status */
\r
661 jns Ready /* returns 80, 81, or 84 hex on error */
\r
667 } /* End of EMReady() */
\r
669 /********************************************************************/
\r
671 static unsigned int
\r
674 unsigned int EMSegment;
\r
677 mov ah,0x41 /* get EMM page frame segment */
\r
680 js NotReady /* returns 80, 81, or 84 hex on error */
\r
683 return(EMSegment); /*lint !e530 */
\r
687 } /* End of GetEMMSeg() */
\r
689 /********************************************************************/
\r
692 GetEMHandle(int NumPages)
\r
697 mov ah,0x43 /* get handle and allocate EM */
\r
698 mov bx,NumPages /* number of 16K pages to allocate */
\r
700 or ah,ah /* returns 80 to 89 hex on error */
\r
702 mov NewHandle,dx /* retrieve handle */
\r
708 } /* End of GetEMHandle() */
\r
710 /********************************************************************/
\r
713 EMMap(int Handle, int LogPg, int PhyPg)
\r
715 int RtnCode = NO_DATA;
\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
723 or ah,ah /* returns 80 to 8B hex on error */
\r
730 } /* End of EMMap() */
\r
732 /********************************************************************/
\r
735 FreeEMHandle(int Handle)
\r
738 mov ah,0x45 /* free handle and deallocate EM */
\r
741 or ah,ah /* returns 80 to 86 hex on error */
\r
746 NotFreed: /* must retry if unsuccessful */
\r
748 } /* End of FreeEMHandle() */
\r
750 /********************************************************************/
\r
753 GetNumPages(int Handle)
\r
758 mov ah,0x4C /* get allocated pages for Handle */
\r
761 or ah,ah /* returns 80 to 84 hex on error */
\r
768 } /* End of GetNumPages() */
\r
770 /********************************************************************/
\r
773 EMStateSave(int Handle)
\r
775 int RtnCode = NO_MEMORY;
\r
777 mov ah,0x47 /* save page map under Handle */
\r
781 js Unsaved /* out of save space error */
\r
787 } /* End of EMStateSave() */
\r
789 /********************************************************************/
\r
792 EMStateRestore(int Handle)
\r
795 mov ah,0x48 /* restore page map for Handle */
\r
797 int 0x67 /* ignore error */
\r
799 } /* End of EMStateRestore() */
\r
801 /********************************************************************/
\r
804 *********************************************************************
\r
805 *********************************************************************
\r
809 *********************************************************************
\r
810 *********************************************************************
\r
813 // Cut this out as emm.c
\r
816 * Module: All Modules
\r
817 * Author(s): Chris Somers
\r
818 * Date: December 1, 1992
\r
821 minor mods by Alex Russell to simplify
\r
823 Must use memory model with FAR code
\r
829 #include <stdlib.h>
\r
832 #include "memory.h"
\r
834 void TransformData(char *pEmmData, unsigned int len)
\r
850 if ( OpenEMM() != SUCCESS )
\r
851 { // make sure we got EMM
\r
852 printf("EMM unavailable.\n");
\r
856 printf("Emm available\n");
\r
858 pEmmData = EMMalloc(&hEData, 6); // get 6 * 16K bytes - 96K
\r
859 if ( pEmmData == NULL )
\r
861 printf("Not enough EMM or out of handles.\n");
\r
865 printf("emm alloced OK\n");
\r
868 printf("Map 1st 4 pages\n");
\r
869 MapEMM(hEData, 0, 4); // load 1st 4 pages into page frame: 0-3
\r
871 memset(pEmmData, 0x0e, 64000u);
\r
872 UnmapEMM(hEData, 0, 4); // not absolutely necessary
\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
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
887 printf("Close emm\n");
\r
888 EMMFree(hEData); // finished with the file data
\r