· 9 years ago · Nov 23, 2016, 01:54 AM
1 length becomes the length of the non-standard size page for
2 any raw handle that Function 27 assigns.
3
4 Note............................................................
5 This note affects expanded memory manager implementors and
6 operating system developers only. Applications should not
7 use the following characteristic of the memory manager. An
8 application violating this rule will be incompatible with
9
10
11 EMM Functions 147
12
13
14
15
16
17 Function 27. Allocate Standard/Raw Pages
18 Allocate Raw Pages subfunction
19
20
21
22 future versions of Microsoft's operating systems and
23 environments.
24
25 To be compatible with this specification, an expanded memory
26 manager will provide a special handle which is available to
27 the operating system only. This handle will have a value of
28 0000h and will have a set of pages allocated to it when the
29 expanded memory manager driver installs. The pages that the
30 memory manager will automatically allocate to handle 0000h
31 are those that backfill conventional memory. Typically,
32 this backfill occurs between addresses 40000h (256K) and
33 9FFFFh (640K). However, the range can extend below and
34 above this limit if the hardware and memory manager have the
35 capability.
36
37 An operating system won't have to invoke Function 27 to
38 obtain this handle because it can assume the handle already
39 exists and is available for use immediately after the
40 expanded memory device driver installs. When an operating
41 system wants to use this handle, it uses the special handle
42 value of 0000h. The operating system will be able to invoke
43 any EMM function using this special handle value. To
44 allocate pages to this handle, the operating system need
45 only invoke Function 18 (Reallocate Pages).
46
47 There are two special cases for this handle:
48
49 1. Function 27 (Allocate Raw Pages subfunction). This
50 function must never return zero as a handle value.
51 Applications must always invoke Function 27 to allocate
52 pages and obtain a handle which identifies the pages
53 which belong to it. Since Function 27 never returns a
54 handle value of zero, an application will never gain
55 access to this special handle.
56
57 2. Function 6 (Deallocate Pages). If the operating system
58 uses it to deallocate the pages which are allocated to
59 this handle, the pages the handle owns will be returned
60 to the manager for use. But the handle will not be
61 available for reassignment. The manager should treat a
62 deallocate pages function request for this handle the
63 same as a reallocate pages function request, where the
64 number of pages to reallocate to this handle is zero.
65
66
67
68
69
70 EMM Functions 148
71
72
73
74
75
76 Function 27. Allocate Standard/Raw Pages
77 Allocate Raw Pages subfunction
78
79
80
81 CALLING PARAMETERS
82
83 AX = 5A01h
84 Contains the Allocate Raw Pages subfunction.
85
86 BX = num_of_raw_pages_to_alloc
87 Contains the number of raw pages the operating system
88 wishes to allocate.
89
90
91 RESULTS
92
93 These results are valid only if the status returned is zero.
94
95 DX = raw handle
96 Contains a unique EMM raw handle. The operating system
97 must use this EMM raw handle as a parameter in any
98 function that requires it. Up to 255 handles may be
99 obtained. (Both Function 4 and Function 27 must share
100 the same 255 handles).
101
102 For all functions using this raw handle, the length of
103 the physical and logical pages allocated to it may be
104 non-standard (that is, not 16K bytes).
105
106
107 REGISTERS MODIFIED
108
109 AX, DX
110
111
112 STATUS
113
114 AH = 0 SUCCESSFUL.
115 The manager has allocated the raw pages to an assigned
116 EMM raw handle.
117
118 AH = 80h NON-RECOVERABLE.
119 The manager detected a malfunction in the memory manager
120 software.
121
122 AH = 81h NON-RECOVERABLE.
123 The manager detected a malfunction in the expanded
124 memory hardware.
125
126
127
128
129 EMM Functions 149
130
131
132
133
134
135 Function 27. Allocate Standard/Raw Pages
136 Allocate Raw Pages subfunction
137
138
139
140 AH = 84h NON-RECOVERABLE.
141 The function code passed to the memory manager is not
142 defined.
143
144 AH = 85h RECOVERABLE.
145 All EMM handles are being used.
146
147 AH = 87h RECOVERABLE.
148 There aren't enough expanded memory raw pages present in
149 the system to satisfy the operating system's request.
150
151 AH = 88h RECOVERABLE.
152 There aren't enough unallocated raw pages to satisfy the
153 operating system's request.
154
155 AH = 8Fh NON-RECOVERABLE.
156 The subfunction parameter is invalid.
157
158
159 EXAMPLE
160
161 num_of_raw_pages_to_alloc DW ?
162 emm_raw_handle DW ?
163
164 MOV BX,num_of_raw_pages_to_alloc
165 MOV AX,5A01h ; load function code
166 INT 67h ; call the memory manager
167 OR AH,AH ; check EMM status
168 JNZ emm_err_handler ; jump to error handler
169 ; on error
170 MOV emm_raw_handle,DX ; save raw handle
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188 EMM Functions 150
189
190
191
192
193
194 Function 28. Alternate Map Register Set
195
196
197
198 Note............................................................
199 This function is for use by operating systems only. The
200 operating system can disable this function at any time.
201 Refer to Function 30 for a description of how an operating
202 system can enable or disable this function.
203
204
205 Design Considerations
206
207 The hardware support for the entire set of subfunctions
208 described is generally not present on every expanded memory
209 board from every vendor of expanded memory board products.
210 For some of the subfunctions, software emulation is provid-
211 ed. For other subfunctions, a certain protocol in their use
212 must be observed. The subfunctions for which this is most
213 crucial are those which address system DMA capabilities.
214
215
216 System DMA Capabilities & Expanded Memory Support of DMA
217
218 In a multitasking operating system, when one task is waiting
219 for DMA to complete, it is useful to be able to switch to
220 another task. This specification describes a capability
221 which may be designed into expanded memory boards to provide
222 DMA into memory regions which may be mapped out while the
223 DMA is occurring. For expanded memory boards that do not
224 provide this, it is crucial to understand that while DMA is
225 in progress into a region of mappable memory, the memory
226 mapping context cannot be changed. That is, all DMA action
227 must be complete before any remapping of pages can be done.
228
229
230 Expanded Memory Support of DMA Register Sets
231
232 Expanded memory boards which have DMA register sets could
233 support DMA into a region of mappable memory while the
234 memory mapping context is being switched. It is important
235 to realize that these DMA register sets are separate from
236 the alternate map register sets. An example of how an OS/E
237 might use DMA register sets follows:
238
239 Example 1
240
241 1. Allocate a DMA register set.
242
243 2. Get current register set.
244
245 3. Set the DMA register set.
246
247 EMM Functions 151
248
249
250
251
252
253 Function 28. Alternate Map Register Set
254
255
256
257 4. Map in the memory desired.
258
259 5. Get the DMA register set.
260
261 6. Set the original register set.
262
263 7. Assign the desired DMA channel to the DMA register set.
264
265 The preceding set of calls makes all DMA accesses for the
266 desired DMA channel get mapped through the current DMA
267 register set regardless of the current register set. In
268 other words, the DMA register set overrides the current
269 mapping register set for DMA operations on the DMA channel
270 specified. A DMA channel that is not assigned to a DMA
271 register set has all its DMA operations mapped through the
272 current mapping register set.
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306 EMM Functions 152
307
308
309
310
311
312 Function 28. Alternate Map Register Set
313 Get Alternate Map Register Set subfunction
314
315
316
317 Note............................................................
318 This function is for use by operating systems only. The
319 operating system can disable this function at any time.
320 Refer to Function 30 for a description of how an operating
321 system can enable or disable this function.
322
323
324 PURPOSE
325
326 The subfunction does one of two things depending on the map
327 register set which is active at the time this function is
328 invoked:
329
330 1. If the preceding Set Alternate Map Register Set call was
331 done with the alternate map register set equal to zero
332 (BL = 0), these points apply:
333
334 a. The context save area pointer saved within EMM by
335 the Set Alternate Map Register subfunction is
336 returned by this call. This pointer is always
337 returned for boards which do not supply alternate
338 mapping register sets.
339
340 b. If the context save area pointer returned is not
341 equal to zero, this subfunction copies the contents
342 of the mapping registers on each expanded memory
343 board in the system into the save area specified by
344 the pointer. The format of this save area is the
345 same as that returned by Function 15 (Get Page Map
346 subfunction). This is intended to simulate getting
347 an alternate map register set. Note that the memory
348 manager does not allocate the space for the context:
349 the operating system must do so.
350
351 c. If the context save area pointer returned is equal
352 to zero, this subfunction does not copy the contents
353 of the mapping registers on each expanded memory
354 board in the system into the save area specified by
355 the pointer.
356
357 d. The context save area pointer must have been
358 initialized by a previous Set Alternate Map Register
359 Set call. Note that the value of the context save
360 area pointer saved within EMM is zero immediately
361 after installation.
362
363
364
365 EMM Functions 153
366
367
368
369
370
371 Function 28. Alternate Map Register Set
372 Get Alternate Map Register Set subfunction
373
374
375
376 e. The context save area must be initialized by a
377 previous Get Page Map call (Function 15).
378
379 2. If the preceding Set Alternate Map Register Set call was
380 done with the alternate map register set greater than
381 zero (BL > 0), then the number of the alternate map
382 register set which is in use at the time that this
383 function is invoked is returned. The context save area
384 pointer is not returned in this case.
385
386
387 CALLING PARAMETERS
388
389 AX = 5B00h
390 Contains the Get Alternate Map Register Set subfunction.
391
392
393 RESULTS
394
395 These results are valid only if the status returned is zero.
396
397 If BL <> 0, current active alternate map register set number
398 Contains the alternate map register set which was active
399 at the time that this function was invoked.
400
401 ES:DI Unaffected.
402
403 If BL = 0
404 Indicates that a pointer to an area which contains the
405 state of all the map registers on all boards in the
406 system, and any additional information necessary to
407 restore the boards to their original state, has been
408 returned.
409
410 ES:DI = pointer to a map register context save area
411 Contains a pointer to an operating system supplied
412 context save area. The pointer is in standard seg-
413 ment:offset format. This pointer is always returned if
414 the expanded memory hardware does not supply alternate
415 mapping register sets.
416
417
418
419
420
421
422
423
424 EMM Functions 154
425
426
427
428
429
430 Function 28. Alternate Map Register Set
431 Get Alternate Map Register Set subfunction
432
433
434
435 The operating system first passes this pointer to the
436 memory manager whenever it invokes a Set Alternate Map
437 Register Set subfunction (the description follows). If
438 the OS/E invokes this function before invoking a Set
439 Alternate Map Register Set subfunction, this function
440 returns a pointer value of zero. The OS/E must have
441 allocated the space for the save area. However, the OS
442 must request that the memory manager initialize the
443 contents of this save area before it contains any useful
444 information.
445
446 The OS/E must initialize the save area it has allocated
447 by invoking Function 15 (Get Page Map subfunction).
448 After the OS/E has done this, the save area will contain
449 the state of all the map registers on all boards in the
450 system. The save area will also contain any additional
451 information necessary to restore the boards to their
452 original state when the operating system invokes a Set
453 Alternate Map Register Set subfunction.
454
455
456 REGISTERS MODIFIED
457
458 AX, BX, ES:DI
459
460
461 STATUS
462
463 AH = 0 SUCCESSFUL.
464 The manager got the alternate map register set.
465
466 AH = 80h NON-RECOVERABLE.
467 The manager detected a malfunction in the memory manager
468 software.
469
470 AH = 81h NON-RECOVERABLE.
471 The manager detected a malfunction in the expanded
472 memory hardware.
473
474 AH = 84h NON-RECOVERABLE.
475 The function code passed to the memory manager is not
476 defined.
477
478 AH = 8Fh NON-RECOVERABLE.
479 The subfunction parameter is invalid.
480
481
482
483 EMM Functions 155
484
485
486
487
488
489 Function 28. Alternate Map Register Set
490 Get Alternate Map Register Set subfunction
491
492
493
494 AH = A4h NON-RECOVERABLE.
495 The operating system denied access to this function.
496 The function cannot be used at this time.
497
498
499 EXAMPLE
500
501 alt_map_reg_set DB ?
502 context_save_area_ptr_seg DW ?
503 context_save_area_ptr_offset DW ?
504
505 MOV AX,5B00h ; load function code
506 INT 67h ; call the memory manager
507 OR AH,AH ; check EMM status
508 JNZ emm_err_handler ; jump to error handler
509 ; on error
510 MOV alt_map_reg_set,BL
511 TEST BL,BL
512 JNZ no_ptr_returned
513
514 MOV context_save_area_ptr_seg,ES ; save pointer values
515 MOV context_save_area_ptr_offset,DI
516
517 no_ptr_returned:
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542 EMM Functions 156
543
544
545
546
547
548 Function 28. Alternate Map Register Set
549 Set Alternate Map Register Set subfunction
550
551
552
553 Note............................................................
554 This function is for use by operating systems only. The
555 operating system can disable this function at any time.
556 Refer to Function 30 for a description of how an operating
557 system can enable or disable this function.
558
559
560 PURPOSE
561
562 The subfunction does one of two things, depending on the map
563 register set specified:
564
565 1. If the alternate map register set specified is zero, map
566 register set zero is activated. If the map register
567 context restore area pointer is not equal to zero, the
568 contents of the restore area pointed to by ES:DI are
569 copied into register set zero on each expanded memory
570 board in the system. If the pointer is equal to zero,
571 the contents are not copied.
572
573 Regardless of its value, the map register context
574 restore area pointer is saved within the memory manager.
575 It will be used during the Get Alternate Map Register
576 Set subfunction.
577
578 The operating system must supply the pointer to the
579 area. This subfunction is intended to simulate setting
580 an alternate map register set. Note that the operating
581 system must allocate the space for the context. The
582 memory manager saves the context save area pointer
583 internally.
584
585 2. If the alternate map register set specified is not zero,
586 the alternate map register set specified is activated.
587 The restore area, which the operating system is pointing
588 to, is not used.
589
590
591 CALLING PARAMETERS
592
593 AX = 5B01h
594 Contains the Set Alternate Map Register Set subfunction.
595
596
597
598
599
600
601 EMM Functions 157
602
603
604
605
606
607 Function 28. Alternate Map Register Set
608 Set Alternate Map Register Set subfunction
609
610
611
612 BL = new alternate map register set number
613 Contains the number of the alternate map register set
614 which is to be activated.
615
616 If BL <> 0
617 A pointer to a map register context restore area is
618 not required and the contents of ES:DI is unaffected
619 and ignored. The alternate map register set
620 specified in BL is activated if the board supports
621 it.
622
623 If BL = 0
624 A pointer to an area which contains the state of all
625 the map registers on all boards in the system, and
626 any additional information necessary to restore the
627 boards to their original state, has been passed in
628 ES:DI.
629
630 ES:DI = pointer to a map register context restore area
631 Contains a pointer to an OS/E supplied map register
632 context restore area. The pointer is in standard
633 segment:offset format. This pointer must always be
634 passed if the expanded memory hardware does not supply
635 alternate mapping register sets.
636
637 The memory manager must save this pointer whenever the
638 OS/E invokes this function. The OS/E must have allo-
639 cated the space for the restore area. Additionally, the
640 contents of this restore area must have been initialized
641 by the memory manager before it will contain any useful
642 information. The OS/E initializes the restore area it
643 has allocated by invoking Function 15 (Get Page Map
644 subfunction). After the OS/E has done this, the restore
645 area will contain the state of the map registers on all
646 boards in the system, and any additional information
647 necessary to restore the boards to their original state
648 when the operating system invokes a Set Alternate Map
649 Register Set subfunction.
650
651
652 REGISTERS MODIFIED
653
654 AX
655
656
657
658
659
660 EMM Functions 158
661
662
663
664
665
666 Function 28. Alternate Map Register Set
667 Set Alternate Map Register Set subfunction
668
669
670
671 STATUS
672
673 AH = 0 SUCCESSFUL.
674 The manager set the alternate map register set.
675
676 AH = 80h NON-RECOVERABLE.
677 The manager detected a malfunction in the memory manager
678 software.
679
680 AH = 81h NON-RECOVERABLE.
681 The manager detected a malfunction in the expanded
682 memory hardware.
683
684 AH = 84h NON-RECOVERABLE.
685 The function code passed to the memory manager is not
686 defined.
687
688 AH = 8Fh NON-RECOVERABLE.
689 The subfunction parameter is invalid.
690
691 AH = 9Ah NON-RECOVERABLE.
692 Alternate map register sets are supported, but the
693 alternate map register set specified is not supported.
694
695 AH = 9Ch NON-RECOVERABLE.
696 Alternate map register sets are not supported, and the
697 alternate map register set specified is not zero.
698
699 AH = 9Dh NON-RECOVERABLE.
700 Alternate map register sets are supported, but the
701 alternate map register set specified is either not
702 defined or not allocated.
703
704 AH = A3h NON-RECOVERABLE.
705 The contents of the source array have been corrupted, or
706 the pointer passed to the subfunction is invalid.
707
708 AH = A4h NON-RECOVERABLE.
709 The operating system has denied access to this function.
710 The function cannot be used at this time.
711
712
713
714
715
716
717
718
719 EMM Functions 159
720
721
722
723
724
725 Function 28. Alternate Map Register Set
726 Set Alternate Map Register Set subfunction
727
728
729
730 EXAMPLE
731
732 alt_map_reg_set DB ?
733 context_restore_area_ptr_seg DW ?
734 context_restore_area_ptr_offset DW ?
735
736 MOV AX,5B01h ; load function code
737 MOV BL,alt_map_reg_set
738 TEST BL,BL
739 JZ no_ptr_passed
740
741 MOV ES,context_restore_area_ptr_seg
742 MOV DI,context_restore_area_ptr_offset
743
744 no_ptr_passed:
745
746 INT 67h ; call the memory manger
747 OR AH,AH ; check EMM status
748 JNZ emm_err_handler ; jump to error handler
749 ; on error
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778 EMM Functions 160
779
780
781
782
783
784 Function 28. Alternate Map Register Set
785 Get Alternate Map Save Array Size subfunction
786
787
788
789 Note............................................................
790 This function is for use by operating systems only. The
791 operating system can disable this function at any time.
792 Refer to Function 30 for a description of how an operating
793 system can enable or disable this function.
794
795
796 PURPOSE
797
798 This subfunction returns the storage requirements for the
799 map register context save area referenced by the other
800 subfunctions.
801
802
803 CALLING PARAMETERS
804
805 AX = 5B02h
806 Contains the Get Alternate Map Save Array Size subfunc-
807 tion.
808
809
810 RESULTS
811
812 These results are valid only if the status returned is zero.
813
814 DX = size_of_array
815 Contains the number of bytes that will be transferred to
816 the memory area supplied by an operating system whenever
817 an operating system requests the Get, Set, or Get and
818 Set subfunction.
819
820
821 REGISTERS MODIFIED
822
823 AX, DX
824
825
826 STATUS
827
828 AH = 0 SUCCESSFUL.
829 The manager has returned the array size.
830
831 AH = 80h NON-RECOVERABLE.
832 The manager detected a malfunction in the memory manager
833 software.
834
835
836
837 EMM Functions 161
838
839
840
841
842
843 Function 28. Alternate Map Register Set
844 Get Alternate Map Save Array Size subfunction
845
846
847
848 AH = 81h NON-RECOVERABLE.
849 The manager detected a malfunction in the expanded
850 memory hardware.
851
852 AH = 84h NON-RECOVERABLE.
853 The function code passed to the memory manager is not
854 defined.
855
856 AH = 8Fh NON-RECOVERABLE.
857 The subfunction parameter is invalid.
858
859 AH = A4h NON-RECOVERABLE.
860 The operating system has denied access to this function.
861 The function cannot be used at this time.
862
863
864 EXAMPLE
865
866 size_of_array DW ?
867
868 MOV AX,5B02h ; load function code
869 INT 67h ; call the memory manager
870 OR AH,AH ; check EMM status
871 JNZ emm_err_handler ; jump to error handler on error
872 MOV size_of_array,DX ; save size of array
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896 EMM Functions 162
897
898
899
900
901
902 Function 28. Alternate Map Register Set
903 Allocate Alternate Map Register Set subfunction
904
905
906
907 Note............................................................
908 This function is for use by operating systems only. The
909 operating system can disable this function at any time.
910 Refer to Function 30 for a description of how an operating
911 system can enable or disable this function.
912
913
914 PURPOSE
915
916 The Allocate Alternate Map Register Set subfunction gets the
917 number of an alternate map register set for an operating
918 system if an alternate map register set is currently
919 available for use. If the hardware does not support
920 alternate map register sets, an alternate map register set
921 number of zero will be returned.
922
923 The alternate map register set allocated may be referred to
924 by this number when using the Get or Set Alternate Map
925 Register Set subfunctions. The operating system can use
926 these subfunctions to switch map contexts very rapidly on
927 expanded memory boards with alternate map register sets.
928
929 This subfunction copies the currently active alternate map
930 register set's contents into the newly allocated alternate
931 map register set's mapping registers. This is done so that
932 when the OS/E performs a Set Alternate Map Register Set
933 subfunction the memory mapped before the allocation of the
934 new alternate map will be available for reading and writing.
935 This function does not actually change the alternate map
936 register set in use, but in addition to allocating a new
937 alternate map register set, it prepares the new alternate
938 map register set for a subsequent Set Alternate Map Register
939 Set subfunction.
940
941
942 CALLING PARAMETERS
943
944 AX = 5B03h
945 Contains the Allocate Alternate Map Register Set
946 subfunction.
947
948
949
950
951
952
953
954
955 EMM Functions 163
956
957
958
959
960
961 Function 28. Alternate Map Register Set
962 Allocate Alternate Map Register Set subfunction
963
964
965
966 RESULTS
967
968 These results are valid only if the status returned is zero.
969
970 BL = alternate map register set number
971 Contains the number of an alternate map register set.
972 If there are no alternate map register sets supported by
973 the hardware, a zero will be returned. In this case,
974 the Get Alternate Map function (Function 28) should be
975 invoked in order to obtain a pointer to a map register
976 context save area. The OS/E must supply this area. The
977 save area is necessary because the hardware doesn't
978 support alternate map register sets.
979
980
981 REGISTERS MODIFIED
982
983 AX, BX
984
985
986 STATUS
987
988 AH = 0 SUCCESSFUL.
989 The manager has returned the alternate map register set
990 number.
991
992 AH = 80h NON-RECOVERABLE.
993 The manager detected a malfunction in the memory manager
994 software.
995
996 AH = 81h NON-RECOVERABLE.
997 The manager detected a malfunction in the expanded
998 memory hardware.
999
1000 AH = 84h NON-RECOVERABLE.
1001 The function code passed to the memory manager is not
1002 defined.
1003
1004 AH = 8Fh NON-RECOVERABLE.
1005 The subfunction parameter is invalid.
1006
1007 AH = 9Bh NON-RECOVERABLE.
1008 Alternate map register sets are supported. However, all
1009 alternate map register sets are currently allocated.
1010
1011
1012
1013
1014 EMM Functions 164
1015
1016
1017
1018
1019
1020 Function 28. Alternate Map Register Set
1021 Allocate Alternate Map Register Set subfunction
1022
1023
1024
1025 AH = A4h NON-RECOVERABLE.
1026 The operating system has denied access to this function.
1027 The function cannot be used at this time.
1028
1029
1030 EXAMPLE
1031
1032 alt_map_reg_num DB ?
1033
1034 MOV AX,5B03h ; load function code
1035 INT 67h ; call the memory manager
1036 OR AH,AH ; check EMM status
1037 JNZ emm_err_handler ; jump to error handler on error
1038 MOV alt_map_reg_num,BL ; save number of
1039 ; alternate map register set
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073 EMM Functions 165
1074
1075
1076
1077
1078
1079 Function 28. Alternate Map Register Set
1080 Deallocate Alternate Map Register Set subfunction
1081
1082
1083
1084 Note............................................................
1085 This function is for use by operating systems only. The
1086 operating system can disable this function at any time.
1087 Refer to Function 30 for a description of how an operating
1088 system can enable or disable this function.
1089
1090
1091 PURPOSE
1092
1093 The Deallocate Alternate Map Register Set subfunction
1094 returns the alternate map register set to the memory manager
1095 for future use. The memory manager may reallocate the
1096 alternate map register set when needed.
1097
1098 This subfunction also makes the mapping context of the
1099 alternate map register specified unavailable for reading or
1100 writing (unmapping). This protects the pages previously
1101 mapped in an alternate map register set by making them
1102 inaccessible. Note that the current alternate map register
1103 set cannot be deallocated. This makes all memory which was
1104 currently mapped into conventional and expanded memory
1105 inaccessible.
1106
1107
1108 CALLING PARAMETERS
1109
1110 AX = 5B04h
1111 Contains the Deallocate Alternate Map Register Set
1112 subfunction.
1113
1114 BL = alternate register set number
1115 Contains the number of the alternate map register set to
1116 deallocate. Map register set zero cannot be allocated
1117 or deallocated. However, if alternate map register set
1118 zero is specified and this subfunction is invoked, no
1119 error will be returned. The function invocation is
1120 ignored in this case.
1121
1122
1123 REGISTERS MODIFIED
1124
1125 AX
1126
1127
1128
1129
1130
1131
1132 EMM Functions 166
1133
1134
1135
1136
1137
1138 Function 28. Alternate Map Register Set
1139 Deallocate Alternate Map Register Set subfunction
1140
1141
1142
1143 STATUS
1144
1145 AH = 0 SUCCESSFUL.
1146 The manager has deallocated the alternate map register
1147 set.
1148
1149 AH = 80h NON-RECOVERABLE.
1150 The manager detected a malfunction in the memory manager
1151 software.
1152
1153 AH = 81h NON-RECOVERABLE.
1154 The manager detected a malfunction in the expanded
1155 memory hardware.
1156
1157 AH = 84h NON-RECOVERABLE.
1158 The function code passed to the memory manager is not
1159 defined.
1160
1161 AH = 8Fh NON-RECOVERABLE.
1162 The subfunction parameter is invalid.
1163
1164 AH = 9Ch NON-RECOVERABLE.
1165 Alternate map register sets are not supported and the
1166 alternate map register set specified is not zero.
1167
1168 AH = 9Dh NON-RECOVERABLE.
1169 Alternate map register sets are supported, but the
1170 alternate map register set specified is either not
1171 defined or not allocated.
1172
1173 AH = A4h NON-RECOVERABLE.
1174 The operating system has denied access to this function.
1175 The function cannot be used at this time.
1176
1177
1178 EXAMPLE
1179
1180 alternate_map_reg_set DB ?
1181
1182 MOV BL,alternate_map_reg_set ; specify alternate map
1183 ; register set
1184 MOV AX,5B04h ; load function code
1185 INT 67h ; call the memory manager
1186 OR AH,AH ; check EMM status
1187 JNZ emm_err_handler ; jump to error handler
1188 ; on error
1189
1190
1191 EMM Functions 167
1192
1193
1194
1195
1196
1197 Function 28. Alternate Map Register Set
1198 Allocate DMA Register Set subfunction
1199
1200
1201
1202 Note............................................................
1203 This function is for use by operating systems only. The
1204 operating system can disable this function at any time.
1205 Refer to Function 30 for a description of how an operating
1206 system can enable or disable this function.
1207
1208
1209 PURPOSE
1210
1211 The Allocate DMA Register Set subfunction gets the number of
1212 a DMA register set for an OS/E, if a DMA register set is
1213 currently available for use. If the hardware does not
1214 support DMA register sets, a DMA register set number of zero
1215 will be returned.
1216
1217 In a multitasking operating system, when one task is waiting
1218 for DMA to complete, it is useful to be able to switch to
1219 another task. However, if the DMA is being mapped through
1220 the current register set, the switching cannot occur. That
1221 is, all DMA action must be complete before any remapping of
1222 pages can be done.
1223
1224 The operating system would initiate a DMA operation on a
1225 specific DMA channel using a specific alternate map register
1226 set. This alternate map register set would not be used
1227 again, by the operating system or an application, until
1228 after the DMA operation is complete. The operating system
1229 guarantees this by not changing the contents of the alter-
1230 nate map register set, or allowing an application to change
1231 the contents of the alternate map register set, for the
1232 duration of the DMA operation.
1233
1234
1235 CALLING PARAMETERS
1236
1237 AX = 5B05h
1238 Contains the Allocate DMA Register Set subfunction.
1239
1240
1241 RESULTS
1242
1243 These results are valid only if the status returned is zero.
1244
1245 BL = DMA register set number
1246 Contains the number of a DMA register set. If there are
1247 no DMA register sets supported by the hardware, a zero
1248 will be returned.
1249
1250 EMM Functions 168
1251
1252
1253
1254
1255
1256 Function 28. Alternate Map Register Set
1257 Allocate DMA Register Set subfunction
1258
1259
1260
1261 REGISTERS MODIFIED
1262
1263 AX, BX
1264
1265
1266 STATUS
1267
1268 AH = 0 SUCCESSFUL.
1269 The manager has allocated the DMA register set.
1270
1271 AH = 80h NON-RECOVERABLE.
1272 The manager detected a malfunction in the memory manager
1273 software.
1274
1275 AH = 81h NON-RECOVERABLE.
1276 The manager detected a malfunction in the expanded
1277 memory hardware.
1278
1279 AH = 84h NON-RECOVERABLE.
1280 The function code passed to the memory manager is not
1281 defined.
1282
1283 AH = 8Fh NON-RECOVERABLE.
1284 The subfunction parameter is invalid.
1285
1286 AH = 9Bh NON-RECOVERABLE.
1287 DMA register sets are supported. However, all DMA
1288 register sets are currently allocated.
1289
1290 AH = A4h NON-RECOVERABLE.
1291 Access to this function has been denied by the operating
1292 system. The function cannot be used at this time.
1293
1294
1295 EXAMPLE
1296
1297 DMA_reg_set_number DB ?
1298
1299 MOV AX,5B05h ; load function code
1300 INT 67h ; call memory manager
1301 OR AH,AH ; check EMM status
1302 JNZ emm_err_handler ; jump to error handler
1303 ; on error
1304 MOV DMA_reg_set_number,BL ; save number of DMA
1305 ; register set
1306
1307
1308
1309 EMM Functions 169
1310
1311
1312
1313
1314
1315 Function 28. Alternate Map Register Set
1316 Enable DMA on Alternate Map Register Set subfunction
1317
1318
1319
1320 Note............................................................
1321 This function is for use by operating systems only. The
1322 operating system can disable this function at any time.
1323 Refer to Function 30 for a description of how an operating
1324 system can enable or disable this function.
1325
1326
1327 PURPOSE
1328
1329 This subfunction allows DMA accesses on a specific DMA
1330 channel to be associated with a specific alternate map
1331 register set. In a multitasking operating system, when a
1332 task is waiting for the completion of DMA, it is useful to
1333 be able to switch to another task until the DMA operation
1334 completes.
1335
1336 Any DMA on the specified channel will go through the speci-
1337 fied DMA register set regardless of the current register
1338 set. If a DMA channel is not assigned to a DMA register
1339 set, DMA for that channel will be mapped through the current
1340 register set.
1341
1342
1343 CALLING PARAMETERS
1344
1345 AX = 5B06h
1346 Contains the Enable DMA on Alternate Map Register Set
1347 subfunction.
1348
1349 BL = DMA register set number
1350 Contains the number of the alternate map register set to
1351 be used for DMA operations on the DMA channel specified
1352 by DL. If the alternate map register set specified is
1353 zero, no special action will be taken on DMA accesses
1354 for the DMA channel specified.
1355
1356 DL = DMA channel number
1357 Contains the DMA channel which is to be associated with
1358 the DMA map register set specified in BL.
1359
1360
1361 REGISTERS MODIFIED
1362
1363 AX
1364
1365
1366
1367
1368 EMM Functions 170
1369
1370
1371
1372
1373
1374 Function 28. Alternate Map Register Set
1375 Enable DMA on Alternate Map Register Set subfunction
1376
1377
1378
1379 STATUS
1380
1381 AH = 0 SUCCESSFUL.
1382 The manager has enabled DMA on the DMA register set and
1383 the DMA channel specified.
1384
1385 AH = 80h NON-RECOVERABLE.
1386 The manager detected a malfunction in the memory manager
1387 software.
1388
1389 AH = 81h NON-RECOVERABLE.
1390 The manager detected a malfunction in the expanded
1391 memory hardware.
1392
1393 AH = 84h NON-RECOVERABLE.
1394 The function code passed to the memory manager is not
1395 defined.
1396
1397 AH = 8Fh NON-RECOVERABLE.
1398 The subfunction parameter is invalid.
1399
1400 AH = 9Ah NON-RECOVERABLE.
1401 Alternate DMA register sets are supported, but the
1402 alternate DMA register set specified is not supported.
1403
1404 AH = 9Ch NON-RECOVERABLE.
1405 Alternate DMA register sets are not supported, and the
1406 DMA register set specified is not zero.
1407
1408 AH = 9Dh NON-RECOVERABLE.
1409 DMA register sets are supported, but the DMA register
1410 set specified is either not defined or not allocated.
1411
1412 AH = 9Eh NON-RECOVERABLE.
1413 Dedicated DMA channels are not supported.
1414
1415 AH = 9Fh NON-RECOVERABLE.
1416 Dedicated DMA channels are supported, but the DMA
1417 channel specified is not supported.
1418
1419 AH = A4h NON-RECOVERABLE.
1420 The operating system has denied access to this function.
1421 The function cannot be used at this time.
1422
1423
1424
1425
1426
1427 EMM Functions 171
1428
1429
1430
1431
1432
1433 Function 28. Alternate Map Register Set
1434 Enable DMA on Alternate Map Register Set subfunction
1435
1436
1437
1438 EXAMPLE
1439
1440 alt_map_reg_set DB ?
1441 DMA_channel_num DB ?
1442
1443 MOV BL,alt_map_reg_set
1444 MOV DL,DMA_channel_num
1445 MOV AX,5B06h ; load function code
1446 INT 67h ; call the memory manager
1447 OR AH,AH ; check EMM status
1448 JNZ emm_err_handler ; jump to error handler on error
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486 EMM Functions 172
1487
1488
1489
1490
1491
1492 Function 28. Alternate Map Register Set
1493 Disable DMA on Alternate Map Register Set subfunction
1494
1495
1496
1497 Note............................................................
1498 This function is for use by operating systems only. The
1499 operating system can disable this function at any time.
1500 Refer to Function 30 for a description of how an operating
1501 system can enable or disable this function.
1502
1503
1504 PURPOSE
1505
1506 This subfunction disables DMA accesses for all DMA channels
1507 which were associated with a specific alternate map register
1508 set.
1509
1510
1511 CALLING PARAMETERS
1512
1513 AX = 5B07h
1514 Contains the Disable DMA on Alternate Map Register Set
1515 subfunction.
1516
1517 BL = alternate register set number
1518 Contains the number of the DMA register set for which
1519 all operations are to be disabled. If the alternate map
1520 register set specified is zero, no action will be taken.
1521
1522
1523 REGISTERS MODIFIED
1524
1525 AX
1526
1527
1528 STATUS
1529
1530 AH = 0 SUCCESSFUL.
1531 The manager has disabled DMA operations on the alternate
1532 DMA register set.
1533
1534 AH = 80h NON-RECOVERABLE.
1535 The manager detected a malfunction in the memory manager
1536 software.
1537
1538 AH = 81h NON-RECOVERABLE.
1539 The manager detected a malfunction in the expanded
1540 memory hardware.
1541
1542
1543
1544
1545 EMM Functions 173
1546
1547
1548
1549
1550
1551 Function 28. Alternate Map Register Set
1552 Disable DMA on Alternate Map Register Set subfunction
1553
1554
1555
1556 AH = 84h NON-RECOVERABLE.
1557 The function code passed to the memory manager is not
1558 defined.
1559
1560 AH = 8Fh NON-RECOVERABLE.
1561 The subfunction parameter is invalid.
1562
1563 AH = 9Ah NON-RECOVERABLE.
1564 Alternate DMA register sets are supported, but the
1565 alternate DMA register set specified is not supported.
1566
1567 AH = 9Ch NON-RECOVERABLE.
1568 Alternate DMA register sets are not supported, and the
1569 DMA register set specified is not zero.
1570
1571 AH = 9Dh NON-RECOVERABLE.
1572 DMA register sets are supported, but the DMA register
1573 set specified is either not defined or not allocated.
1574
1575 AH = 9Eh NON-RECOVERABLE.
1576 Dedicated DMA channels are not supported.
1577
1578 AH = 9Fh NON-RECOVERABLE.
1579 Dedicated DMA channels are supported, but the DMA
1580 channel specified is not supported.
1581
1582 AH = A4h NON-RECOVERABLE.
1583 The operating system has denied access to this function.
1584 The function cannot be used at this time.
1585
1586
1587 EXAMPLE
1588
1589 DMA_reg_set DB ?
1590
1591 MOV BL,DMA_reg_set
1592 MOV AX,5B07h ; load function code
1593 INT 67h ; call the memory manager
1594 OR AH,AH ; check EMM status
1595 JNZ emm_err_handler ; jump to error handler on error
1596
1597
1598
1599
1600
1601
1602
1603
1604 EMM Functions 174
1605
1606
1607
1608
1609
1610 Function 28. Alternate Map Register Set
1611 Deallocate DMA Register Set subfunction
1612
1613
1614
1615 Note............................................................
1616 This function is for use by operating systems only. The
1617 operating system can disable this function at any time.
1618 Refer to Function 30 for a description of how an operating
1619 system can enable or disable this function.
1620
1621
1622 PURPOSE
1623
1624 The Deallocate DMA Register Set subfunction deallocates the
1625 specified DMA register set.
1626
1627
1628 CALLING PARAMETERS
1629
1630 AX = 5B08h
1631 Contains the Deallocate DMA Register Set subfunction.
1632
1633 BL = DMA register set number
1634 Contains the number of the DMA register set which should
1635 not be used for DMA operations any longer. The DMA
1636 register set would have been previously allocated and
1637 enabled for DMA operations on a specific DMA channel.
1638 If the DMA register set specified is zero, no action
1639 will be taken.
1640
1641
1642 REGISTERS MODIFIED
1643
1644 AX
1645
1646
1647 STATUS
1648
1649 AH = 0 SUCCESSFUL.
1650 The manager has deallocated the DMA register set.
1651
1652 AH = 80h NON-RECOVERABLE.
1653 The manager detected a malfunction in the memory manager
1654 software.
1655
1656 AH = 81h NON-RECOVERABLE.
1657 The manager detected a malfunction in the expanded
1658 memory hardware.
1659
1660
1661
1662
1663 EMM Functions 175
1664
1665
1666
1667
1668
1669 Function 28. Alternate Map Register Set
1670 Deallocate DMA on Alternate Map Register Set subfunction
1671
1672
1673
1674 AH = 84h NON-RECOVERABLE.
1675 The function code passed to the memory manager is not
1676 defined.
1677
1678 AH = 8Fh NON-RECOVERABLE.
1679 The subfunction parameter is invalid.
1680
1681 AH = 9Ch NON-RECOVERABLE.
1682 DMA register sets are not supported, and the DMA
1683 register set specified is not zero.
1684
1685 AH = 9Dh NON-RECOVERABLE.
1686 DMA register sets are supported, but the DMA register
1687 set specified is either not defined or not allocated.
1688
1689 AH = A4h NON-RECOVERABLE.
1690 The operating system has denied access to this function.
1691 The function cannot be used at this time.
1692
1693
1694 EXAMPLE
1695
1696 DMA_reg_set_num DB ?
1697
1698 MOV BL,DMA_reg_set_num
1699 MOV AX,5B08h ; load function code
1700 INT 67h ; call the memory manager
1701 OR AH,AH ; check EMM status
1702 JNZ emm_err_handler ; jump to error handler on error
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722 EMM Functions 176
1723
1724
1725
1726
1727
1728 Function 29. Prepare Expanded Memory Hardware For Warm Boot
1729
1730
1731
1732 PURPOSE
1733
1734 This function prepares the expanded memory hardware for an
1735 impending warm boot. This function assumes that the next
1736 operation that the operating system performs is a warm boot
1737 of the system. In general, this function will effect the
1738 current mapping context, the alternate register set in use,
1739 and any other expanded memory hardware dependencies which
1740 need to be initialized at boot time. If an application
1741 decides to map memory below 640K, the application must trap
1742 all possible conditions leading to a warm boot and invoke
1743 this function before performing the warm boot itself.
1744
1745
1746 CALLING PARAMETERS
1747
1748 AH = 5Ch
1749 Contains the Prepare Expanded Memory Hardware for Warm
1750 Boot function.
1751
1752
1753 REGISTERS MODIFIED
1754
1755 AX
1756
1757
1758 STATUS
1759
1760 AH = 0 SUCCESSFUL.
1761 The manager has prepared the expanded memory hardware
1762 for a warm boot.
1763
1764 AH = 80h NON-RECOVERABLE.
1765 The manager detected a malfunction in the memory manager
1766 software.
1767
1768 AH = 81h NON-RECOVERABLE.
1769 The manager detected a malfunction in the expanded
1770 memory hardware.
1771
1772 AH = 84h NON-RECOVERABLE.
1773 The function code passed to the memory manager is not
1774 defined.
1775
1776
1777
1778
1779
1780
1781 EMM Functions 177
1782
1783
1784
1785
1786
1787 Function 29. Prepare Expanded Memory Hardware for Warm Boot
1788
1789
1790
1791 EXAMPLE
1792
1793 MOV AH,5Ch ; load function code
1794 INT 67h ; call the memory manager
1795 OR AH,AH ; check EMM status
1796 JNZ emm_err_handler ; jump to error handler on error
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840 EMM Functions 178
1841
1842
1843
1844
1845
1846 Function 30. Enable/Disable OS/E Function Set Functions
1847 Enable OS/E Function Set subfunction
1848
1849
1850
1851 Note............................................................
1852 This function is for use by operating systems only. The
1853 operating system can disable this function at any time.
1854
1855
1856 PURPOSE
1857
1858 This subfunction provides an OS/E with the ability to enable
1859 all programs or device drivers to use the OS/E specific
1860 functions. The capability is provided only for an OS/E
1861 which manages regions of mappable conventional memory and
1862 cannot permit programs to use any of the functions which
1863 affect mappable conventional memory regions, but must be
1864 able to use these functions itself. When an OS/E disables
1865 these functions and a program attempts to use them, the
1866 memory manager returns a status to the program indicating
1867 that the OS/E has denied the program access to the function.
1868 In other words, the functions will not work when disabled.
1869 However, all programs may use them when enabled.
1870
1871 The OS/E (Operating System/Environment) functions this
1872 subfunction enables are:
1873
1874 Function 26. Get Expanded Memory Hardware Information.
1875 Function 28. Alternate Map Register Sets.
1876 Function 30. Enable/Disable Operating System Functions.
1877
1878 It appears contradictory that the OS/E can re-enable these
1879 functions when the function which re-enables them is itself
1880 disabled. An overview of the process follows.
1881
1882 The memory manager enables all the OS/E specific functions,
1883 including this one, when it is loaded. The OS/E gets
1884 exclusive access to these functions by invoking either of
1885 the Enable/Disable OS/E Function Set subfunctions before any
1886 other software does.
1887
1888 On the first invocation of either of these subfunctions, the
1889 memory manager returns an access_key which the OS/E must use
1890 in all future invocations of either of these subfunctions.
1891 The memory manager does not require the access_key on the
1892 first invocation of the Enable/Disable OS/E Function Set
1893 subfunctions.
1894
1895
1896
1897
1898
1899 EMM Functions 179
1900
1901
1902
1903
1904
1905 Function 30. Enable/Disable OS/E Function Set Functions
1906 Enable OS/E Function Set subfunction
1907
1908
1909
1910 On all subsequent invocations, the access_key is required
1911 for either the Enable or Disable OS/E Function Set subfunc-
1912 tions. Since the access_key is returned only on the first
1913 invocation of the Enable/Disable OS/E Function Set subfunc-
1914 tions, and presumably the OS/E is the first software to
1915 invoke this function, only the OS/E obtains a copy of this
1916 key. The memory manager must return an access key with a
1917 random value, a fixed value key defeats the purpose of
1918 providing this level of security for an OS/E.
1919
1920
1921 CALLING PARAMETERS
1922
1923 AX = 5D00h
1924 Contains the Enable OS/E Function Set subfunction.
1925
1926 BX,CX = access_key
1927 Required on all function invocations after the first.
1928 The access_key value returned by the first function
1929 invocation is required.
1930
1931
1932 RESULTS
1933
1934 These results are valid only if the status returned is zero.
1935
1936 BX,CX = access_key
1937 Returned only on the first function invocation, the
1938 memory manager returns a random valued key which will be
1939 required thereafter for the execution of this function.
1940 On all invocations after the first, this key is not
1941 returned. Neither BX nor CX is affected after the first
1942 time this function is invoked.
1943
1944
1945 REGISTERS MODIFIED
1946
1947 AX, BX, CX
1948
1949
1950 STATUS
1951
1952 AH = 0 SUCCESSFUL.
1953 The operating system function set has been enabled.
1954
1955
1956
1957
1958 EMM Functions 180
1959
1960
1961
1962
1963
1964 Function 30. Enable/Disable OS/E Function Set Functions
1965 Enable OS/E Function Set subfunction
1966
1967
1968
1969 AH = 80h NON-RECOVERABLE.
1970 The manager detected a malfunction in the memory manager
1971 software.
1972
1973 AH = 81h NON-RECOVERABLE.
1974 The manager detected a malfunction in the expanded
1975 memory hardware.
1976
1977 AH = 84h NON-RECOVERABLE.
1978 The function code passed to the memory manager is not
1979 defined.
1980
1981 AH = 8Fh NON-RECOVERABLE.
1982 The subfunction parameter is invalid.
1983
1984 AH = A4h NON-RECOVERABLE.
1985 The operating system has denied access to this function.
1986 The function cannot be used at this time. The value of
1987 the key which was passed to this function does not
1988 entitle the program to execute this function.
1989
1990
1991 EXAMPLE
1992
1993 First invocation
1994
1995 access_key DW 2 DUP (?)
1996
1997 MOV AX,5D00h ; load function code
1998 INT 67h ; call the memory manager
1999 OR AH,AH ; check EMM status
2000 JNZ emm_err_handler ; jump to error handler on error
2001 MOV access_key[0],BX
2002 MOV access_key[2],CX
2003
2004
2005 All invocations after the first
2006
2007 access_key DW 2 DUP (?)
2008
2009 MOV BX,access_key[0]
2010 MOV CX,access_key[2]
2011 MOV AX,5D00h ; load function code
2012 INT 67h ; call the memory manager
2013 OR AH,AH ; check EMM status
2014 JNZ emm_err_handler ; jump to error handler on error
2015
2016
2017 EMM Functions 181
2018
2019
2020
2021
2022
2023 Function 30. Enable/Disable OS/E Function Set Functions
2024 Disable OS/E Function Set subfunction
2025
2026
2027
2028 Note............................................................
2029 This function is for use by operating systems only. The
2030 operating system can disable this function at any time.
2031
2032
2033 PURPOSE
2034
2035 This subfunction provides an OS/E with the ability to
2036 disable all programs or device drivers from using the OS/E
2037 specific functions. The capability is provided only for an
2038 OS/E which manages regions of mappable conventional memory
2039 and cannot permit programs to use any of the functions which
2040 would affect mappable conventional memory regions. When an
2041 OS/E disables these functions and a program attempts to use
2042 them, the memory manager returns a status to the program
2043 indicating that the OS/E has denied the program access to
2044 the function. In other words, the functions will not work
2045 when disabled.
2046
2047 The OS/E (Operating System) functions which are disabled by
2048 this subfunction are:
2049
2050 Function 26. Get Expanded Memory Hardware Information.
2051 Function 28. Alternate Map Register Sets.
2052 Function 30. Enable/Disable Operating System Functions.
2053
2054
2055 CALLING PARAMETERS
2056
2057 AX = 5D01h
2058 Contains the Disable OS/E Function Set subfunction.
2059
2060 BX,CX = access_key
2061 Required on all function invocations after the first.
2062 The access_key value returned by the first function
2063 invocation is required.
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076 EMM Functions 182
2077
2078
2079
2080
2081
2082 Function 30. Enable/Disable OS/E Function Set Functions
2083 Disable OS/E Function Set subfunction
2084
2085
2086
2087 RESULTS
2088
2089 These results are valid only if the status returned is zero.
2090
2091 BX,CX = access_key
2092 Returned only on the first function invocation, the
2093 memory manager returns a random valued key which will be
2094 required thereafter for the execution of this function.
2095 On all invocations after the first, this key is not
2096 returned. Neither BX nor CX is affected after the first
2097 time this function is invoked.
2098
2099
2100 REGISTERS MODIFIED
2101
2102 AX, BX, CX
2103
2104
2105 STATUS
2106
2107 AH = 0 SUCCESSFUL.
2108 The operating system function set has been disabled.
2109
2110 AH = 80h NON-RECOVERABLE.
2111 The manager detected a malfunction in the memory manager
2112 software.
2113
2114 AH = 81h NON-RECOVERABLE.
2115 The manager detected a malfunction in the expanded
2116 memory hardware.
2117
2118 AH = 84h NON-RECOVERABLE.
2119 The function code passed to the memory manager is not
2120 defined.
2121
2122 AH = 8Fh NON-RECOVERABLE.
2123 The subfunction parameter is invalid.
2124
2125 AH = A4h NON-RECOVERABLE.
2126 The operating system has denied access to this function.
2127 The function cannot be used at this time. The value of
2128 the key which was passed to this function does not
2129 entitle the program to execute this function.
2130
2131
2132
2133
2134
2135 EMM Functions 183
2136
2137
2138
2139
2140
2141 Function 30. Enable/Disable OS/E Function Set Functions
2142 Disable OS/E Function Set subfunction
2143
2144
2145
2146 EXAMPLE
2147
2148 First Function invocation
2149
2150 access_key DW 2 DUP (?)
2151
2152 MOV AX,5D01h ; load function code
2153 INT 67h ; call the memory manager
2154 OR AH,AH ; check EMM status
2155 JNZ emm_err_handler ; jump to error handler on error
2156 MOV access_key[0],BX
2157 MOV access_key[2],CX
2158
2159
2160 All invocations after the first
2161
2162 access_key DW 2 DUP (?)
2163
2164 MOV BX,access_key[0]
2165 MOV CX,access_key[2]
2166 MOV AX,5D01h ; load function code
2167 INT 67h ; call the memory manager
2168 OR AH,AH ; check EMM status
2169 JNZ emm_err_handler ; jump to error handler on error
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194 EMM Functions 184
2195
2196
2197
2198
2199
2200 Function 30. Enable/Disable OS/E Function Set Functions
2201 Return Access Key subfunction
2202
2203
2204
2205 Note............................................................
2206 This function is for use by operating systems only. The
2207 operating system can disable this function at any time.
2208
2209
2210 PURPOSE
2211
2212 This subfunction provides an OS/E with the ability to return
2213 the access key to the memory manager. Returning the access
2214 key to the memory manager places the memory manager in the
2215 state it is in at installation time (regarding the use of
2216 the OS/E function set and the access key). That is, access
2217 to the OS/E function set is enabled. Upon execution of the
2218 next enable/disable OS/E function set subfunction, the
2219 access key will once again be returned.
2220
2221
2222 CALLING PARAMETERS
2223
2224 AX = 5D02h
2225 Contains the Return Access Key subfunction.
2226
2227 BX,CX = access_key
2228 Required on all function invocations. The access_key
2229 value returned by the first function invocation of the
2230 enable or disable subfunctions is required.
2231
2232
2233 REGISTERS MODIFIED
2234
2235 AX
2236
2237
2238 STATUS
2239
2240 AH = 0 SUCCESSFUL.
2241 The access key has been returned to the memory manager.
2242
2243 AH = 80h NON-RECOVERABLE.
2244 The manager detected a malfunction in the memory manager
2245 software.
2246
2247 AH = 81h NON-RECOVERABLE.
2248 The manager detected a malfunction in the expanded
2249 memory hardware.
2250
2251
2252
2253 EMM Functions 185
2254
2255
2256
2257
2258
2259 Function 30. Enable/Disable OS/E Function Set Functions
2260 Return Access Key subfunction
2261
2262
2263
2264 AH = 84h NON-RECOVERABLE.
2265 The function code passed to the memory manager is not
2266 defined.
2267
2268 AH = 8Fh NON-RECOVERABLE.
2269 The subfunction parameter is invalid.
2270
2271 AH = A4h NON-RECOVERABLE.
2272 The operating system has denied access to this function.
2273 The function cannot be used at this time. The value of
2274 the key which was passed to this function does not
2275 entitle the program to execute this function.
2276
2277
2278 EXAMPLE
2279
2280 access_key DW 2 DUP (?)
2281
2282 MOV BX,access_key[0]
2283 MOV CX,access_key[2]
2284 MOV AX,5D02h ; load function code
2285 INT 67h ; call the memory manager
2286 OR AH,AH ; check EMM status
2287 JNZ emm_err_handler ; jump to error handler on error
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312 EMM Functions 186
2313
2314
2315
2316
2317
2318 Appendix A
2319 FUNCTION AND STATUS CODE CROSS REFERENCE TABLES
2320
2321
2322
2323 This appendix contains two cross reference tables: one
2324 lists the function codes and the status codes they return;
2325 the other lists the status codes and the functions that
2326 return them.
2327
2328
2329 Table A-1. Function and Status Code Cross Reference
2330 ----------------------------------------------------------------
2331
2332 Function Status Description
2333
2334 ----------------------------------------------------------------
2335
2336 40h 00h, 80h, 81h, 84h Get Memory Manager Status
2337
2338 41h 00h, 80h, 81h, 84h Get Page Frame Segment Address
2339
2340 42h 00h, 80h, 81h, 84h Get Unallocated Page Count
2341
2342 43h 00h, 80h, 81h, 84h Allocate Pages
2343 85h, 87h, 88h, 89h
2344
2345 44h 00h, 80h, 81h, 83h Map/Unmap Handle Page
2346 84h, 8Ah, 8Bh
2347
2348 45h 00h, 80h, 81h, 83h Deallocate Pages
2349 84h, 86h
2350
2351 46h 00h, 80h, 81h, 84h Get EMM Version
2352
2353 47h 00h, 80h, 81h, 83h Save Page Map
2354 84h, 8Ch, 8Dh
2355
2356 48h 00h, 80h, 81h, 83h Restore Page Map
2357 84h, 8Eh
2358
2359 49h Reserved
2360
2361 4Ah Reserved
2362
2363 4Bh 00h, 80h, 81h, 84h Get EMM Handle Count
2364
2365 4Ch 00h, 80h, 81h, 83h Get EMM Handle Pages
2366 84h
2367
2368 4Dh 00h, 80h, 81h, 84h Get All EMM Handle Pages
2369
2370
2371 Cross Reference Tables 187
2372
2373
2374
2375
2376
2377 Table A-1. Function and Status Code Cross Reference (continued)
2378 ----------------------------------------------------------------
2379
2380 Function Status Description
2381
2382 ----------------------------------------------------------------
2383
2384 4E00h 00h, 80h, 81h, 84h Get Page Map
2385 8Fh
2386
2387 4E01h 00h, 80h, 81h, 84h Set Page Map
2388 8Fh, A3h
2389
2390 4E02h 00h, 80h, 81h, 84h Get & Set Page Map
2391 8Fh, A3h
2392
2393 4E03h 00h, 80h, 81h, 84h Get Size of Page Map Save Array
2394 8Fh
2395
2396 4F00h 00h, 80h, 81h, 84h Get Partial Page Map
2397 8Bh, 8Fh, A3h
2398
2399 4F01h 00h, 80h, 81h, 84h Set Partial Page Map
2400 8Fh, A3h
2401
2402 4F02h 00h, 80h, 81h, 84h Get Size of Partial Page Map Array
2403 8Bh, 8Fh
2404
2405 5000h 00h, 80h, 81h, 83h Map/Unmap Multiple Handle Pages
2406 84h, 8Ah, 8Bh, 8Fh (physical page number mode)
2407
2408 5001h 00h, 80h, 81h, 83h Map/Unmap Multiple Handle Pages
2409 84h, 8Ah, 8Bh, 8Fh (segment address mode)
2410
2411 51h 00h, 80h, 81h, 83h Reallocate Pages
2412 84h, 87h, 88h
2413
2414 5200h 00h, 80h, 81h, 83h Get Handle Attribute
2415 84h, 8Fh, 91h
2416
2417 5201h 00h, 80h, 81h, 83h Set Handle Attribute
2418 84h, 8Fh, 90h, 91h
2419
2420 5202h 00h, 80h, 81h, 84h Get Handle Attribute Capability
2421 8Fh
2422
2423 5300h 00h, 80h, 81h, 83h Get Handle Name
2424 84h, 8Fh
2425
2426 5301h 00h, 80h, 81h, 83h Set Handle Name
2427 84h, 8Fh, A1h
2428
2429
2430 Cross Reference Tables 188
2431
2432
2433
2434
2435
2436 Table A-1. Function and Status Code Cross Reference (continued)
2437 ----------------------------------------------------------------
2438
2439 Function Status Description
2440
2441 ----------------------------------------------------------------
2442
2443 5400h 00h, 80h, 81h, 84h Get Handle Directory
2444 8Fh
2445
2446 5401h 00h, 80h, 81h, 84h Search for Named Handle
2447 8Fh, A0h, A1h
2448
2449 5402h 00h, 80h, 81h, 84h Get Total Handles
2450 8Fh
2451
2452 5500h 00h, 80h, 81h, 83h Alter Page Map & Jump (Physical
2453 84h, 8Ah, 8Bh, 8Fh page mode)
2454
2455 5501h 00h, 80h, 81h, 83h Alter Page Map & Jump (Segment
2456 84h, 8Ah, 8Bh, 8Fh address mode)
2457
2458 5600h 00h, 80h, 81h, 83h Alter Page Map & Call (Physical
2459 84h, 8Ah, 8Bh, 8Fh page mode)
2460
2461 5601h 00h, 80h, 81h, 83h Alter Page Map & Call (Segment
2462 84h, 8Ah, 8Bh, 8Fh address mode)
2463
2464 5602h 00h, 80h, 81h, 84h Get Alter Page Map & Call Stack
2465 8Fh Space Size
2466
2467 5700h 00h, 80h, 81h, 83h Move Memory Region
2468 84h, 8Ah, 8Fh, 92h
2469 93h, 94h, 95h, 96h
2470 98h, A2h
2471
2472 5701h 00h, 80h, 81h, 83h Exchange Memory Region
2473 84h, 8Ah, 8Fh, 93h
2474 94h, 95h, 96h, 97h
2475 98h, A2h
2476
2477 5800h 00h, 80h, 81h, 84h Get Mappable Physical Address
2478 8Fh Array
2479
2480 5801h 00h, 80h, 81h, 84h Get Mappable Physical Address
2481 8Fh Array Entries
2482
2483 5900h 00h, 80h, 81h, 84h Get Expanded Memory Hardware
2484 8Fh, A4h Information
2485
2486 5901h 00h, 80h, 81h, 84h Get Unallocated Raw Page Count
2487 8Fh
2488
2489 Cross Reference Tables 189
2490
2491
2492
2493
2494
2495 Table A-1. Function and Status Code Cross Reference (continued)
2496 ----------------------------------------------------------------
2497
2498 Function Status Description
2499
2500 ----------------------------------------------------------------
2501
2502 5A00h 00h, 80h, 81h, 84h Allocate Standard Pages
2503 85h, 87h, 88h, 8Fh
2504
2505 5A01h 00h, 80h, 81h, 84h Allocate Raw Pages
2506 85h, 87h, 88h, 8Fh
2507
2508 5B00h 00h, 80h, 81h, 84h Get Alternate Map Register Set
2509 8Fh, A4h
2510
2511 5B01h 00h, 80h, 81h, 84h Set Alternate Map Register Set
2512 8Fh, 9Ah, 9Ch, 9Dh
2513 A3h, A4h
2514
2515 5B02h 00h, 80h, 81h, 84h Get Alternate Map Save Array Size
2516 8Fh, A4h
2517
2518 5B03h 00h, 80h, 81h, 84h Allocate Alternate Map Register
2519 8Fh, 9Bh, A4h Set
2520
2521 5B04h 00h, 80h, 81h, 84h Deallocate Alternate Map Register
2522 8Fh, 9Ch, 9Dh, A4h Set
2523
2524 5B05h 00h, 80h, 81h, 84h Allocate DMA Register Set
2525 8Fh, 9Bh, A4h
2526
2527 5B06h 00h, 80h, 81h, 84h Enable DMA on Alternate Map
2528 8Fh, 9Ah, 9Ch, 9Dh Register Set
2529 9Eh, 9Fh, A4h
2530
2531 5B07h 00h, 80h, 81h, 84h Disable DMA on Alternate Map
2532 8Fh, 9Ah, 9Ch, 9Dh Register Set
2533 9Eh, 9Fh, A4h
2534
2535 5B08h 00h, 80h, 81h, 84h Deallocate DMA Register Set
2536 8Fh, 9Ch, 9Dh, A4h
2537
2538 5Ch 00h, 80h, 81h, 84h Prepare Expanded Memory Hardware
2539 for Warmboot
2540
2541 5D00h 00h, 80h, 81h, 84h Enable Operating System Function
2542 8Fh, A4h Set
2543
2544 5D01h 00h, 80h, 81h, 84h Disable Operating System Function
2545 8Fh, A4h Set
2546
2547
2548 Cross Reference Tables 190
2549
2550
2551
2552
2553
2554 Table A-1. Function and Status Code Cross Reference (continued)
2555 ----------------------------------------------------------------
2556
2557 Function Status Description
2558
2559 ----------------------------------------------------------------
2560
2561 5D02h 00h, 80h, 81h, 84h Return Operating System Access Key
2562 8Fh, A4h
2563 ----------------------------------------------------------------
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607 Cross Reference Tables 191
2608
2609
2610
2611
2612
2613 Table A-2. Status and Function Code Cross Reference
2614 ----------------------------------------------------------------
2615
2616 Status Function Description
2617
2618 ----------------------------------------------------------------
2619
2620 00h All The function completed normally.
2621
2622 80h All The memory manager has detected a
2623 malfunction in the expanded memory
2624 software. A condition has been
2625 detected which would not have
2626 occurred if the memory manager had
2627 been operating correctly.
2628
2629 81h All The memory manager has detected a
2630 malfunction in the expanded memory
2631 hardware. A condition has been
2632 detected which would not occur if the
2633 memory hardware were working correct-
2634 ly. Diagnostics should be run on the
2635 expanded memory system to determine
2636 the source of the problem.
2637
2638 82h None This error code is not returned in
2639 version 3.2 of the memory manager or
2640 above. In earlier versions of the
2641 memory manager this code meant a
2642 "busy" status. This status indicated
2643 that the memory manager was already
2644 processing an expanded memory request
2645 when the current request was made and
2646 is unable to process another request.
2647 In versions 3.2 of the memory manager
2648 and above, the memory manager is
2649 never "busy" and can always honor
2650 requests.
2651
2652 83h 44h, 45h, 47h, 48h The memory manager can not find the
2653 4Ch, 5000h, 5001h handle specified. The program has
2654 51h, 5200h, 5201h probably corrupted its specified
2655 5300h, 5301h handle. The memory manager does not
2656 5500h, 5501h have any information pertaining to
2657 5600h, 5601h the specified handle. The program
2658 5700h, 5701h has probably corrupted its handle.
2659
2660 84h All The function code passed to the
2661 manager is not currently defined.
2662 Function codes in the range 40h
2663 through 5Dh are currently defined.
2664
2665
2666 Cross Reference Tables 192
2667
2668
2669
2670
2671
2672 Table A-2. Status and Function Code Cross Reference (continued)
2673 ----------------------------------------------------------------
2674
2675 Status Function Description
2676
2677 ----------------------------------------------------------------
2678
2679 85h 43h, 5A00h, 5A01h No handles are currently available.
2680 All assignable handles are currently
2681 in use. The program may re-request
2682 the assignment of a handle in the
2683 hope that another program has
2684 released a handle. The maximum
2685 number of handles that may be
2686 supported is 255.
2687
2688 86h 45h A mapping context restoration error
2689 has been detected. This error occurs
2690 when a program attempts to return a
2691 handle and there is still a "mapping
2692 context" on the context stack for the
2693 indicated handle. A program can
2694 recover from this error by restoring
2695 the mapping context before returning
2696 the handle.
2697
2698 87h 43h, 51h, 5A00h, The number of total pages that are
2699 5A01h available in the system is insuffi-
2700 cient to honor the request. The
2701 program can recover from this
2702 condition by requesting fewer pages.
2703
2704 88h 43h, 51h, 5A00h, The number of unallocated pages
2705 5A01h currently available is insufficient
2706 to honor the allocation request. The
2707 program can recover from this
2708 condition by re-posting the request
2709 or by requesting fewer pages.
2710
2711 89h 43h A Function 4 (Allocate Pages) request
2712 has been made specifying zero pages.
2713 Zero pages cannot be assigned to a
2714 handle with Function 4 (Allocate
2715 Pages). If it is necessary to assign
2716 zero pages to a handle, Function 27
2717 (Allocate Standard Pages and Allocate
2718 Raw Pages subfunctions) may be used.
2719
2720
2721
2722
2723
2724
2725 Cross Reference Tables 193
2726
2727
2728
2729
2730
2731 Table A-2. Status and Function Code Cross Reference (continued)
2732 ----------------------------------------------------------------
2733
2734 Status Function Description
2735
2736 ----------------------------------------------------------------
2737
2738 8Ah 44h, 5000h, 5001h The logical page to map into memory
2739 5500h, 5501h is out of the range of logical pages
2740 5600h, 5601h which are allocated to the handle.
2741 5700h, 5701h The program can recover from this
2742 condition by attempting to map a
2743 logical page which is within the
2744 bounds for the handle.
2745
2746 8Bh 44h, 4F00h, 4F02h One or more of the physical pages is
2747 5000h, 5001h out of the range of allowable
2748 5600h, 5601h physical pages. Physical page
2749 5500h, 5501 numbers are numbered zero-relative.
2750 The program can recover from this
2751 condition by mapping at a physical
2752 page which is in the range from zero
2753 to three.
2754
2755 8Ch 47h The mapping register context save
2756 area is full. The program can
2757 recover from this condition by
2758 attempting to save the mapping
2759 registers again.
2760
2761 8Dh 47h The mapping register context stack
2762 already has a context associated with
2763 the handle. The program has at-
2764 tempted to save the mapping register
2765 context when there was already a
2766 context for the handle on the stack.
2767 The program can recover from this
2768 condition by not attempting to save
2769 the context again (this assumes the
2770 mapping register context on the stack
2771 for the handle is correct).
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784 Cross Reference Tables 194
2785
2786
2787
2788
2789
2790 Table A-2. Status and Function Code Cross Reference (continued)
2791 ----------------------------------------------------------------
2792
2793 Status Function Description
2794
2795 ----------------------------------------------------------------
2796
2797 8Eh 48h The mapping register context stack
2798 does not have a context associated
2799 with the handle. The program has
2800 attempted to restore the mapping
2801 register context when there was no
2802 context for the handle on the stack.
2803 The program can recover from this
2804 condition by not attempting to
2805 restore the context again (this
2806 assumes the current mapping register
2807 context is correct).
2808
2809 8Fh All functions The subfunction parameter passed to
2810 requiring the function is not defined.
2811 subfunction codes
2812
2813 90h 5201h The attribute type is undefined.
2814
2815 91h 5200h, 5201h The system configuration does not
2816 support non-volatility.
2817
2818 92h 5700h The source and destination expanded
2819 memory regions have the same handle
2820 and overlap. This is valid for a
2821 move. The move has been completed
2822 and the destination region has a full
2823 copy of the source region. However,
2824 at least a portion of the source
2825 region has been overwritten by the
2826 move. Note that the source and
2827 destination expanded memory regions
2828 with different handles will never
2829 physically overlap because the
2830 different handles specify totally
2831 different regions of expanded memory.
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843 Cross Reference Tables 195
2844
2845
2846
2847
2848
2849 Table A-2. Status and Function Code Cross Reference (continued)
2850 ----------------------------------------------------------------
2851
2852 Status Function Description
2853
2854 ----------------------------------------------------------------
2855
2856 93h 5700h, 5701h The length of the specified source or
2857 destination expanded memory region
2858 exceeds the length of the expanded
2859 memory region allocated to the
2860 specified source or destination
2861 handle. There are insufficient pages
2862 allocated to this handle to move/ex-
2863 change a region of the size speci-
2864 fied. The program can recover from
2865 this condition by attempting to
2866 allocate additional pages to the
2867 destination or source handle or by
2868 reducing the specified length.
2869 However, if the application program
2870 has allocated as much expanded memory
2871 as it thought it needed, this may be
2872 a program error and is therefore not
2873 recoverable.
2874
2875 94h 5700h, 5701h The conventional memory region and
2876 expanded memory region overlap. This
2877 is invalid, the conventional memory
2878 region cannot overlap the expanded
2879 memory region.
2880
2881 95h 5700h, 5701h The offset within the logical page
2882 exceeds the length of the logical
2883 page. The initial source or destina-
2884 tion offsets within an expanded
2885 memory region must be between 0 and
2886 the (length of a logical page - 1) or
2887 16383 (3FFFh).
2888
2889 96h 5700h, 5701h Region length exceeds 1M-byte limit.
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902 Cross Reference Tables 196
2903
2904
2905
2906
2907
2908 Table A-2. Status and Function Code Cross Reference (continued)
2909 ----------------------------------------------------------------
2910
2911 Status Function Description
2912
2913 ----------------------------------------------------------------
2914
2915 97h 5701h The source and destination expanded
2916 memory regions have the SAME handle
2917 AND overlap. This is invalid; the
2918 source and destination expanded
2919 memory regions cannot have the same
2920 handle and overlap when they are
2921 being exchanged. Note that the
2922 source and destination expanded
2923 memory regions with different handles
2924 will never physically overlap because
2925 the different handles specify totally
2926 different regions of expanded memory.
2927
2928 98h 5700h, 5701h The memory source and destination
2929 types are undefined/not supported.
2930
2931 9Ah 5B01h, 5B06h Alternate map register sets are
2932 5B07h supported, but the alternate map
2933 register set specified is not
2934 supported.
2935
2936 9Bh 5B03h, 5B05h Alternate map/DMA register sets are
2937 supported. However, all alternate
2938 map/DMA register sets are currently
2939 allocated.
2940
2941 9Ch 5B01h, 5B04h Alternate map/DMA register sets are
2942 5B06h, 5B07h not supported, and the alternate
2943 5B08h map/DMA register set specified is not
2944 zero.
2945
2946 9Dh 5B01h, 5B04h Alternate map/DMA register sets are
2947 5B06h, 5B07h supported, but the alternate map
2948 5B08h register set specified is not
2949 defined, not allocated, or is the
2950 currently allocated map register set.
2951
2952 9Eh 5B06h, 5B07h Dedicated DMA channels are not
2953 supported.
2954
2955 9Fh 5B06h, 5B07h Dedicated DMA channels are supported.
2956 But the DMA channel specified is not
2957 supported.
2958
2959
2960
2961 Cross Reference Tables 197
2962
2963
2964
2965
2966
2967 Table A-2. Status and Function Code Cross Reference (continued)
2968 ----------------------------------------------------------------
2969
2970 Status Function Description
2971
2972 ----------------------------------------------------------------
2973
2974 A0h 5401h No corresponding handle value could
2975 be found for the handle name speci-
2976 fied.
2977
2978 A1h 5301h, 5401h A handle with this name already
2979 exists. The specified handle was not
2980 assigned a name.
2981
2982 A2h 5700h, 5701h An attempt was made to "wrap around"
2983 the 1M-byte address space during the
2984 move/exchange. The source starting
2985 address together with the length of
2986 the region to be moved/exchanged
2987 exceeds 1M bytes. No data was
2988 moved/exchanged.
2989
2990 A3h 4E01h, 4E02h The contents of the data structure
2991 4F00h, 4F01h passed to the function have either
2992 5B01h been corrupted or are meaningless.
2993
2994 A4h 5900h, 5B00h The operating system has denied
2995 5B01h, 5B02h access to this function. The
2996 5B03h, 5B04h function cannot be used at this time.
2997 5B05h, 5B06h
2998 5B07h, 5B08h
2999 5D00h, 5D01h
3000 5D02h
3001
3002 ----------------------------------------------------------------
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020 Cross Reference Tables 198
3021
3022
3023
3024
3025
3026 Appendix B
3027 TESTING FOR THE PRESENCE OF THE EXPANDED MEMORY MANAGER
3028
3029
3030
3031 Before an application program can use the Expanded Memory
3032 Manager, it must determine whether DOS has loaded the
3033 manager. This appendix describes two methods your program
3034 can use to test for the presence of the memory manager and
3035 how to choose the correct one for your situation.
3036
3037 The first method uses the DOS "open handle" technique; the
3038 second method uses the DOS "get interrupt vector" technique.
3039
3040
3041 Which method should your program use?
3042
3043 The majority of application programs can use either the
3044 "open handle" or the "get interrupt vector" method.
3045 However, if your program is a device driver or if it
3046 interrupts DOS during file system operations, you must use
3047 only the "get interrupt vector" method.
3048
3049 Device drivers execute from within DOS and can't access the
3050 DOS file system; programs that interrupt DOS during file
3051 system operations have a similar restriction. During their
3052 interrupt processing procedures, they can't access the DOS
3053 file system because another program may be using the system.
3054 Since the "get interrupt vector" method doesn't require the
3055 DOS file system, you must use it for these types of pro-
3056 grams.
3057
3058
3059 The "open handle" technique
3060
3061 Most application programs can use the DOS "open handle"
3062 technique to test for the presence of the memory manager.
3063 This section describes how to use the technique and gives an
3064 example.
3065
3066 Caution.........................................................
3067 Don't use this technique if your program is a device driver
3068 or if it interrupts DOS during file system operations. Use
3069 the "get interrupt vector" technique described later in this
3070 appendix.
3071
3072
3073 Using the "open handle" technique
3074
3075 This section describes how to use the DOS "open handle"
3076 technique to test for the presence of the memory manager.
3077 Follow these steps in order:
3078
3079 Testing For The Presence Of The EMM 199
3080
3081
3082
3083
3084
3085 1. Issue an "open handle" command (DOS function 3Dh) in
3086 "read only" access mode (register AL = 0). This
3087 function requires your program to point to an ASCII
3088 string which contains the path name of the file or
3089 device in which you're interested (register set DS:DX
3090 contains the pointer). In this case the file is
3091 actually the name of the memory manager.
3092
3093 You should format the ASCII string as follows:
3094
3095 ASCII_device_name DB 'EMMXXXX0', 0
3096
3097 The ASCII codes for the capital letters EMMXXXX0 are
3098 terminated by a byte containing a value of zero.
3099
3100 2. If DOS returns no error status code, skip Steps 3 and 4
3101 and go to Step 5. If DOS returns a "Too many open
3102 files" error status code, go to Step 3. If DOS returns
3103 a "File/Path not found" error status code, skip Step 3
3104 and go to Step 4.
3105
3106 3. If DOS returns a "Too many open files" (not enough
3107 handles) status code, your program should invoke the
3108 "open file" command before it opens any other files.
3109 This will guarantee that at least one file handle will
3110 be available to perform the function without causing
3111 this error.
3112
3113 After the program performs the "open file" command, it
3114 should perform the test described in Step 6 and close
3115 the "file handle" (DOS function 3Eh). Don't keep the
3116 manager "open" after this status test is performed since
3117 "manager" functions are not available through DOS. Go
3118 to Step 6.
3119
3120 4. If DOS returns a "File/Path not found," the memory
3121 manager is not installed. If your application requires
3122 the memory manager, the user will have to reboot the
3123 system with a disk containing the memory manager and the
3124 appropriate CONFIG.SYS file before proceeding.
3125
3126 5. If DOS doesn't return an error status code you can
3127 assume that either a device with the name EMMXXXX0 is
3128 resident in the system, or a file with this name is on
3129 disk in the current disk drive. Go to Step 6.
3130
3131 6. Issue an "I/O Control for Devices" command (DOS function
3132 44h) with a "get device information" command (register
3133 AL = 0). DOS function 44h determines whether EMMXXXX0
3134 is a device or a file.
3135
3136
3137
3138 Testing For The Presence Of The EMM 200
3139
3140
3141
3142
3143
3144 You must use the file handle (register BX) which you
3145 obtained in Step 1 to access the "EMM" device.
3146
3147 This function returns the "device information" in a word
3148 (register DX). Go to Step 7.
3149
3150 7. If DOS returns any error status code, you should assume
3151 that the memory manager device driver is not installed.
3152 If your application requires the memory manager, the
3153 user will have to reboot the system with a disk contain-
3154 ing the memory manager and the appropriate CONFIG.SYS
3155 file before proceeding.
3156
3157 8. If DOS didn't return an error status, test the contents
3158 of bit 7 (counting from 0) of the "device information"
3159 word (register DX) the function returned. Go to Step 9.
3160
3161 9. If bit 7 of the "device information" word contains a
3162 zero, then EMMXXXX0 is a file, and the memory manager
3163 device driver is not present. If your application
3164 requires the memory manager, the user will have to
3165 reboot the system with a disk containing the memory
3166 manager and the appropriate CONFIG.SYS file before
3167 proceeding.
3168
3169 If bit 7 contains a one, then EMMXXXX0 is a device. Go
3170 to Step 10.
3171
3172 10. Issue an "I/O Control for Devices" command (DOS function
3173 44h) with a "get output status" command (register AL =
3174 7).
3175
3176 You must use the file handle you obtained in Step 1 to
3177 access the "EMM" device (register BX). Go to Step 11.
3178
3179 11. If the expanded memory device driver is "ready," the
3180 memory manager passes a status value of "FFh" in
3181 register AL. The status value is "00h" if the device
3182 driver is "not ready."
3183
3184 If the memory manager device driver is "not ready" and
3185 your application requires its presence, the user will
3186 have to reboot the system with a disk containing the
3187 memory manager and the appropriate CONFIG.SYS file
3188 before proceeding.
3189
3190 If the memory manager device driver is "ready," go to
3191 Step 12.
3192
3193
3194
3195
3196
3197 Testing For The Presence Of The EMM 201
3198
3199
3200
3201
3202
3203 12. Issue a "Close File Handle" command (DOS function 3Eh)
3204 to close the expanded memory device driver. You must
3205 use the file handle you obtained in Step 1 to close the
3206 "EMM" device (register BX).
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256 Testing For The Presence Of The EMM 202
3257
3258
3259
3260
3261
3262 An example of the "open handle" technique
3263
3264 The following procedure is an example of the "open handle"
3265 technique outlined in the previous section.
3266
3267 ;--------------------------------------------------------------;
3268 ; The following procedure tests for the presence of the ;
3269 ; EMM in the system. It returns the CARRY FLAG SET if ;
3270 ; the EMM is present. If the EMM is not present, this ;
3271 ; procedure returns the CARRY FLAG CLEAR. ;
3272 ;--------------------------------------------------------------;
3273
3274 first_test_for_EMM PROC NEAR
3275 PUSH DS
3276 PUSH CS
3277 POP DS
3278 MOV AX,3D00h ; issue "device open" in
3279 LEA DX,ASCII_device_name ; "read only" mode
3280 INT 21h
3281 JC first_test_for_EMM_error_exit ; test for error
3282 ; during "device open"
3283 MOV BX,AX ; get the "file
3284 ; handle" returned by DOS
3285 MOV AX,4400h ; issue "IOCTL
3286 INT 21h ; get device info"
3287 JC first_test_for_EMM_error_exit ; test for error
3288 ; during "get device info"
3289 TEST DX,0080h ; test to determine
3290 JZ first_test_for_EMM_error_exit ; ASCII_device_name
3291 ; is a device or a file
3292 MOV AX,4407h ; issue "IOCTL"
3293 INT 21h
3294 JC first_test_for_EMM_error_exit ; test for error
3295 ; during "IOCTL"
3296 PUSH AX ; save "IOCTL" status
3297 MOV AH,3Eh ; issue "close
3298 INT 21h ; file handle"
3299 POP AX ; restore "IOCTL" status
3300 CMP AL,0FFh ; test for "device
3301 JNE first_test_for_EMM_error_exit ; ready" status
3302 ; returned by the driver
3303 first_test_for_EMM_exit:
3304 POP DS ; EMM is present
3305 STC ; in the system
3306 RET
3307
3308 first_test_for_EMM_error_exit:
3309 POP DS ; EMM is NOT present
3310 CLC ; in the system
3311 RET
3312 ASCII_device_name DB 'EMMXXXX0', 0
3313 first_test_for_EMM ENDP
3314
3315 Testing For The Presence Of The EMM 203
3316
3317
3318
3319
3320
3321 The "get interrupt vector" technique
3322
3323 Any type of program can use the DOS "get interrupt vector"
3324 technique to test for the presence of the memory manager.
3325 This section describes how to use the technique and gives an
3326 example.
3327
3328 Caution.........................................................
3329 Be sure to use this technique (and not the "open handle"
3330 technique) if your program is a device driver or if it
3331 interrupts DOS during file system operations.
3332
3333
3334 Using the "get interrupt vector" technique
3335
3336 This section describes how to use the DOS "get interrupt
3337 vector" technique to test for the presence of the memory
3338 manager. Follow these steps in order:
3339
3340 1. Issue a "get vector" command (DOS function 35h) to
3341 obtain the contents of interrupt vector array entry
3342 number 67h (addresses 0000:019Ch thru 0000:019Fh).
3343
3344 The memory manager uses this interrupt vector to perform
3345 all manager functions. The offset portion of this
3346 interrupt service routine address is stored in the word
3347 located at address 0000:019Ch; the segment portion is
3348 stored in the word located at address 0000:019Eh.
3349
3350 2. Compare the "device name field" with the contents of the
3351 ASCII string which starts at the address specified by
3352 the segment portion of the contents of interrupt vector
3353 address 67h and a fixed offset of 000Ah. If DOS loaded
3354 the memory manager at boot time this name field will
3355 have the name of the device in it.
3356
3357 Since the memory manager is implemented as a character
3358 device driver, its program origin is 0000h. Device
3359 drivers are required to have a "device header" located
3360 at the program origin. Within the "device header" is an
3361 8 byte "device name field." For a character mode device
3362 driver this name field is always located at offset 000Ah
3363 within the device header. The device name field
3364 contains the name of the device which DOS uses when it
3365 references the device.
3366
3367 If the result of the "string compare" in this technique
3368 is positive, the memory manager is present.
3369
3370
3371
3372
3373
3374 Testing For The Presence Of The EMM 204
3375
3376
3377
3378
3379
3380 An example of the "get interrupt vector" technique
3381
3382 The following procedure is an example of the "get interrupt
3383 vector" technique outlined in the previous section.
3384
3385
3386 ;--------------------------------------------------------------;
3387 ; The following procedure tests for the presence of the ;
3388 ; EMM in the system. It returns the CARRY FLAG SET if ;
3389 ; the EMM is present. If the EMM is not present, this ;
3390 ; procedure returns the CARRY FLAG CLEAR. ;
3391 ;--------------------------------------------------------------;
3392
3393
3394 second_test_for_EMM PROC NEAR
3395 PUSH DS
3396 PUSH CS
3397 POP DS
3398 MOV AX,3567h ; issue "get interrupt
3399 ; vector"
3400 INT 21h
3401 MOV DI,000Ah ; use the segment in ES
3402 ; returned by DOS, place
3403 ; the "device name field"
3404 ; OFFSET in DI
3405 LEA SI,ASCII_device_name ; place the OFFSET of the
3406 ; device name string in SI,
3407 ; the SEGMENT is already
3408 ; in DS
3409 MOV CX,8 ; compare the name strings
3410 CLD
3411 REPE CMPSB
3412 JNE second_test_for_EMM_error_exit
3413
3414 second_test_for_EMM_exit:
3415 POP DS ; EMM is present in
3416 STC ; the system
3417 RET
3418
3419 second_test_for_EMM_error_exit:
3420 POP DS ; EMM is NOT present
3421 CLC ; in the system
3422 RET
3423
3424 ASCII_device_name DB 'EMMXXXX0'
3425 second_test_for_EMM ENDP
3426
3427
3428
3429
3430
3431
3432
3433 Testing For The Presence Of The EMM 205
3434
3435
3436
3437
3438
3439 Appendix C
3440 EXPANDED MEMORY MANAGER IMPLEMENTATION GUIDELINES
3441
3442
3443
3444 In addition to the functional specification, the expanded
3445 memory manager should provide certain resources. The
3446 following guidelines are provided so required resources are
3447 present in expanded memory managers which comply with this
3448 version of the LIM specification.
3449
3450 o The amount of expanded memory supported:
3451 Up to a maximum of 32M bytes of expanded memory should
3452 be supported.
3453
3454 o The number of handles supported:
3455 The maximum number of expanded memory handles provided
3456 should be 255, the minimum should be 64.
3457
3458 o Handle Numbering:
3459 Although a handle is a word quantity, there is a maximum
3460 of 255 handles, including the operating system handle.
3461 This specification defines the handle word as follows:
3462 the low byte of the word is the actual handle value, the
3463 high byte of the handle is set to 00h by the memory
3464 manager. Previous versions of this specification did
3465 not specify the value of handles.
3466
3467 o New handle type: Handles versus Raw Handles:
3468 The difference between a raw handle and a regular handle
3469 is slight. If you use Function 27 to "Allocate raw
3470 pages to a handle," what is returned in DX is termed a
3471 raw handle. The raw handle does not necessarily refer
3472 to 16K-byte pages. Instead it refers to the "raw" page
3473 size, which depends on the expanded memory hardware.
3474
3475 An application program can use Function 26 to find the
3476 raw page size, and by using the raw handle Function 27
3477 returns, it can access them with the finer resolution
3478 that a particular expanded memory board may allow.
3479
3480 On the other hand, applications which use Function 4 to
3481 "allocate pages to handle" receive a handle which always
3482 refers to 16K-byte pages. On expanded memory boards
3483 with smaller raw pages, the EMM driver will allocate and
3484 maintain the number of raw pages it takes to create a
3485 single composite 16K-byte page. The difference between
3486 the expanded memory boards' raw page size and the 16K-
3487 byte LIM page size is transparent to the application
3488 when it is using a handle obtained with Function 4.
3489
3490
3491
3492 EMM Implementation Guidelines 206
3493
3494
3495
3496
3497
3498 The memory manager must differentiate between pages
3499 allocated to handles and pages allocated to raw handles.
3500 The meaning of a call to the driver changes depending on
3501 whether a handle or a raw handle is passed to the memory
3502 manager. If, for example, a handle is passed to
3503 Function 18 (Reallocate), the memory manager will
3504 increase or decrease the number of 16K-byte pages
3505 allocated to the handle. If Function 18 is passed a raw
3506 handle, the memory manager will increase or decrease the
3507 number of raw (non-16K-byte) pages allocated to the raw
3508 handle. For LIM standard boards, there is no difference
3509 between pages and raw pages.
3510
3511 o The system Raw Handle (Raw Handle = 0000h):
3512 For expanded memory boards that can remap the memory in
3513 the lower 640K-byte address space, managing the pages of
3514 memory which are used to fill in the lower 640K can be a
3515 problem. To solve this problem, the memory manager will
3516 create a raw handle with a value of 0000h when DOS loads
3517 the manager. This raw handle is called the system
3518 handle.
3519
3520 At power up, the memory manager will allocate all of the
3521 pages that are mapped into the lower 640K bytes to the
3522 system handle. These pages should be mapped in their
3523 logical order. For example, if the system board
3524 supplies 256K bytes of RAM, and the 384K bytes above it
3525 is mappable, the system handle should have its logical
3526 page zero mapped into the first physical page at 256K,
3527 its logical page one mapped into the next physical page,
3528 and so on.
3529
3530 The system handle should deal with raw pages. To
3531 release some of these pages so application programs can
3532 use them, an operating system could decrease the number
3533 of pages allocated to the system handle with the
3534 "Reallocate" function. Invoking the "Deallocate"
3535 function would decrease the system handle to zero size,
3536 but it must not deallocate the raw handle itself. The
3537 "Deallocate" function treats the system handle dif-
3538 ferently than it treats other raw handles. If the
3539 operating system can ever be "exited" (for example, the
3540 way Windows can be exited), it must increase the size of
3541 the system handle back to what is needed to fill 640K
3542 and map these logical pages back into physical memory
3543 before returning to DOS.
3544
3545
3546
3547
3548
3549
3550
3551 EMM Implementation Guidelines 207
3552
3553
3554
3555
3556
3557 There are two functional special cases for this handle:
3558
3559 - The first special case deals with Function 4
3560 (Allocate Pages). This function must never return
3561 zero as a handle value. Applications must always
3562 invoke Function 4 to allocate pages and obtain a
3563 handle which identifies its pages. Since Function 4
3564 will never return a handle value of zero, an
3565 application will never gain access to this special
3566 handle.
3567
3568 - The second special case deals with Function 6
3569 (Deallocate Pages). If the operating system uses
3570 Function 6 to deallocate the pages which are
3571 allocated to the system handle, the pages will be
3572 returned to the manager for use, but the handle will
3573 not be available for reassignment. The manager
3574 should treat a "deallocate pages" function request
3575 for this handle the same as a "reallocate pages"
3576 function request, where the number of pages to
3577 reallocate to this handle is zero.
3578
3579 o Terminate and Stay Resident (TSR) Program Cooperation:
3580 In order for TSR's to cooperate with each other and with
3581 other applications, TSR's must follow this rule: a
3582 program may only remap the DOS partition it lives in.
3583 This rule applies at all times, even when no expanded
3584 memory is present.
3585
3586 o Accelerator Cards:
3587 To support generic accelerator cards, the support of
3588 Function 34, as defined by AST, is encouraged.
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610 EMM Implementation Guidelines 208
3611
3612
3613
3614
3615
3616 Appendix D
3617 OPERATING SYSTEM/ENVIRONMENT USE OF FUNCTION 28
3618
3619
3620
3621 All expanded memory boards have a set of registers that
3622 "remember" the logical to physical page mappings. Some
3623 boards have extra (or alternate) sets of these mapping
3624 registers. Because no expanded memory board can supply an
3625 infinite number of alternate map register sets, this
3626 specification provides a way to simulate them using Function
3627 28 (Alternate Map Register Set).
3628
3629
3630 Examples
3631
3632 For the examples in this section, assume the hardware
3633 supports alternate map register sets. First Windows is
3634 brought up, then "Reversi" is started. Then control is
3635 switched back to the MS-DOS Executive. For this procedure,
3636 here are the calls to the expanded memory manager:
3637
3638 Example 1
3639
3640 Allocate alt reg set ; Start up the MS-DOS
3641 (for MS-DOS Executive) ; Executive
3642
3643 Set alt reg set
3644 (for MS-DOS Executive)
3645
3646 Allocate alt reg set ; Start up Reversi
3647 (for Reversi)
3648
3649 Set alt reg set
3650 (for Reversi)
3651
3652 Map pages
3653 (for Reversi)
3654
3655 Set alt ret set ; Switch back to MS-DOS
3656 (for MS-DOS Executive) ; Executive
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669 Operating System Use Of Function 28 209
3670
3671
3672
3673
3674
3675 Notice this procedure needed no "get" calls because the
3676 register set contained all the information needed to save a
3677 context. However, using "Get" calls would have no ill
3678 effects.
3679
3680 Example 2
3681
3682 Allocate alt reg set ; Start up MS-DOS
3683 (for MS-DOS Executive) ; Executive
3684
3685 Set alt reg set
3686 (for MS-DOS Executive)
3687
3688 Get alt reg set
3689 (for MS-DOS Executive)
3690
3691 Allocate alt reg set ; Start up Reversi
3692 (for Reversi)
3693
3694 Set alt reg set
3695 (for Reversi)
3696
3697 Map pages
3698 (for Reversi)
3699
3700 Get alt reg set
3701 (for Reversi)
3702
3703 Set alt reg set ; Switch back to MS-DOS
3704 (for MS-DOS Executive) ; Executive
3705
3706 The important point to follow is that a Set must always
3707 precede a Get. The model of Set then Get is the inverse of
3708 what interrupt handlers use, which is Get then Set (Get the
3709 old map context and Set the new one). Another crucial point
3710 is that an alternate map register set must have the current
3711 mapping when allocated; otherwise, the Set will create
3712 chaos.
3713
3714 What happens if this is simulated in software? The same Set
3715 and Get model applies. The main difference is where the
3716 context is saved.
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728 Operating System Use Of Function 28 210
3729
3730
3731
3732
3733
3734 Since the allocate call is dynamic and there is no limit on
3735 the number of sets allocated, the OS/E must supply the space
3736 required. Device drivers cannot allocate space dynamically,
3737 since the request would fail. If the Allocate register set
3738 call returns a status indicating the alternate map register
3739 sets aren't supported, the OS/E must allocate space for the
3740 context. It must also initialize the context using Function
3741 15. At that point it can do the Set, passing a pointer to
3742 the map context space. On the Get call, the EMM driver is
3743 to return a pointer to the same context space.
3744
3745 Example 3
3746
3747 Allocate alt reg set ; Start up MS-DOS
3748 (for MS-DOS Executive) ; Executive
3749
3750 Get Page Map
3751 (for MS-DOS Executive)
3752
3753 Set alt reg set
3754 (for MS-DOS Executive)
3755
3756 Allocate alt reg set ; Start up Reversi
3757 (for Reversi)
3758
3759 Set alt reg set
3760 (for Reversi)
3761
3762 Map pages
3763 (for Reversi)
3764
3765 Get Page Map
3766 (for Reversi)
3767
3768 Set alt ret set ; Switch back to MS-DOS
3769 (for MS-DOS Executive) ; Executive
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787 Operating System Use Of Function 28 211
3788
3789
3790
3791
3792
3793 GLOSSARY
3794
3795
3796
3797 The following terms are used frequently in this specifica-
3798 tion:
3799
3800
3801 Allocate To reserve a specified amount of
3802 expanded memory pages.
3803
3804 Application Program An application program is the program
3805 you write and your customer uses. Some
3806 categories of application software are
3807 word processors, database managers,
3808 spreadsheet managers, and project
3809 managers.
3810
3811 Conventional memory The memory between 0 and 640K bytes,
3812 address range 00000h thru 9FFFFh.
3813
3814 Deallocate To return previously allocated expanded
3815 memory to the memory manager.
3816
3817 EMM See Expanded Memory Manager.
3818
3819 Expanded memory Expanded memory is memory outside DOS's
3820 640K-byte limit (usually in the range of
3821 C0000h thru EFFFFh).
3822
3823 Expanded Memory A device driver that controls the
3824 Manager (EMM) interface between DOS application
3825 programs and expanded memory.
3826
3827 Extended memory The 15M-byte address range between
3828 100000h thru FFFFFFh available on an
3829 80286 processor when it is operating in
3830 protected virtual address mode.
3831
3832 Handle A value that the EMM assigns and uses to
3833 identify a block of memory requested by
3834 an application program. All allocated
3835 logical pages are associated with a
3836 particular handle.
3837
3838 Logical Page The EMM allocates expanded memory in
3839 units (typically 16K bytes) called
3840 logical pages.
3841
3842 Mappable Segment A 16K-byte region of memory which can
3843 have a logical page mapped at it.
3844
3845
3846 Glossary 212
3847
3848
3849
3850
3851
3852 Map Registers The set of registers containing the
3853 current mapping context of the EMM
3854 hardware.
3855
3856 Mapping The process of making a logical page of
3857 memory appear at a physical page.
3858
3859 Mapping Context The contents of the mapping registers at
3860 a specific instant. This context
3861 represents a map state.
3862
3863 Page Frame A collection of 16K-byte contiguous
3864 physical pages from which an application
3865 program accesses expanded memory.
3866
3867 Page Frame A page frame base address is the
3868 Base Address location (in segment format) of the
3869 first byte of the page frame.
3870
3871 Physical Page A physical page is the range of memory
3872 addresses occupied by a single 16K-byte
3873 page.
3874
3875 Raw Page The smallest unit of mappable memory
3876 that an expanded memory board can
3877 supply.
3878
3879 Resident Application A resident application program is loaded
3880 Program by DOS, executes, and remains resident
3881 in the system after it returns control
3882 to DOS. This type of program occupies
3883 memory and is usually invoked by the
3884 operating system, an application
3885 program, or the hardware. Some example
3886 of resident application programs are RAM
3887 disks, print spoolers, and "pop-up"
3888 desktop programs.
3889
3890 Status code A code that an EMM function returns
3891 which indicates something about the
3892 result of running the function. Some
3893 status codes indicate whether the
3894 function worked correctly and others may
3895 tell you something about the expanded
3896 memory hardware or software.
3897
3898
3899
3900
3901
3902
3903
3904
3905 Glossary 213
3906
3907
3908
3909
3910
3911 Transient Application A transient application program is
3912 Program loaded by DOS, executes, and doesn't
3913 remain in the system after it returns
3914 control to DOS. After a transient
3915 application program returns control to
3916 DOS, the memory it used is available for
3917 other programs.
3918
3919 Unmap To make a logical page inaccessible for
3920 reading or writing.
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964 Glossary 214
3965
3966
3967
3968
3969
3970 INDEX
3971
3972
3973
3974 Allocate Alternate Map Register Set 36, 163
3975 Allocate DMA Register Set 36, 168, 190
3976 Allocate Pages 5, 14, 23, 30, 34, 42, 43, 47, 49, 144,
3977 147, 148, 193, 206, 208
3978 Allocate Raw Pages 36, 46, 80, 89, 147-149, 190, 193,
3979 206
3980 Allocate Standard Pages 36, 42, 46, 80, 89, 144, 145,
3981 147, 190, 193
3982 Alter Page Map & Call 7, 10, 35, 113, 118, 189
3983 Alter Page Map & Jump 7, 10, 35, 109, 189
3984 Alternate Map 10, 36, 151, 153-155, 157-159, 161, 163,
3985 164, 165-168, 170, 173, 175, 179, 182, 190, 197,
3986 209, 210, 211
3987 Alternate Map Register Set 10, 36, 151, 153-155, 157,
3988 158, 159, 161, 163-168, 170, 173, 175, 190, 197,
3989 209, 210
3990 Alternate Mapping and Unmapping Methods 81
3991 Alternate Register 139, 166, 173, 177
3992 Data Aliasing 12
3993 Deallocate Alternate Map Register Set 36, 166
3994 Deallocate DMA Register Set 36, 175, 190
3995 Deallocate Pages 5, 14, 25, 31, 34, 43, 49, 88, 145,
3996 148, 208
3997 Design Considerations 91, 151
3998 Device Driver 1, 15, 43, 53, 55, 144, 148, 199, 201,
3999 202, 204, 212
4000 Disable DMA on Alternate Map Register Set 173
4001 Disable OS/E Function Set 36, 179, 180, 182, 185
4002 DMA 36, 138-140, 151, 152, 168-176, 190, 197
4003 DMA Channels 139, 171, 173, 174, 197
4004 DMA Register 36, 139, 140, 151, 152, 168-171, 173-176,
4005 190, 197
4006 DOS 1, 12, 14, 15, 19, 21, 30, 31, 49, 53, 88, 199-205,
4007 207-214
4008 Enable DMA on Alternate Map Register Set 170
4009 Enable OS/E Function Set 36, 179, 180
4010 Enable/Disable OS/E Function Set 179, 180, 182, 185
4011 Exchange Memory Region 7, 10, 35, 120, 126, 127, 189
4012 Expanded Memory Support of DMA 151
4013 Expanded Memory Support of DMA Register Sets 151
4014 Extended Memory 91
4015 Function 1 37
4016 Function 10 57
4017 Function 11 58
4018 Function 12 59
4019 Function 13 61
4020 Function 14 7, 63
4021
4022
4023 Index 215
4024
4025
4026
4027
4028
4029 Function 15 13, 53, 55, 65, 67, 69, 71, 73, 76, 139,
4030 153, 154, 155, 158, 211
4031 Function 16 13, 73, 76, 78
4032 Function 17 6, 80, 82, 85
4033 Function 18 6, 43, 88, 144, 148, 207
4034 Function 19 7, 91, 92, 94, 96
4035 Function 2 4, 38
4036 Function 20 7, 98, 100
4037 Function 21 7, 42, 102, 105, 107
4038 Function 22 109
4039 Function 23 113, 118
4040 Function 24 7, 120, 126
4041 Function 25 6, 8, 46, 74, 85, 132, 136
4042 Function 26 138, 142, 179, 182, 206
4043 Function 27 42, 46, 80, 89, 144, 145, 147-149, 193, 206
4044 Function 28 140, 151, 153, 157, 161, 163, 164, 166,
4045 168, 170, 173, 175, 179, 182, 209
4046 Function 29 177
4047 Function 3 4, 40, 142
4048 Function 30 138, 151, 153, 157, 161, 163, 166, 168,
4049 170, 173, 175, 179, 182, 185
4050 Function 4 4, 42, 43, 46, 47, 49, 80, 89, 144, 145,
4051 147, 149, 193, 206, 208
4052 Function 5 4, 46, 81
4053 Function 6 4, 43, 49, 88, 145, 148, 208
4054 Function 7 5, 51
4055 Function 8 46, 50, 53, 55
4056 Function 9 46, 50, 53, 55
4057 Get & Set Page Map 35, 69
4058 Get All Handle Pages 9, 34, 63
4059 Get Alternate Map Register Set 36, 153, 154, 157, 190
4060 Get Alternate Map Save Array Size 36, 161, 190
4061 Get Attribute Capability 7, 96
4062 Get Expanded Memory Hardware Information 10, 138, 142,
4063 179, 182
4064 Get Handle Attribute 35, 92
4065 Get Handle Count 9, 34, 59
4066 Get Handle Directory 10, 35, 102, 105, 107
4067 Get Handle Name 35, 98
4068 Get Handle Pages 7, 9, 34, 61
4069 Get Hardware Configuration Array 36, 138
4070 Get Interrupt Vector 15, 21, 30, 199, 204, 205
4071 Get Mappable Physical Address Array 6, 8, 10, 35, 46,
4072 85, 132, 136
4073 Get Mappable Physical Address Array Entries 8, 136
4074 Get Page Frame Address 5, 34, 38
4075 Get Page Map 35, 65, 118, 153-155, 158, 211
4076 Get Page Map Stack Space Size 35, 118
4077 Get Partial Page Map 35, 73, 78
4078 Get Size of Page Map Save Array 35, 65, 67, 71, 139
4079 Get Size of Partial Page Map Save Array 74, 76, 78
4080 Get Status 5, 34, 37
4081
4082 Index 216
4083
4084
4085
4086
4087
4088 Get Total Handles 35, 107
4089 Get Unallocated Page Count 5, 22, 34, 40, 142
4090 Get Unallocated Raw Page Count 36, 142, 189
4091 Get Version 5, 34, 51
4092 Get/Set Handle Attribute 9, 91, 92, 94, 96
4093 Get/Set Handle Name 10, 98, 100
4094 Get/Set Page Map 9, 13, 65, 67, 69, 71
4095 Get/Set Partial Page Map 9, 13, 73, 76, 78
4096 Handle Attribute 9, 35, 91-94, 96, 188
4097 Handle Name 6, 7, 10, 35, 98, 100, 105, 106, 188, 198
4098 Intel i, ii, 1, 5, 57, 58
4099 Interrupt Vector 12, 15, 21, 30, 199, 204, 205
4100 LIM 1, 7, 13, 19, 27, 53, 55, 138, 140, 206, 207
4101 Logical Page 1, 5, 12, 16, 19, 23, 28, 31, 32, 46-48,
4102 80-83, 85, 86, 88, 110, 111, 115, 116, 120, 122,
4103 123, 125, 126, 128, 129, 131, 147, 194, 196, 207,
4104 212-214
4105 Logical Page/Physical Page Method 82
4106 Logical Page/Segment Address Method 85
4107 Lotus i, ii, 1, 5, 57, 58
4108 Map Register 10, 13, 36, 53, 55, 151, 153-155, 157-159,
4109 161, 163-168, 170, 173, 175, 179, 182, 190, 197,
4110 209-211
4111 Map/Unmap Handle Pages 46
4112 Map/Unmap Multiple Handle Pages 9, 35, 80, 82, 85
4113 Mapping and Unmapping Multiple Pages Simultaneously 80
4114 Mapping Multiple Pages 6, 80
4115 Microsoft i, ii, 1, 5, 14, 30, 42, 57, 58, 144, 148
4116 Move Memory Region 35, 120, 121, 189
4117 Move/Exchange Memory Region 7, 10, 120, 126
4118 Open Handle 64, 102, 199, 200, 203, 204
4119 Operating System 3, 8, 10-12, 42, 43, 59, 63, 107, 138,
4120 139, 141, 142, 144-151, 153-159, 161-163, 165-171,
4121 173-177, 179-183, 185, 186, 190, 191, 198, 206,
4122 207-209, 213
4123 Page Frame 1-6, 14, 17-19, 24, 28, 31, 34, 38, 39, 47,
4124 53, 55, 121, 128, 133, 187, 213
4125 Page Map 7, 9, 10, 13, 34, 35, 50, 53, 55, 65, 67, 69,
4126 71, 73-76, 78, 109, 113, 118, 139, 153-155, 158,
4127 187, 188, 189, 211
4128 Page Mapping Register I/O Array 57
4129 Page Translation Array 58
4130 Physical Page 1, 5, 6, 8, 10, 12, 16, 23, 28, 31, 35,
4131 46, 47, 48, 80-83, 85, 109-112, 114-117, 132-134,
4132 136, 138, 139, 142, 147, 188, 194, 207, 209, 213
4133 Prepare Expanded Memory Hardware For Warm Boot 10, 177
4134 Raw Handle 147, 149, 150, 206, 207
4135 Raw Page 36, 142, 143, 147, 189, 206
4136 Reallocate Pages 9, 35, 43, 88, 144, 145, 148, 208
4137 Restore Page Map 9, 13, 34, 50, 53, 55
4138 Return Access Key 185
4139 Save Page Map 9, 13, 34, 50, 53, 55
4140
4141 Index 217
4142
4143
4144
4145
4146
4147 Search For Named Handle 7, 35, 105
4148 Set Alternate Map Register Set 36, 153-155, 157, 158,
4149 163, 190
4150 Set Handle Attribute 9, 35, 91, 92, 94, 96
4151 Set Handle Name 7, 10, 35, 98, 100
4152 Set Page Map 9, 13, 35, 65, 67, 69, 71, 188
4153 Set Partial Page Map 9, 13, 35, 73, 76, 78
4154 Standard Handle 146
4155 Standard Page 147
4156 System DMA Capabilities 151
4157 TSR 12, 13, 208
4158 Unmapping Multiple Pages 6, 80
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200 Index 218
4201
4202 Mµp��ALLINFO.TXT��
4203Following are BBSes that are members of DV-NET. DV-Net is an informal
4204network of BBS's that carry files that would be useful to DESQview users.
4205Not all BBSes that carry the DESQview conference are members of DV-Net.
4206
4207All address are NetMail addresses.
4208
4209 ----------------------------------------------
4210 DVNet DESQview Support File Network
4211 ----------------------------------------------
4212 DESQview is a trademark of Quarterdeck Office Systems
4213 -----------------------------------------------------------
4214 DVNet is not affiliated with Quarterdeck Office Systems
4215 ----------------------------------------------------------------
4216
4217 Name, City and State NetAddress Telephone Maxbaud
4218 ------------------------------- ---------- ------------ -------
4219 *65'North, Fairbanks, AK 1:17/38 907-452-1460 9600HSTV32
4220 Opus 386, Davis, CA 1:203/910 916-753-6321 2400
4221 Carl's Corner, San Jose, CA 1:10/1 408-248-9704 9600HSTV32
4222 Carl's Corner, San Jose, CA 1:10/2 408-248-0198 2400
4223 SeaHunt BBS, Burlingame, CA 1:125/20 415-344-4348 9600HST
4224 Stingray!, Clovis CA 1:205/12 209-298-9461 9600HST
4225 SF PCUG BBS, San Francisco CA 1:1/310 415-621-2609 9600HSTV32RE
4226 Bink of an Aye, Portland, OR 1:105/42 503-297-9043 9600PEPV32MO
4227 P C Support, Portland, OR 1:105/66 503-297-9078 2400
4228 Atarian BBS, Portland, OR 1:105/10 503-245-9730 9600HSTV32
4229 Busker's BoneYard, Portland,OR 1:105/14 503-771-4773 9600PEP
4230 Busker's Boneyard, Portland,OR 1:105/41 503-775-7926 9600HSTV32
4231 Pacifier BBS, Vancouver, WA 1:105/103 206-253-9770 9600HSTV32
4232 Puget Sound Gtwy., Puyallup, WA 1:138/3 206-566-8854 9600HST
4233 Rampart General,Kansas City,MO 1:280/6 816-761-4039 9600HST
4234 Oregon Trail XRoads, Casper WY 1:303/5 307-472-3615 9600H96
4235 Dawg Byte, Nashville, TN 1:116/29 615-385-4268 9600HST
4236 Dickson County, Dickson, TN 1:116/25 615-446-4475 2400
4237 Programmers' Attic, Will., MI 1:159/850 517-655-3347 2400
4238 Dark Side Of the Moon,Savoy IL 1:233/493 217-356-6922 9600HSTV32
4239 Ecclesia Place, Monroeville, PA 1:129/75 412-373-8612 9600HST
4240 The Other BBS, Harrisburg PA 1:270/101 717-657-2223 9600HST
4241 IBM Tech Fido, Pepperell, MA 1:322/1 508-433-8452 9600HSTV32
4242 Waystar BBS, Marlborough, MA 1:322/14 508-481-7147 9600HST
4243 Andromeda Galaxy, Troy NY 1:267/167 518-273-8313 9600HST
4244 Treasure Island, Danbury, CT 1:141/730 203-791-8532, 9600HST
4245 Addict's Attic,Germantown MD 1:109/423 301-428-8998 9600HST
4246 Maple Shade Opus,Maple Shade NJ 1:266/12 609-482-8604 9600HSTV32
4247 Capital City , Burlington NJ 99:9230/1 609-386-1989 9600HSTV32
4248 Capital City , Burlington NJ 8:950/10 609-386-1989 9600HSTV32
4249 Southern Cross BBS, Miami FL 1:135/69 305-220-8752 9600HST
4250 Software Designer, Albany, GA 1:3617/1 912-432-2440 9600HSTV32
4251 Software Designer, Albany, GA 8:928/1 912-432-2440 9600HSTV32
4252 Dragon's Lair, Galveston, TX 1:386/451 409-762-2761 9600HST
4253 Dragon's Lair, Galveston, TX 1:386/1451 409-762-7456 2400MNP
4254 Conch Opus, Houston, TX 1:106/357 713-667-7213 2400PCP
4255 Inns of Court, Dallas, TX 1:124/6101 214-458-2620 9600HSTV32
4256 Dallas Email, Dallas, TX 8:930/101 214-358-1205 9600HSTV32MO
4257 Spare Parts, Bedford, TX 1:130/38 817-540-3527 9600HST
4258 QE2, Austin TX 1:382/58 512-328-1229 2400
4259 Ned's Opus HST Ottawa,ON Canada 1:163/211 613-523-8965 9600HST
4260 Ned's Opus, Ottawa ON Canada 1:163/210 613-731-8132 2400
4261 Imperial Terran, St Cath,ON 1:247/102 416-646-7105 9600HST
4262 Arcane BBS, Laval PQ Canada 1:167/116 514-687-9586 9600HST
4263 Zone 2 & Zone 3
4264 ------------------------------ --------- ------------- -------
4265 The HEKOM Board (Netherlands) 2:286/3 31-3483-4072 2400MNP5
4266 BBS_D.C.V.V., Maaseik (Belgium) 2:295/26 32-11-568620eXtended Memory Specification (XMS), ver 3.0
4267
4268
4269January 1991
4270
4271
4272Copyright (c) 1988, Microsoft Corporation, Lotus Development
4273Corporation, Intel Corporation, and AST Research, Inc.
4274
4275Microsoft Corporation
4276Box 97017
4277
4278One Microsoft Way
4279Redmond, WA 98073
4280
4281LOTUS (r)
4282INTEL (r)
4283MICROSOFT (r)
4284AST (r) Research
4285
4286This specification was jointly developed by Microsoft Corporation,
4287Lotus Development Corporation, Intel Corporation,and AST Research,
4288Inc. Although it has been released into the public domain and is not
4289confidential or proprietary, the specification is still the copyright
4290and property of Microsoft Corporation, Lotus Development Corporation,
4291Intel Corporation, and AST Research, Inc.
4292
4293Disclaimer of Warranty
4294
4295MICROSOFT CORPORATION, LOTUS DEVELOPMENT CORPORATION, INTEL
4296CORPORATION, AND AST RESEARCH, INC., EXCLUDE ANY AND ALL IMPLIED
4297WARRANTIES, INCLUDING WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
4298PARTICULAR PURPOSE. NEITHER MICROSOFT NOR LOTUS NOR INTEL NOR AST
4299RESEARCH MAKE ANY WARRANTY OF REPRESENTATION, EITHER EXPRESS OR
4300IMPLIED, WITH RESPECT TO THIS SPECIFICATION, ITS QUALITY,
4301PERFORMANCE, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
4302NEITHER MICROSOFT NOR LOTUS NOR INTEL NOR AST RESEARCH SHALL HAVE ANY
4303LIABILITY FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING
4304OUT OF OR RESULTING FROM THE USE OR MODIFICATION OF THIS
4305SPECIFICATION.
4306
4307This specification uses the following trademarks:
4308
4309Intel is a registered trademark of Intel Corporation, Microsoft is a
4310registered trademark of Microsoft Corporation, Lotus is a registered
4311trademark of Lotus Development Corporation, and AST is a registered
4312trademark of AST Research, Inc.
4313
4314
4315
4316Extended Memory Specification
4317
4318 The purpose of this document is to define the Extended Memory Specification (XMS) version 3.00 for MS-DOS. XMS allows DOS programs to utilize additional memory found in Intel's 80286 and 80386 based machines in a consistent, machine independent manner. With some restrictions, XMS adds almost 64K to the 640K which DOS programs can access directly. Depending on available hardware, XMS may provide even more memory to DOS programs. XMS also provides DOS programs with a standard method of storing data in extended memory.
4319
4320 To be considered fully XMS 3.0 compliant, all calls except those associated with UMB support must be implemented. UMB functions 10h, 11h and 12h are optional for XMS 3.0 and may return the Function Not Implemented error code, 80h.
4321
4322DEFINITIONS:
4323------------
4324
4325Extended Memory:
4326Memory in 80286 and 80386 based machines which is located above the 1MB address boundary.
4327
4328High Memory Area (HMA):
4329The first 64K of extended memory. The High Memory Area is unique because code can be executed in it while in real mode. The HMA officially starts at FFFF:10h and ends at FFFF:FFFFh making it 64K-16 bytes in length.
4330
4331Upper Memory Blocks (UMBs):
4332Blocks of memory available on some 80x86 based machines which are located between DOS's 640K limit and the 1MB address boundary. The number, size, and location of these blocks vary widely depending upon the types of hardware adapter cards installed in the machine.
4333
4334Extended Memory Blocks (EMBs):
4335Blocks of extended memory located above the HMA which can only be used for data storage.
4336
4337A20 Line:
4338The 21st address line of 80x86 CPUs. Enabling the A20 line allows access to the HMA.
4339
4340XMM:
4341An Extended Memory Manager. A DOS device driver which implements XMS. XMMs are machine specific but allow programs to use extended memory in a machine-independent manner.
4342
4343HIMEM.SYS:
4344The Extended Memory Manager currently being distributed by Microsoft.
4345
4346
4347
4348Helpful Diagram:
4349
4350| | Top of Memory
4351| |
4352| |
4353| /\ |
4354| /||\ |
4355| || |
4356| || |
4357| |
4358| |
4359| |
4360| Possible Extended Memory Block |
4361| |
4362| |
4363| |
4364| || |
4365| || |
4366| \||/ |
4367| \/ |
4368| |
4369| |
4370| Other EMBs could exist above 1088K (1MB+64K) |
4371| |
4372| |
4373| | 1088K
4374| |
4375| |
4376| The High Memory Area |
4377| |
4378| |
4379| | 1024K or 1MB
4380| |
4381| /\ |
4382| /||\ |
4383| || |
4384| || |
4385| |
4386| |
4387| Possible Upper Memory Block |
4388| |
4389| || |
4390| || |
4391| \||/ |
4392| \/ |
4393| |
4394| Other UMBs could exist between 640K and 1MB |
4395| |
4396| | 640K
4397
4398| |
4399| |
4400| |
4401| Conventional or DOS Memory |
4402| |
4403| |
4404| |
4405| |
4406| |
4407+ + 0K
4408
4409DRIVER INSTALLATION:
4410--------------------
4411
4412 An XMS driver is installed by including a DEVICE= statement in the
4413machine's CONFIG.SYS file. It must be installed prior to any other
4414devices or TSRs which use it. An optional parameter after the driver's
4415name (suggested name "/HMAMIN=") indicates the minimum amount of space in
4416the HMA a program can use. Programs which use less than the minimum will
4417not be placed in the HMA. See "Prioritizing HMA Usage" below for more
4418information. A second optional parameter (suggested name "/NUMHANDLES=")
4419allows users to specify the maximum number of extended memory blocks which
4420may be allocated at any time.
4421
4422 NOTE: XMS requires DOS 3.00 or above.
4423
4424
4425THE PROGRAMMING API:
4426--------------------
4427
4428 The XMS API Functions are accessed via the XMS driver's Control Function.
4429The address of the Control Function is determined via INT 2Fh. First, a
4430program should determine if an XMS driver is installed. Next, it should
4431retrieve the address of the driver's Control Function. It can then use any
4432of the available XMS functions. The functions are divided into several
4433groups:
4434
4435 1. Driver Information Functions (0h)
4436 2. HMA Management Functions (1h-2h)
4437 3. A20 Management Functions (3h-7h)
4438 4. Extended Memory Management Functions (8h-Fh)
4439 5. Upper Memory Management Functions (10h-11h)
4440
4441
4442DETERMINING IF AN XMS DRIVER IS INSTALLED:
4443------------------------------------------
4444
4445 The recommended way of determining if an XMS driver is installed is to
4446set AH=43h and AL=00h and then execute INT 2Fh. If an XMS driver is available,
444780h will be returned in AL.
4448
4449 Example:
4450 ; Is an XMS driver installed?
4451 mov ax,4300h
4452 int 2Fh
4453 cmp al,80h
4454 jne NoXMSDriver
4455
4456
4457CALLING THE API FUNCTIONS:
4458--------------------------
4459
4460 Programs can execute INT 2Fh with AH=43h and AL=10h to obtain the address
4461of the driver's control function. The address is returned in ES:BX. This
4462function is called to access all of the XMS functions. It should be called
4463with AH set to the number of the API function requested. The API function
4464will put a success code of 0001h or 0000h in AX. If the function succeeded
4465(AX=0001h), additional information may be passed back in BX and DX. If the
4466function failed (AX=0000h), an error code may be returned in BL. Valid
4467error codes have their high bit set. Developers should keep in mind that
4468some of the XMS API functions may not be implemented by all drivers and will
4469return failure in all cases.
4470
4471 Example:
4472 ; Get the address of the driver's control function
4473 mov ax,4310h
4474 int 2Fh
4475 mov word ptr [XMSControl],bx ; XMSControl is a DWORD
4476 mov word ptr [XMSControl+2],es
4477
4478 ; Get the XMS driver's version number
4479 mov ah,00h
4480 call [XMSControl] ; Get XMS Version Number
4481
4482 NOTE: Programs should make sure that at least 256 bytes of stack space
4483 is available before calling XMS API functions.
4484
4485
4486API FUNCTION DESCRIPTIONS:
4487--------------------------
4488
4489 The following XMS API functions are available:
4490
4491 0h) Get XMS Version Number
4492 1h) Request High Memory Area
4493 2h) Release High Memory Area
4494 3h) Global Enable A20
4495 4h) Global Disable A20
4496 5h) Local Enable A20
4497 6h) Local Disable A20
4498 7h) Query A20
4499 8h) Query Free Extended Memory
4500 9h) Allocate Extended Memory Block
4501 Ah) Free Extended Memory Block
4502 Bh) Move Extended Memory Block
4503 Ch) Lock Extended Memory Block
4504 Dh) Unlock Extended Memory Block
4505 Eh) Get Handle Information
4506 Fh) Reallocate Extended Memory Block
4507 10h) Request Upper Memory Block
4508 11h) Release Upper Memory Block
4509 12h) Realloc Upper Memory Block
4510 88h) Query any Free Extended Memory
4511 89h) Allocate any Extended Memory Block
4512 8Eh) Get Extended EMB Handle
4513 8Fh) Realloc any Extended Memory
4514
4515Each is described below.
4516
4517
4518Get XMS Version Number (Function 00h):
4519--------------------------------------
4520
4521 ARGS: AH = 00h
4522 RETS: AX = XMS version number
4523 BX = Driver internal revision number
4524 DX = 0001h if the HMA exists, 0000h otherwise
4525 ERRS: None
4526
4527 This function returns with AX equal to a 16-bit BCD number representing
4528the revision of the DOS Extended Memory Specification which the driver
4529implements (e.g. AX=0235h would mean that the driver implemented XMS version
45302.35). BX is set equal to the driver's internal revision number mainly for
4531debugging purposes. DX indicates the existence of the HMA (not its
4532availability) and is intended mainly for installation programs.
4533
4534 NOTE: This document defines version 3.00 of the specification.
4535
4536
4537Request High Memory Area (Function 01h):
4538----------------------------------------
4539
4540 ARGS: AH = 01h
4541 If the caller is a TSR or device driver,
4542 DX = Space needed in the HMA by the caller in bytes
4543 If the caller is an application program,
4544 DX = FFFFh
4545 RETS: AX = 0001h if the HMA is assigned to the caller, 0000h otherwise
4546 ERRS: BL = 80h if the function is not implemented
4547 BL = 81h if a VDISK device is detected
4548 BL = 90h if the HMA does not exist
4549 BL = 91h if the HMA is already in use
4550 BL = 92h if DX is less than the /HMAMIN= parameter
4551
4552 This function attempts to reserve the 64K-16 byte high memory area for
4553the caller. If the HMA is currently unused, the caller's size parameter is
4554compared to the /HMAMIN= parameter on the driver's command line. If the
4555value passed by the caller is greater than or equal to the amount specified
4556by the driver's parameter, the request succeeds. This provides the ability
4557to ensure that programs which use the HMA efficiently have priority over
4558those which do not.
4559
4560 NOTE: See the sections "Prioritizing HMA Usage" and "High Memory Area
4561 Restrictions" below for more information.
4562
4563
4564Release High Memory Area (Function 02h):
4565----------------------------------------
4566
4567 ARGS: AH = 02h
4568 RETS: AX = 0001h if the HMA is successfully released, 0000h otherwise
4569 ERRS: BL = 80h if the function is not implemented
4570 BL = 81h if a VDISK device is detected
4571 BL = 90h if the HMA does not exist
4572 BL = 93h if the HMA was not allocated
4573
4574 This function releases the high memory area and allows other programs to
4575use it. Programs which allocate the HMA must release it before exiting.
4576When the HMA has been released, any code or data stored in it becomes invalid
4577and should not be accessed.
4578
4579
4580Global Enable A20 (Function 03h):
4581---------------------------------
4582
4583 ARGS: AH = 03h
4584 RETS: AX = 0001h if the A20 line is enabled, 0000h otherwise
4585 ERRS: BL = 80h if the function is not implemented
4586 BL = 81h if a VDISK device is detected
4587 BL = 82h if an A20 error occurs
4588
4589 This function attempts to enable the A20 line. It should only be used
4590by programs which have control of the HMA. The A20 line should be turned
4591off via Function 04h (Global Disable A20) before a program releases control
4592of the system.
4593
4594 NOTE: On many machines, toggling the A20 line is a relatively slow
4595 operation.
4596
4597
4598Global Disable A20 (Function 04h):
4599----------------------------------
4600
4601 ARGS: AH = 04h
4602 RETS: AX = 0001h if the A20 line is disabled, 0000h otherwise
4603 ERRS: BL = 80h if the function is not implemented
4604 BL = 81h if a VDISK device is detected
4605 BL = 82h if an A20 error occurs
4606 BL = 94h if the A20 line is still enabled
4607
4608 This function attempts to disable the A20 line. It should only be used
4609by programs which have control of the HMA. The A20 line should be disabled
4610before a program releases control of the system.
4611
4612 NOTE: On many machines, toggling the A20 line is a relatively slow
4613 operation.
4614
4615
4616Local Enable A20 (Function 05h):
4617--------------------------------
4618
4619 ARGS: AH = 05h
4620 RETS: AX = 0001h if the A20 line is enabled, 0000h otherwise
4621 ERRS: BL = 80h if the function is not implemented
4622 BL = 81h if a VDISK device is detected
4623 BL = 82h if an A20 error occurs
4624
4625 This function attempts to enable the A20 line. It should only be used
4626by programs which need direct access to extended memory. Programs which use
4627this function should call Function 06h (Local Disable A20) before releasing
4628control of the system.
4629
4630 NOTE: On many machines, toggling the A20 line is a relatively slow
4631 operation.
4632
4633
4634Local Disable A20 (Function 06h):
4635---------------------------------
4636
4637 ARGS: AH = 06h
4638 RETS: AX = 0001h if the function succeeds, 0000h otherwise
4639 ERRS: BL = 80h if the function is not implemented
4640 BL = 81h if a VDISK device is detected
4641 BL = 82h if an A20 error occurs
4642 BL = 94h if the A20 line is still enabled
4643
4644 This function cancels a previous call to Function 05h (Local Enable
4645A20). It should only be used by programs which need direct access to
4646extended memory. Previous calls to Function 05h must be canceled before
4647releasing control of the system.
4648
4649 NOTE: On many machines, toggling the A20 line is a relatively slow
4650 operation.
4651
4652
4653Query A20 (Function 07h):
4654-------------------------
4655
4656 ARGS: AH = 07h
4657 RETS: AX = 0001h if the A20 line is physically enabled, 0000h otherwise
4658 ERRS: BL = 00h if the function succeeds
4659 BL = 80h if the function is not implemented
4660 BL = 81h if a VDISK device is detected
4661
4662 This function checks to see if the A20 line is physically enabled. It
4663does this in a hardware independent manner by seeing if "memory wrap" occurs.
4664
4665
4666Query Free Extended Memory (Function 08h):
4667------------------------------------------
4668
4669 ARGS: AH = 08h
4670 RETS: AX = Size of the largest free extended memory block in K-bytes
4671 DX = Total amount of free extended memory in K-bytes
4672 ERRS: BL = 80h if the function is not implemented
4673 BL = 81h if a VDISK device is detected
4674 BL = A0h if all extended memory is allocated
4675
4676 This function returns the size of the largest available extended memory
4677block in the system.
4678
4679 NOTE: The 64K HMA is not included in the returned value even if it is
4680 not in use.
4681
4682
4683Allocate Extended Memory Block (Function 09h):
4684----------------------------------------------
4685
4686 ARGS: AH = 09h
4687 DX = Amount of extended memory being requested in K-bytes
4688 RETS: AX = 0001h if the block is allocated, 0000h otherwise
4689 DX = 16-bit handle to the allocated block
4690 ERRS: BL = 80h if the function is not implemented
4691 BL = 81h if a VDISK device is detected
4692 BL = A0h if all available extended memory is allocated
4693 BL = A1h if all available extended memory handles are in use
4694
4695 This function attempts to allocate a block of the given size out of the
4696pool of free extended memory. If a block is available, it is reserved
4697for the caller and a 16-bit handle to that block is returned. The handle
4698should be used in all subsequent extended memory calls. If no memory was
4699allocated, the returned handle is null.
4700
4701 NOTE: Extended memory handles are scarce resources. Programs should
4702 try to allocate as few as possible at any one time. When all
4703 of a driver's handles are in use, any free extended memory is
4704 unavailable.
4705
4706
4707
4708Free Extended Memory Block (Function 0Ah):
4709------------------------------------------
4710
4711 ARGS: AH = 0Ah
4712 DX = Handle to the allocated block which should be freed
4713 RETS: AX = 0001h if the block is successfully freed, 0000h otherwise
4714 ERRS: BL = 80h if the function is not implemented
4715 BL = 81h if a VDISK device is detected
4716 BL = A2h if the handle is invalid
4717 BL = ABh if the handle is locked
4718
4719 This function frees a block of extended memory which was previously
4720allocated using Function 09h (Allocate Extended Memory Block). Programs
4721which allocate extended memory should free their memory blocks before
4722exiting. When an extended memory buffer is freed, its handle and all data
4723stored in it become invalid and should not be accessed.
4724
4725
4726Move Extended Memory Block (Function 0Bh):
4727------------------------------------------
4728
4729 ARGS: AH = 0Bh
4730 DS:SI = Pointer to an Extended Memory Move Structure (see below)
4731 RETS: AX = 0001h if the move is successful, 0000h otherwise
4732 ERRS: BL = 80h if the function is not implemented
4733 BL = 81h if a VDISK device is detected
4734 BL = 82h if an A20 error occurs
4735 BL = A3h if the SourceHandle is invalid
4736 BL = A4h if the SourceOffset is invalid
4737 BL = A5h if the DestHandle is invalid
4738 BL = A6h if the DestOffset is invalid
4739 BL = A7h if the Length is invalid
4740 BL = A8h if the move has an invalid overlap
4741 BL = A9h if a parity error occurs
4742
4743 Extended Memory Move Structure Definition:
4744
4745 ExtMemMoveStruct struc
4746 Length dd ? ; 32-bit number of bytes to transfer
4747 SourceHandle dw ? ; Handle of source block
4748 SourceOffset dd ? ; 32-bit offset into source
4749 DestHandle dw ? ; Handle of destination block
4750 DestOffset dd ? ; 32-bit offset into destination block
4751 ExtMemMoveStruct ends
4752
4753 This function attempts to transfer a block of data from one location to
4754another. It is primarily intended for moving blocks of data between
4755conventional memory and extended memory, however it can be used for moving
4756blocks within conventional memory and within extended memory.
4757
4758 NOTE: If SourceHandle is set to 0000h, the SourceOffset is interpreted
4759 as a standard segment:offset pair which refers to memory that is
4760 directly accessible by the processor. The segment:offset pair
4761 is stored in Intel DWORD notation. The same is true for DestHandle
4762 and DestOffset.
4763
4764 SourceHandle and DestHandle do not have to refer to locked memory
4765 blocks.
4766
4767 Length must be even. Although not required, WORD-aligned moves
4768 can be significantly faster on most machines. DWORD aligned move
4769 can be even faster on 80386 machines.
4770
4771 If the source and destination blocks overlap, only forward moves
4772 (i.e. where the source base is less than the destination base) are
4773 guaranteed to work properly.
4774
4775 Programs should not enable the A20 line before calling this
4776 function. The state of the A20 line is preserved.
4777
4778 This function is guaranteed to provide a reasonable number of
4779 interrupt windows during long transfers.
4780
4781
4782Lock Extended Memory Block (Function 0Ch):
4783------------------------------------------
4784
4785 ARGS: AH = 0Ch
4786 DX = Extended memory block handle to lock
4787 RETS: AX = 0001h if the block is locked, 0000h otherwise
4788 DX:BX = 32-bit physical address of the locked block
4789 ERRS: BL = 80h if the function is not implemented
4790 BL = 81h if a VDISK device is detected
4791 BL = A2h if the handle is invalid
4792 BL = ACh if the block's lock count overflows
4793 BL = ADh if the lock fails
4794
4795 This function locks an extended memory block and returns its base
4796address as a 32-bit physical address. Locked memory blocks are guaranteed not
4797to move. The 32-bit pointer is only valid while the block is locked.
4798Locked blocks should be unlocked as soon as possible.
4799
4800 NOTE: A block does not have to be locked before using Function 0Bh (Move
4801 Extended Memory Block).
4802
4803 "Lock counts" are maintained for EMBs.
4804
4805
4806
4807Unlock Extended Memory Block (Function 0Dh):
4808--------------------------------------------
4809
4810 ARGS: AH = 0Dh
4811 DX = Extended memory block handle to unlock
4812 RETS: AX = 0001h if the block is unlocked, 0000h otherwise
4813 ERRS: BL = 80h if the function is not implemented
4814 BL = 81h if a VDISK device is detected
4815 BL = A2h if the handle is invalid
4816 BL = AAh if the block is not locked
4817
4818 This function unlocks a locked extended memory block. Any 32-bit
4819pointers into the block become invalid and should no longer be used.
4820
4821
4822Get EMB Handle Information (Function 0Eh):
4823------------------------------------------
4824
4825 ARGS: AH = 0Eh
4826 DX = Extended memory block handle
4827 RETS: AX = 0001h if the block's information is found, 0000h otherwise
4828 BH = The block's lock count
4829 BL = Number of free EMB handles in the system
4830 DX = The block's length in K-bytes
4831 ERRS: BL = 80h if the function is not implemented
4832 BL = 81h if a VDISK device is detected
4833 BL = A2h if the handle is invalid
4834
4835 This function returns additional information about an extended memory
4836block to the caller.
4837
4838 NOTE: To get the block's base address, use Function 0Ch (Lock Extended
4839 Memory Block).
4840
4841
4842Reallocate Extended Memory Block (Function 0Fh):
4843------------------------------------------------
4844
4845 ARGS: AH = 0Fh
4846 BX = New size for the extended memory block in K-bytes
4847 DX = Unlocked extended memory block handle to reallocate
4848 RETS: AX = 0001h if the block is reallocated, 0000h otherwise
4849 ERRS: BL = 80h if the function is not implemented
4850 BL = 81h if a VDISK device is detected
4851 BL = A0h if all available extended memory is allocated
4852 BL = A1h if all available extended memory handles are in use
4853 BL = A2h if the handle is invalid
4854 BL = ABh if the block is locked
4855
4856 This function attempts to reallocate an unlocked extended memory block
4857so that it becomes the newly specified size. If the new size is smaller
4858than the old block's size, all data at the upper end of the old block is
4859lost.
4860
4861
4862Request Upper Memory Block (Function 10h):
4863------------------------------------------
4864
4865 ARGS: AH = 10h
4866 DX = Size of requested memory block in paragraphs
4867 RETS: AX = 0001h if the request is granted, 0000h otherwise
4868 BX = Segment number of the upper memory block
4869 If the request is granted,
4870 DX = Actual size of the allocated block in paragraphs
4871 otherwise,
4872 DX = Size of the largest available UMB in paragraphs
4873 ERRS: BL = 80h if the function is not implemented
4874 BL = B0h if a smaller UMB is available
4875 BL = B1h if no UMBs are available
4876
4877 This function attempts to allocate an upper memory block to the caller.
4878If the function fails, the size of the largest free UMB is returned in DX.
4879
4880 NOTE: By definition UMBs are located below the 1MB address boundary.
4881 The A20 Line does not need to be enabled before accessing an
4882 allocated UMB.
4883
4884 UMBs are paragraph aligned.
4885
4886 To determine the size of the largest available UMB, attempt to
4887 allocate one with a size of FFFFh.
4888
4889 UMBs are unaffected by EMS calls.
4890
4891
4892Release Upper Memory Block (Function 11h):
4893------------------------------------------
4894
4895 ARGS: AH = 11h
4896 DX = Segment number of the upper memory block
4897 RETS: AX = 0001h if the block was released, 0000h otherwise
4898 ERRS: BL = 80h if the function is not implemented
4899 BL = B2h if the UMB segment number is invalid
4900
4901 This function frees a previously allocated upper memory block. When an
4902UMB has been released, any code or data stored in it becomes invalid and
4903should not be accessed.
4904
4905
4906
4907
4908Reallocate Upper Memory Block (Function 12h)
4909
4910 ARGS:
4911 AH = 12h
4912 BX = New size for UMB in paragraphs
4913 DX = Segment number of the UMB to reallocate
4914 RETS:
4915 AX = 1 if the block was reallocated, 0 otherwise
4916 ERRS:
4917 BL = 80h if the function is not implemented
4918 BL = B0h if no UMB large enough to satisfy the request is available.
4919 In this event, DX is returned with the size of the largest UMB that is available.
4920 BL = B2h if the UMB segment number is invalid
4921
4922This function attempts to reallocate an Upper Memory Block to a newly specified size. If the new size is smaller than the old block's size, all data at the upper end of the block is lost.
4923
4924
4925
4926Super Extended Memory Support
4927
4928These changes are intended to provide support for extended memory pools up to 4 Gb in size. The current XMS API, since it uses 16-bit values to specify block sizes in Kb, is limited to 64 Mb maximum block size. Future machines are expected to support memory above 64 MB.
4929
4930This support is implemented in the form of extensions to existing functions, rather than entirely new entry points, to allow for more efficient implementations.
4931
4932Programs should generally use the existing functions, instead of these extended ones, unless they have an explicit need to deal with memory above 64 Mb.
4933
4934
4935Query Any Free Extended Memory (Function 88h)
4936
4937 Entry:
4938 AH = 88h
4939 Exit:
4940 EAX = Size of largest free extended memory block in Kb.
4941 BL = 0 if no error occurs, otherwise it takes an error code.
4942 ECX = Highest ending address of any memory block.
4943 EDX = Total amount of free memory in Kb.
4944 Errors:
4945 BL = 80h if the function is not implemented.
4946 BL = 81h if a VDISK device is detected.
4947 BL = A0h if all extended memory is allocated.
4948
4949This function uses 32-bit values to return the size of available memory, thus allowing returns up to 4GByte. Additionally, it returns the highest known physical memory address, that is, the physical address of the last byte of memory. There may be discontinuities in the memory map below this address.
4950
4951The memory pool reported on is the same as that reported on by the existing Query Free Extended Memory function. If the highest memory address is not more than 64 Mb, then these two functions will return the same results.
4952
4953Because of its reliance on 32-bit registers, this function is only available on 80386 and higher processors. XMS drivers on 80286 machines should return error code 80h if this function is called.
4954
4955If error code 81h is returned, the value in ECX will still be valid. If error code A0h is returned, EAX and EDX will be 0, and ECX will still be valid.
4956
4957
4958Allocate Any Extended Memory (Function 89h)
4959
4960 Entry:
4961 AH = 89h
4962 EDX = Amount of extended memory requested, in Kb.
4963 Exit:
4964 AX = 1 if the block is allocated, 0 if not
4965 DX = Handle to allocated block.
4966 Errors:
4967 BL = 80h if the function is not implemented.
4968 BL = 81h if a VDISK device is detected.
4969 BL = A0h if all available extended memory is allocated.
4970 BL = A1h if all available extended memory handles are in use.
4971
4972This function is similar to the existing Allocate Extended Memory, except that it uses a 32-bit instead of a 16-bit value to specify the amount of memory requested. It allocates from the same memory and handle pool as the current function. Since it requires a 32-bit register, this function can be supported only on 80386 and higher processors, and XMS drivers on 80286 machines should return error code 80h.
4973
4974
4975Get Extended EMB Handle Information (Function 8Eh)
4976
4977 Entry:
4978 AH = 8Eh
4979 DX = Extended memory block handle.
4980 Exit:
4981 AX = 1 if the block's information is found, 0 if not
4982 BH = Block lock count
4983 CX = Number of free EMB handles in the system
4984 EDX = Block's length in Kb.
4985 Errors:
4986 BL = 80h if the function is not implemented.
4987 BL = 81h if a VDISK device is detected.
4988 BL = A2h if the handle is invalid.
4989
4990This function is similar to the Get EMB Handle Information function. Since it uses a 32-bit register to report the block size, it can be used to get information on blocks larger than 64 Mb. It also uses a 16-bit instead of 8-bit register to report the number of free handles, allowing the handle pool to be extended beyond 256 entries.
4991
4992Because of its reliance on a 32-bit register, this function is available on 80386 and higher processors. XMS drivers on 80286 machines should return error code 80h if this function is called.
4993
4994
4995Reallocate Any Extended Memory (Function 8Fh)
4996
4997 Entry:
4998 AH = 8Fh
4999 EBX = New size for extended memory block, in Kb.
5000 DX = Unlocked handle for memory block to be resized.
5001 Exit:
5002 AX = 1 if the block is reallocated, 0 if not
5003 Errors:
5004 BL = 80h if the function is not implemented.
5005 BL = 81h if a VDISK device is detected.
5006 BL = A0h if all available extended memory is allocated.
5007 BL = A1h if all available extended memory handles are in use.
5008 BL = A2h if the handle is invalid.
5009 BL = ABh if the block is locked.
5010
5011This function is similar to the existing Reallocate Extended Memory, except that it uses a 32-bit instead of a 16-bit value to specify the amount of memory requested. It allocates from the same memory and handle pool as the current function. Since it requires a 32-bit register, this function can be supported only on 80386 and higher processors, and XMS drivers on 80286 machines should return error code 80h.
5012
5013
5014
5015
5016PRIORITIZING HMA USAGE:
5017-----------------------
5018
5019 For DOS users to receive the maximum benefit from the High Memory Area,
5020programs which use the HMA must store as much of their resident code in it as
5021is possible. It is very important that developers realize that the HMA is
5022allocated as a single unit.
5023
5024 For example, a TSR program which grabs the HMA and puts 10K of code into
5025it may prevent a later TSR from putting 62K into the HMA. Obviously, regular
5026DOS programs would have more memory available to them below the 640K line if
5027the 62K TSR was moved into the HMA instead of the 10K one.
5028
5029 The first method for dealing with conflicts such as this is to require
5030programs which use the HMA to provide a command line option for disabling
5031this feature. It is crucial that TSRs which do not make full use of the HMA
5032provide such a switch on their own command line (suggested name "/NOHMA").
5033
5034 The second method for optimizing HMA usage is through the /HMAMIN=
5035parameter on the XMS device driver line. The number after the parameter
5036is defined to be the minimum amount of HMA space (in K-bytes) used by any
5037driver or TSR. For example, if "DEVICE=HIMEM.SYS /HMAMIN=48" is in a
5038user's CONFIG.SYS file, only programs which request at least 48K would be
5039allowed to allocate the HMA. This number can be adjusted either by
5040installation programs or by the user himself. If this parameter is not
5041specified, the default value of 0 is used causing the HMA to be allocated
5042on a first come, first served basis.
5043
5044 Note that this problem does not impact application programs. If the HMA
5045is available when an application program starts, the application is free to
5046use as much or as little of the HMA as it wants. For this reason,
5047applications should pass FFFFh in DX when calling Function 01h.
5048
5049
5050
5051HIGH MEMORY AREA RESTRICTIONS:
5052------------------------------
5053
5054- Far pointers to data located in the HMA cannot be passed to DOS. DOS
5055 normalizes any pointer which is passed into it. This will cause data
5056 addresses in the HMA to be invalidated.
5057
5058- Disk I/O directly into the HMA (via DOS, INT 13h, or otherwise) is not
5059 recommended.
5060
5061- Programs, especially drivers and TSRs, which use the HMA *MUST* use
5062 as much of it as possible. If a driver or TSR is unable to use at
5063 least 90% of the available HMA (typically ~58K), they must provide
5064 a command line switch for overriding HMA usage. This will allow
5065 the user to configure his machine for optimum use of the HMA.
5066
5067- Device drivers and TSRs cannot leave the A20 line permanently turned
5068 on. Several applications rely on 1MB memory wrap and will overwrite the
5069 HMA if the A20 line is left enabled potentially causing a system crash.
5070
5071- Interrupt vectors must not point into the HMA. This is a result of
5072 the previous restriction. Note that interrupt vectors can point into
5073 any allocated upper memory blocks however.
5074
5075ERROR CODE INDEX:
5076-----------------
5077
5078If AX=0000h when a function returns and the high bit of BL is set,
5079
5080 BL=80h if the function is not implemented
5081 81h if a VDISK device is detected
5082 82h if an A20 error occurs
5083 8Eh if a general driver error occurs
5084 8Fh if an unrecoverable driver error occurs
5085 90h if the HMA does not exist
5086 91h if the HMA is already in use
5087 92h if DX is less than the /HMAMIN= parameter
5088 93h if the HMA is not allocated
5089 94h if the A20 line is still enabled
5090 A0h if all extended memory is allocated
5091 A1h if all available extended memory handles are in use
5092 A2h if the handle is invalid
5093 A3h if the SourceHandle is invalid
5094 A4h if the SourceOffset is invalid
5095 A5h if the DestHandle is invalid
5096 A6h if the DestOffset is invalid
5097 A7h if the Length is invalid
5098 A8h if the move has an invalid overlap
5099 A9h if a parity error occurs
5100 AAh if the block is not locked
5101 ABh if the block is locked
5102 ACh if the block's lock count overflows
5103 ADh if the lock fails
5104 B0h if a smaller UMB is available
5105 B1h if no UMBs are available
5106 B2h if the UMB segment number is invalid
5107
5108
5109IMPLEMENTATION NOTES FOR DOS XMS DRIVERS:
5110-----------------------------------------
5111
5112- A DOS XMS driver's control function must begin with code similar to the
5113 following:
5114
5115XMMControl proc far
5116
5117 jmp short XCControlEntry ; For "hookability"
5118 nop ; NOTE: The jump must be a short
5119 nop ; jump to indicate the end of
5120 nop ; any hook chainThe nop's
5121 ; allow a far jump to be
5122 ; patched in.
5123XCControlEntry:
5124
5125
5126- XMS drivers must preserve all registers except those containing
5127 returned values across any function call.
5128
5129- XMS drivers are required to hook INT 15h and watch for calls to
5130 functions 87h (Block Move) and 88h (Extended Memory Available). The
5131 INT 15h Block Move function must be hooked so that the state of the A20
5132 line is preserved across the call. The INT 15h Extended Memory
5133 Available function must be hooked to return 0h to protect the HMA.
5134
5135- In order to maintain compatibility with existing device drivers, DOS XMS
5136 drivers must not hook INT 15h until the first non-Version Number call
5137 to the control function is made.
5138
5139- XMS drivers are required to check for the presence of drivers which
5140 use the IBM VDISK allocation scheme. Note that it is not sufficient to
5141 check for VDISK users at installation time but at the time when the HMA
5142 is first allocated. If a VDISK user is detected, the HMA must not be
5143 allocated. Microsoft will publish a standard method for detecting
5144 drivers which use the VDISK allocation scheme.
5145
5146- XMS drivers which have a fixed number of extended memory handles (most
5147 do) should implement a command line parameter for adjusting that number
5148 (suggested name "/NUMHANDLES=")
5149
5150- XMS drivers should make sure that the major DOS version number is
5151 greater than or equal to 3 before installing themselves.
5152
5153- UMBs cannot occupy memory addresses that can be banked by EMS 4.0.
5154 EMS 4.0 takes precedence over UMBs for physically addressable memory.
5155
5156- All driver functions must be re-entrant. Care should be taken to not
5157 leave interrupts disabled for long periods of time.
5158
5159- Allocation of a zero length extended memory buffer is allowed. Programs
5160 which hook XMS drivers may need to reserve a handle for private use via
5161 this method. Programs which hook an XMS driver should pass all requests
5162 for zero length EMBs to the next driver in the chain.
5163
5164- Drivers should control the A20 line via an "enable count." Local En-
5165 able only enables the A20 line if the count is zero. It then increments
5166 the count. Local Disable only disables A20 if the count is one. It
5167 then decrements the count. Global Enable/Disable keeps a flag which
5168 indicates the state of A20. They use Local Enable/Disable to actually
5169 change the state.
5170
5171- Drivers should always check the physical A20 state in the local Enable-Disable calls, to see
5172 that the physical state matches the internal count. If the physical state does not match, it should
5173 be modified so that it matches the internal count. This avoids problems with applications that
5174 modify A20 directly.
5175
5176
5177IMPLEMENTATION OF CODE FOR HOOKING THE XMS DRIVER:
5178
5179 In order to support the hooking of the XMS driver by multiple
5180 pieces of code, the following code sample should be followed.
5181 Use of other methods for hooking the XMS driver will not work
5182 in many cases. This method is the official supported one.
5183
5184 The basic strategy is:
5185
5186 Find the XMS driver header which has the "near jump" dispatch.
5187
5188 Patch the near jump to a FAR jump which jumps to my HOOK XMS
5189 driver header.
5190
5191 NOTES:
5192
5193 o This architecture allows the most recent HOOKer to undo his
5194 XMS driver hook at any time without having to worry about
5195 damaging a "hook chain".
5196
5197 o This architecture allows the complete XMS hook chain to be
5198 enumerated at any time. There are no "hidden hooks".
5199
5200 o This architecture allows the HOOKer to not have to worry
5201 about installing an "INT 2F hook" to hook the AH=43h
5202 INT 2Fs handled by the XMS driver. The base XMS driver
5203 continues to be the only one installed on INT 2Fh AH=43h.
5204
5205 This avoids all of the problems of undoing a software
5206 interrupt hook.
5207
5208 ;
5209 ; When I wish to CHAIN to the previous XMS driver, I execute a FAR JMP
5210 ; to the address stored in this DWORD.
5211 ;
5212 PrevXMSControlAddr dd ?
5213
5214 ;
5215 ; The next two data items are needed ONLY if I desire to be able to undo
5216 ; my XMS hook.
5217 ; PrevXMSControlJmpVal stores the previos XMS dispatch near jump offset
5218 ; value that is used to unhook my XMS hook
5219 ; PrevXMSControlBase stores the address of the XMS header that I hooked
5220 ;
5221 PrevXMSControlBase dd ?
5222 PrevXMSControlJmpVal db ?
5223
5224 ;
5225 ; This is MY XMS control header.
5226 ;
5227 MyXMSControlFunc proc FAR
5228 jmp short XMSControlEntry
5229 nop
5230 nop
5231 nop
5232 XMSControlEntry:
5233
5234 ......
5235
5236 Chain:
5237 jmp cs:[PrevXMSControlAddr]
5238
5239 MyXMSControlFunc endp
5240
5241
5242 .......
5243 ;
5244 ; This is the code which installs my hook into the XMS driver.
5245 ;
5246 ;
5247 ; See if there is an XMS driver to hook
5248 ;
5249 mov ax,4300h
5250 int 2Fh
5251 cmp al,80h
5252 jne NoXMSDrvrToHookError
5253 ;
5254 ; Get the current XMS driver Control address
5255 ;
5256 mov ax,4310h
5257 int 2Fh
5258 NextXMSHeader:
5259 mov word ptr [PrevXMSControlAddr+2],es
5260 mov word ptr [PrevXMSControlBase+2],es
5261 mov word ptr [PrevXMSControlBase],bx
5262 mov cx,word ptr es:[bx]
5263 cmp cl,0EBh ; Near JUMP
5264 je ComputeNearJmp
5265 cmp cl,0EAh ; Far JUMP
5266 jne XMSDrvrChainMessedUpError
5267 ComputeFarJmp:
5268 mov si,word ptr es:[bx+1] ; Offset of jump
5269 mov es,word ptr es:[bx+1+2] ; Seg of jump
5270 mov bx,si
5271 jmp short NextXMSHeader
5272
5273 ComputeNearJmp:
5274 cmp word ptr es:[bx+2],9090h ; Two NOPs?
5275 jne XMSDrvrChainMessedUpError ; No
5276 cmp byte ptr es:[bx+4],90h ; Total of 3 NOPs?
5277 jne XMSDrvrChainMessedUpError ; No
5278 mov di,bx ; Save pointer to header
5279 xor ax,ax
5280 mov al,ch ; jmp addr of near jump
5281 mov [PrevXMSControlJmpVal],al
5282 add ax,2 ; NEAR JMP is 2 byte instruction
5283 add bx,ax ; Target of jump
5284 mov word ptr [PrevXMSControlAddr],bx
5285 ;
5286 ; Now INSTALL my XMS HOOK
5287 ;
5288 cli ; Disable INTs in case someone calls
5289 ; XMS at interrupt time
5290 mov byte ptr es:[di],0EAh ; Far Immed. JUMP instruction
5291 mov word ptr es:[di+1],offset MyXMSControlFunc
5292 mov word ptr es:[di+3],cs
5293 sti
5294 .....
5295
5296 ;
5297 ; Deinstall my XMS hook. This can be done IF AND ONLY IF my XMS header
5298 ; still contains the near jump dispatch
5299 ;
5300 cmp byte ptr [MyXMSControlFunc],0EBh
5301 jne CantDeinstallError
5302 mov al,0EBh
5303 mov ah,[PrevXMSControlJmpVal]
5304 les bx,[PrevXMSControlBase]
5305 cli ; Disable INTs in case someone calls
5306 ; XMS at interrupt time
5307 mov word ptr es:[bx],ax
5308 mov word ptr es:[bx+2],9090h
5309 mov byte ptr es:[bx+4],90h
5310 sti
5311 ....
5312
5313IMPLEMENTATION NOTES FOR HIMEM.SYS:
5314-----------------------------------
5315
5316- HIMEM.SYS currently supports true AT-compatibles, 386 AT machines, IBM
5317 PS/2s, AT&T 6300 Plus systems and Hewlett Packard Vectras.
5318
5319- If HIMEM finds that it cannot properly control the A20 line or if there
5320 is no extended memory available when HIMEM.SYS is invoked, the driver
5321 does not install itself. HIMEM.SYS displays the message "High Memory
5322 Area Unavailable" when this situation occurs.
5323
5324- If HIMEM finds that the A20 line is already enabled when it is invoked,
5325 it will NOT change the A20 line's state. The assumption is that whoever
5326 enabled it knew what they were doing. HIMEM.SYS displays the message "A20
5327 Line Permanently Enabled" when this situation occurs.
5328
5329- HIMEM.SYS is incompatible with IBM's VDISK.SYS driver and other drivers
5330 which use the VDISK scheme for allocating extended memory. However,
5331 HIMEM does attempt to detect these drivers and will not allocate the
5332 HMA if one is found.
5333
5334- HIMEM.SYS supports the optional "/HMAMIN=" parameter. The valid values
5335 are decimal numbers between 0 and 63.
5336
5337- By default, HIMEM.SYS has 32 extended memory handles available for use.
5338 This number may be adjusted with the "/NUMHANDLES=" parameter. The
5339 maximum value for this parameter is 128 and the minimum is 0. Each
5340 handle currently requires 6 bytes of resident space.
5341
5342
5343Copyright (c) 1988, Microsoft Corporation
5344
5345
5346ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5347 INTRO TO DMA by Draeden of VLA
5348ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5349
5350
5351 DMA means Direct Memory Access. You probably already know where and
5352why you use it, so I'll skip right down to the dirty stuff. This all
5353should speak for it's self, so... Enjoy.
5354
5355 Draeden /VLA
5356
5357ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5358
5359 To do a DMA transfer, you need to know a few things:
5360
5361 1) Address of the memory to access
5362
5363 2) Length of data to read/write
5364
5365 This can all be put into a structure:
5366
5367STRUC DMAInfo
5368 Page db ?
5369 Offset dw ?
5370 Length dw ?
5371ENDS
5372
5373 Page is the highest 4 bits of the absolute 20 bit address of the memory
5374location. Note that DMA transfers CANNOT cross 64k page boundries.
5375
5376 The Length is actually LENGTH-1; sending in a 0 will move 1 byte,
5377sending a 0FFFFh will move 64k.
5378
5379 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5380 ; IN: DX:AX = segment/offset address of memory area
5381 ;
5382 ;OUT: DH = Page (0-F) (DL is destroyed)
5383 ; AX = Offset
5384 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5385PROC MakePage
5386 push bx
5387
5388 mov bl,dh
5389 shr bl,4 ;isolate upper 4 bits of segment
5390
5391 shl dx,4 ;make segment into ABS address
5392 add ax,dx ;add the offset and put it in AX
5393 adc bl,0 ;complete the addition
5394
5395 mov dh,bl ;put the PAGE where it goes
5396
5397 pop bx ; DH:AX is now the PAGE:OFFSET address
5398 ret
5399ENDP
5400
5401ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5402 Programming DMA channels 0 thru 3
5403ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5404 There are 3 ports that are DMA channel specific:
5405
5406 1) The Page register
5407 2) The DMA count (length) register
5408 3) The memory address (offset register)
5409
5410 They are as follows:
5411
5412DMACH PAGE ADDRESS LENGTH
5413
5414 0 87h 0 1
5415
5416 1 83h 2 3
5417
5418 2 81h 4 5
5419
5420 3 82h 6 7
5421
5422
5423 And now some general registers:
5424
5425 DMA Mask Register: 0Ah
5426ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5427 bit 7 - 3 = 0 Reserved
5428
5429 bit 2 = 0 clear mask
5430 = 1 set mask
5431
5432 bits 1 - 0 = 00 Select channel 0
5433 = 01 select channel 1
5434 = 10 select channel 2
5435 = 11 select channel 3
5436
5437 USE: You must set the mask of the channel before you
5438 can reprogram it.
5439
5440 DMA Mode Register: 0Bh
5441ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5442 bit 7 - 6 = 00 Demand mode
5443 = 01 Signal mode
5444 = 10 Block mode
5445 = 11 Cascade mode
5446
5447 bit 5 - 4 = 0 Reserved
5448
5449 bit 3 - 2 = 00 Verify operation
5450 = 01 Write operation
5451 = 10 Read operation
5452 = 11 Reserved
5453
5454 bits 1 - 0 = 00 Select channel 0
5455 = 01 select channel 1
5456 = 10 select channel 2
5457 = 11 select channel 3
5458
5459 USE: Tell the DMAC what to do. Common modes are:
5460
5461 48h (Read operation, Signal mode)
5462 Used to read data from host memory and send to whomever
5463 polls it.
5464
5465 44h (Write operation, Signal mode)
5466 Used to write data taken from a device to memory.
5467
5468DMA clear byte ptr: 0Ch
5469ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5470 USE: Send a zero to reset the internal ptrs
5471
5472
5473
5474 WHAT TO DO:
5475ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5476
5477 1) Set the Mask bit for the channel
5478
5479 mov al,4
5480 add al,[DMA_Channel]
5481 out 0ah,al
5482
5483 2) Clear Byte Ptr
5484
5485 sub al,al
5486 out 0Ch,al
5487
5488 3) Set the DMA transfer mode
5489
5490 mov al,48h ;MODE output (read)
5491 add al,[DMA_Channel]
5492 out 0Bh,al
5493
5494 4) Set the memory ADDRESS and LENGTH
5495
5496 ; AX = offset
5497 ; CX = Length
5498 ;[DMA_Base] = port # of memory address
5499
5500 mov dx,[DMA_Base]
5501 out dx,al ;send lower byte address
5502 mov al,ah
5503 out dx,al ;send high byte address
5504
5505 inc dl ;point to Count port
5506 mov al,cl
5507 out dx,al ;send low byte length
5508 mov al,ch
5509 out dx,al ;send high byte length
5510
5511 5) Set the DMA page
5512
5513 ; AL = Page
5514
5515 mov dx,[Dma_Page]
5516 out dx,al ; write the Page
5517
5518 6) Clear DMA mask bit
5519
5520 mov al,[byte DMA_Channel]
5521 out 0Ah,al ; port 0Ah, DMA-1 mask reg bit
5522
5523 7) Program the other device that is going to use the DMA output/input
5524
5525
5526 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5527 ; This routine programs the DMAC for channels 0-3
5528 ;
5529 ; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
5530 ; [DAMBaseAdd] = Memory Address port
5531 ;
5532 ; dh = mode
5533 ; ax = address
5534 ; cx = length
5535 ; dl = page
5536 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5537PROC Prog_DMA03 NEAR
5538 push bx
5539 mov bx,ax
5540
5541 mov al,4
5542 add al,[DMA_Channel]
5543 out 0Ah,al ; mask reg bit
5544
5545 sub al,al
5546 out 0Ch,al ; clr byte ptr
5547
5548 mov al,dh
5549 add al,[DMA_Channel]
5550 out 0Bh,al ; set mode reg
5551
5552 push dx
5553
5554 mov dx,[DMAbaseAdd]
5555 mov al,bl
5556 out dx,al ; set base address low
5557 mov al,bh
5558 out dx,al ; set base address high
5559
5560 inc dx ;point to length
5561 mov al,cl
5562 out dx,al ; set length low
5563 mov al,ch
5564 out dx,al ; set length high
5565
5566 pop dx
5567
5568 mov al,dl
5569 mov dx,[DmaPageReg]
5570 out dx,al ; set DMA page reg
5571
5572 mov al,[DMA_Channel]
5573 out 0Ah,al ; unmask (activate) dma channel
5574 pop bx
5575 ret
5576ENDP
5577
5578ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5579ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5580 Programming DMA channels 4 thru 7
5581ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5582ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5583
5584 Again, there are 3 ports that are DMA channel specific:
5585
5586 1) The Page register
5587 2) The DMA count (length) register
5588 3) The memory address (offset register
5589
5590 They are as follows:
5591
5592DMACH PAGE ADDRESS LENGTH
5593
5594 4 8Fh C0h C2h
5595
5596 5 8Bh C4h C6h
5597
5598 6 89h C8h CAh
5599
5600 7 8Ah CCh CEh
5601
5602
5603 And now some general registers:
5604
5605 DMA Mask Register: 0D4h
5606ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5607 bit 7 - 3 = 0 Reserved
5608
5609 bit 2 = 0 clear mask
5610 = 1 set mask
5611
5612 bits 1 - 0 = 00 Select channel 4
5613 = 01 select channel 5
5614 = 10 select channel 6
5615 = 11 select channel 7
5616
5617 USE: You must set the mask of the channel before you
5618 can reprogram it.
5619
5620 DMA Mode Register: 0D6h
5621ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5622 bit 7 - 6 = 00 Demand mode
5623 = 01 Signal mode
5624 = 10 Block mode
5625 = 11 Cascade mode
5626
5627 bit 5 - 4 = 0 Reserved
5628
5629 bit 3 - 2 = 00 Verify operation
5630 = 01 Write operation
5631 = 10 Read operation
5632 = 11 Reserved
5633
5634 bits 1 - 0 = 00 Select channel 4
5635 = 01 select channel 5
5636 = 10 select channel 6
5637 = 11 select channel 7
5638
5639 USE: Tell the DMAC what to do. Common modes are:
5640
5641 48h (Read operation, Signal mode)
5642 Used to read data from host memory and send to whomever
5643 polls it.
5644
5645 44h (Write operation, Signal mode)
5646 Used to write data taken from a device to memory.
5647
5648DMA clear byte ptr: 0D8h
5649ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5650 USE: Send a zero to reset the internal ptrs
5651
5652
5653 WHAT TO DO: (exactly the same thing, just different io PORTs)
5654ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5655
5656 1) Set the Mask bit for the channel
5657
5658 mov al,[DMA_Channel] ;because the DMA's are 4-7, bit #3
5659 out 0D4h,al ; is already set
5660
5661 2) Clear Byte Ptr
5662
5663 sub al,al
5664 out 0D8h,al
5665
5666 3) Set the DMA transfer mode
5667
5668 mov al,[DMA_Channel]
5669 sub al,4
5670 or al,48h ;MODE output (read)
5671 out 0D6h,al
5672
5673 4) Set the memory ADDRESS and LENGTH
5674
5675 ; AX = offset
5676 ; CX = Length
5677 ;[DMA_Base] = port # of memory address
5678
5679 mov dx,[DMA_Base]
5680 out dx,al ;send lower byte address
5681 mov al,ah
5682 out dx,al ;send high byte address
5683
5684 add dl,2 ;point to Count port (seperated by 2)
5685 mov al,cl
5686 out dx,al ;send low byte length
5687 mov al,ch
5688 out dx,al ;send high byte length
5689
5690 5) Set the DMA page
5691
5692 ; AL = Page
5693
5694 mov dx,[Dma_Page]
5695 out dx,al ; write the Page
5696
5697 6) Clear DMA mask bit
5698
5699 mov al,[byte DMA_Channel]
5700 and al,00000011b
5701 out 0d4h,al ; port 0Ah, DMA-1 mask reg bit
5702
5703 7) Program the other device that is going to use the DMA output/input
5704
5705
5706 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5707 ; This routine programs the DMAC for channels 4-7
5708 ;
5709 ; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
5710 ; [DAMBaseAdd] = Memory Address port
5711 ;
5712 ; dh = mode
5713 ; ax = address
5714 ; cx = length
5715 ; dl = page
5716 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5717PROC Prog_DMA47 NEAR
5718 push bx
5719 mov bx,ax
5720
5721 mov al,[DMA_Channel]
5722 out 0D4h,al ; mask reg bit
5723
5724 sub al,al
5725 out 0D8h,al ; clr byte ptr
5726
5727 mov al,[DMA_Channel]
5728 sub al,4
5729 add al,dh
5730 out 0D6h,al ; set mode reg
5731
5732 push dx
5733
5734 mov dx,[DMAbaseAdd]
5735 mov al,bl
5736 out dx,al ; set base address low
5737 mov al,bh
5738 out dx,al ; set base address high
5739
5740 add dl,2 ;point to length
5741 mov al,cl
5742 out dx,al ; set length low
5743 mov al,ch
5744 out dx,al ; set length high
5745
5746 pop dx
5747
5748 mov al,dl
5749 mov dx,[DmaPageReg]
5750 out dx,al ; set DMA page reg
5751
5752 mov al,[DMA_Channel]
5753 and al,00000011b
5754 out 0D4h,al ; unmask (activate) dma channel
5755 pop bx
5756 ret
5757ENDP
5758
5759 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5760 ; This routine programs the DMAC for channels 0-7
5761 ;
5762 ; IN: [DMA_Channel], [DMAbaseAdd], [DMApageReg] must be setup
5763 ; [DAMBaseAdd] = Memory Address port
5764 ;
5765 ; dh = mode
5766 ; ax = address
5767 ; cx = length
5768 ; dl = page
5769 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5770PROC Prog_DMA NEAR
5771 push bx
5772 mov bx,ax
5773
5774 cmp [DMA_Channel],4
5775 jb @@DoDMA03
5776
5777 mov al,[DMA_Channel]
5778 out 0D4h,al ; mask reg bit
5779
5780 sub al,al
5781 out 0D8h,al ; clr byte ptr
5782
5783 mov al,[DMA_Channel]
5784 sub al,4
5785 add al,dh
5786 out 0D6h,al ; set mode reg
5787
5788 push dx
5789
5790 mov dx,[DMAbaseAdd]
5791 mov al,bl
5792 out dx,al ; set base address low
5793 mov al,bh
5794 out dx,al ; set base address high
5795
5796 add dl,2 ;point to length
5797 mov al,cl
5798 out dx,al ; set length low
5799 mov al,ch
5800 out dx,al ; set length high
5801
5802 pop dx
5803
5804 mov al,dl
5805 mov dx,[DmaPageReg]
5806 out dx,al ; set DMA page reg
5807
5808 mov al,[DMA_Channel]
5809 and al,00000011b
5810 out 0D4h,al ; unmask (activate) dma channel
5811 pop bx
5812 ret
5813
5814@@DoDMA03:
5815 mov al,4
5816 add al,[DMA_Channel]
5817 out 0Ah,al ; mask reg bit
5818
5819 sub al,al
5820 out 0Ch,al ; clr byte ptr
5821
5822 mov al,dh
5823 add al,[DMA_Channel]
5824 out 0Bh,al ; set mode reg
5825
5826 push dx
5827
5828 mov dx,[DMAbaseAdd]
5829 mov al,bl
5830 out dx,al ; set base address low
5831 mov al,bh
5832 out dx,al ; set base address high
5833
5834 inc dx ;point to length
5835 mov al,cl
5836 out dx,al ; set length low
5837 mov al,ch
5838 out dx,al ; set length high
5839
5840 pop dx
5841
5842 mov al,dl
5843 mov dx,[DmaPageReg]
5844 out dx,al ; set DMA page reg
5845
5846 mov al,[DMA_Channel]
5847 out 0Ah,al ; unmask (activate) dma channel
5848 pop bx
5849 ret
5850ENDP
5851 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
5852 Å‚ Programming the Intel 8253 Programmable Interval Timer Å‚
5853 ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5854
5855 Written for the PC-GPE by Mark Feldman
5856 e-mail address : u914097@student.canberra.edu.au
5857 myndale@cairo.anu.edu.au
5858
5859 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
5860 Å‚ THIS FILE MAY NOT BE DISTRIBUTED Å‚
5861 Å‚ SEPARATE TO THE ENTIRE PC-GPE COLLECTION. Å‚
5862 ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5863
5864
5865ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5866Å‚ Disclaimer Å‚
5867ŔÄÄÄÄÄÄÄÄÄÄÄÄŮ
5868
5869I assume no responsibility whatsoever for any effect that this file, the
5870information contained therein or the use thereof has on you, your sanity,
5871computer, spouse, children, pets or anything else related to you or your
5872existance. No warranty is provided nor implied with this information.
5873
5874ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5875Å‚ Introduction Å‚
5876ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5877
5878The PIT chip has 3 channels, each of which are responsible for a different
5879task on the PC:
5880
5881Channel 0 is responsible for updating the system clock. It is usually
5882programmed to generate around 18.2 clock ticks a second. An interrupt 8 is
5883generated for every clock tick.
5884
5885Channel 1 controls DMA memory refreshing. DRAM is cheap, but it's memory
5886cells must be periodically refreshed or they quickly lose their charge. The
5887PIT chip is responsible for sending signals to the DMA chip to refresh
5888memory. Most machines are refreshed at a higher rate than neccesary, and
5889reprogramming channel 1 to refresh memory at a slower rate can sometime speed
5890up system performance. I got a 2.5 MHz speed-up when I did it to my 286, but
5891it didn't seem to work on my 486SUX33.
5892
5893Channel 2 is connected to the speaker. It's normally programmed to generate
5894a square wave so a continuous tone is heard. Reprogramming it for "Interrupt
5895on Terminal Count" mode is a nifty trick which can be used to play 8-bit
5896samples from the PC speaker.
5897
5898Each channel has a counter which counts down. The PIT input frequency is
58991193181 ($1234DD) Hz. Each counter decrements once for every input clock
5900cycle. "Terminal Count", mentioned several times below, is when the counter
5901reaches 0.
5902
5903Loading the counters with 0 has the same effect as loading them with 10000h,
5904and is the highest count possible (approx 18.2 Hz).
5905
5906ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5907Å‚ The PIT Ports Å‚
5908ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5909
5910The PIT chip is hooked up to the Intel CPU through the following ports:
5911
5912 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
5913 Å‚ Port Description Å‚
5914 ĂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
5915 Å‚ 40h Channel 0 counter (read/write) Å‚
5916 Å‚ 41h Channel 1 counter (read/write) Å‚
5917 Å‚ 42h Channel 2 counter (read/write) Å‚
5918 Å‚ 43h Control Word (write only) Å‚
5919 ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5920
5921ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5922Å‚ The Control Word Å‚
5923ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5924
5925 ÚÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄż
5926 Å‚ 7 Å‚ 6 Å‚ 5 Å‚ 4 Å‚ 3 Å‚ 2 Å‚ 1 Å‚ 0 Å‚
5927 ŔÄÄÄÃÄÄÄÃÄÄÄÃÄÄÄÃÄÄÄÃÄÄÄÃÄÄÄÃÄÄÄŮ
5928 ŔÄÂÄŮ ŔÄÂÄŮ ŔÄÄÄÂÄÄÄŮ ŔÄÄ BCD 0 - Binary 16 bit
5929 Å‚ Å‚ Å‚ 1 - BCD 4 decades
5930ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÃÄÄÄÄż Å‚ Å‚
5931ł Select Counter ł ł ŔÄÄÄÄÄÄÄÄÄÄ Mode Number 0 - 5
5932Å‚ 0 - Select Counter 0 Å‚ Å‚
5933ł 1 - Select Counter 1 ł ł ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
5934Å‚ 2 - Select Counter 2 Å‚ Å‚ Å‚ Read/Load Å‚
5935ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ ł ł 0 - Counter Latching ł
5936 ŔÄÄÄÄÄÄÄÄÄ´ 1 - Read/Load LSB only ł
5937 Å‚ 2 - Read/Load MSB only Å‚
5938 Å‚ 3 - Read/Load LSB then MSB Å‚
5939 ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5940
5941ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5942Å‚ The PIT Modes Å‚
5943ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5944
5945The PIT is capable of operating in 6 different modes:
5946
5947MODE 0 - Interrupt on Terminal Count
5948ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5949When this mode is set the output will be low. Loading the count register
5950with a value will cause the output to remain low and the counter will start
5951counting down. When the counter reaches 0 the output will go high and remain
5952high until the counter is reprogrammed. The counter will continue to count
5953down after terminal count is reached. Writing a value to the count register
5954during counting will stop the counter, writing a second byte starts the
5955new count.
5956
5957MODE 1 - Programmable One-Shot
5958ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5959The output will go low once the counter has been loaded, and will go high
5960once terminal count has been reached. Once terminal count has been reached
5961it can be triggered again.
5962
5963MODE 2 - Rate Generator
5964ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5965A standard divide-by-N counter. The output will be low for one period of the
5966input clock then it will remain high for the time in the counter. This cycle
5967will keep repeating.
5968
5969MODE 3 - Square Wave Rate Generator
5970ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5971Similar to mode 2, except the ouput will remain high until one half of the
5972count has been completed and then low for the other half.
5973
5974MODE 4 - Software Triggered Strobe
5975ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5976After the mode is set the output will be high. Once the count is loaded it
5977will start counting, and will go low once terminal count is reached.
5978
5979MODE 5 - Hardware Triggered Strobe
5980ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5981Hardware triggered strobe. Similar to mode 5, but it waits for a hardware
5982trigger signal before starting to count.
5983
5984Modes 1 and 5 require the PIT gate pin to go high in order to start
5985counting. I'm not sure if this has been implemented in the PC.
5986
5987ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5988Å‚ Counter Latching Å‚
5989ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
5990
5991Setting the Read/Load field in the Control Word to 0 (Counter Latch) causes
5992the appropriate channel to go into a sort of "lap" mode, the counter keeps
5993counting down internally but it appears to have stopped if you read it's
5994values through the channel's counter port. In this way you get a stable count
5995value when you read the counter. Once you send a counter latch command you
5996*must* then read the counter.
5997
5998ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
5999Å‚ Doing Something Useful Å‚
6000ŔÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6001
6002Ok, so let's say we are writing a game and we need to have a certain
6003routine called 100 times a second and we want to use channel 0 to do all
6004this timing in the background while the main program is busy doing other
6005stuff.
6006
6007The first thing we have to realise is that BIOS usually uses channel 0 to
6008keep track of the time, so we have 3 options:
6009
60101) Have our own routine handle all timer interrupts. This will effectively
6011 stop the PC clock and the system time will be wrong from that point on.
6012 The clock will be reset to the proper time the next time the computer
6013 is turned off and on again, but it's not a nice thing to do to someone
6014 unless you really have to.
6015
60162) Have our routine do whatever it has to do and then call the BIOS handler.
6017 This would be fine if our program was receiving the usual 18.2 ticks
6018 a second, but we need 100 a second and calling the BIOS handler for every
6019 tick will speed up the system time. Same net result as case 1.
6020
60213) Have our routine do the interrupt handling and call the BIOS handler only
6022 when it needs to be updated! BINGO!
6023
6024The PIT chip runs at a freqency of 1234DDh Hz, and normally the BIOS timer
6025interrupt handler is called for every 10000h cycles of this clock. First we
6026need to reprogram channel 0 to generate an interrupt 100 times a second, ie
6027every 1234DDh / 100 = 11931 cycles. The best thing to do is keep a running
6028total of the number of clock ticks which have occurred. For every interrupt
6029generated we will add 11931 to this total. When it reaches 10000h our handler
6030will know it's time to tell BIOS about it and do so.
6031
6032So let's get into some good old Pascal code. First we'll define a few
6033constants and variables our program will need:
6034
6035ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
6036Uses Crt, Dos;
6037
6038{$F+} { Force far mode, a good idea when mucking around with interrupts }
6039
6040const TIMERINTR = 8;
6041 PIT_FREQ = $1234DD;
6042
6043var BIOSTimerHandler : procedure;
6044 clock_ticks, counter : longint;
6045ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6046
6047The clock_ticks variable will keep track of how many cycles the PIT has
6048had, it'll be intialised to 0. The counter variable will hold the new
6049channel 0 counter value. We'll also be adding this number to clock_ticks
6050every time our handler is called.
6051
6052Next we need to do some initialization:
6053
6054ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
6055procedure SetTimer(TimerHandler : pointer; frequency : word);
6056begin
6057
6058 { Do some initialization }
6059 clock_ticks := 0;
6060 counter := $1234DD div frequency;
6061
6062 { Store the current BIOS handler and set up our own }
6063 GetIntVec(TIMERINTR, @BIOSTimerHandler);
6064 SetIntVec(TIMERINTR, TimerHandler);
6065
6066 { Set the PIT channel 0 frequency }
6067 Port[$43] := $34;
6068 Port[$40] := counter mod 256;
6069 Port[$40] := counter div 256;
6070end;
6071ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6072
6073Pretty straightforward stuff. We save the address of the BIOS handler,
6074install our own, set up the variables we'll use and program PIT channel 0
6075for the divide-by-N mode at the frequency we need.
6076
6077This next bit is what we need to do once our program is finished. It just
6078resets everything back to normal.
6079
6080ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
6081procedure CleanUpTimer;
6082begin
6083 { Restore the normal clock frequency }
6084 Port[$43] := $34;
6085 Port[$40] := 0;
6086 Port[$40] := 0;
6087
6088 { Restore the normal ticker handler }
6089 SetIntVec(TIMERINTR, @BIOSTimerHandler);
6090end;
6091ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6092
6093
6094Ok, here's our actual handler. This particular handler just writes an
6095asterix (*) to the screen. Then it does the checks to see if the BIOS
6096handler should be called. If so it calls it, if not it acknowledges the
6097interrupt itself.
6098
6099ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
6100
6101procedure Handler; Interrupt;
6102begin
6103
6104 { DO WHATEVER WE WANT TO DO IN HERE }
6105 Write('*');
6106
6107 { Adjust the count of clock ticks }
6108 clock_ticks := clock_ticks + counter;
6109
6110 { Is it time for the BIOS handler to do it's thang? }
6111 if clock_ticks >= $10000 then
6112 begin
6113
6114 { Yep! So adjust the count and call the BIOS handler }
6115 clock_ticks := clock_ticks - $10000;
6116
6117 asm pushf end;
6118 BIOSTimerHandler;
6119 end
6120
6121 { If not then just acknowledge the interrupt }
6122 else
6123 Port[$20] := $20;
6124end;
6125
6126ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6127
6128And finally our calling program. What follows is just an example program
6129which sets everything up, waits for us to press a key and then cleans up
6130after itself.
6131
6132ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄż
6133begin
6134 SetTimer(Addr(Handler), 100);
6135 ReadKey;
6136 CleanUpTimer;
6137end.
6138ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŮ
6139
6140
6141ÚÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
6142Å‚ References Å‚
6143ŔÄÄÄÄÄÄÄÄÄÄÄÄŮ
6144
6145Title : "Peripheral Components"
6146Publisher : Intel Corporation
6147ISBN : 1-55512-127-6
6148
6149******************************************************************************
6150* 'Doom' 3D Engine techniques *
6151******************************************************************************
6152By Brian 'Neuromancer' Marshall
6153(Email: brianm@vissci.demon.co.uk)
6154
6155 This document is submitted subject to certain conditions:
6156
61571. This Document is not in any way related to Id Software, and is
6158 not meant to be representive of their techniques : it is based
6159 upon my own investigations of a realtime 3d engine that produces
6160 a screen display similar to 'Doom' by Id software.
6161
61622. I take no responsibility for any damange to data or computer equipment
6163 caused by attempts to implement these algorithms.
6164
61653. Although I have made every attempt to ensure that this document is error
6166 free i take no responsability for any errors it may contain.
6167
61684. Anyone is free to use this information as they wish, however I would
6169 appreciate being credited if the information has been useful.
6170
61715. I take no responsability for the spelling or grammar.
6172 (My written english is none too good...so I won't take offence
6173 at any corrections: I am a programmer not a writer...)
6174
6175 Right now that that little lot is out of the way I will start this
6176document proper....
6177
61781: Definition of Terms
6179======================
6180
6181 Throughout this document I will be making use of many graphical terms
6182using my understanding of them as they apply to this algorithm. I will
6183explain all the terms below. Feel free to skip this part....
6184
6185Texture:
6186 A texture for the purpose of this is a square image.
6187
6188U and V:
6189 U and V are the equivelants of x and y but are in texture space.
6190ie They are the the two axies of the two dimensional texture.
6191
6192Screen:
6193 For my purposes 'screen' is the window we wish to fill: it doesn't
6194have to be the whole screen.
6195
6196Affine Mapping:
6197 A affine mapping is a texture map where the texture is sampled
6198in a linear fashion in both U and V.
6199
6200Biquadratic Mapping:
6201 A biquadratic mapping is a mapping where the texture is sampled
6202along a curve in both U and V that approximates the perspective transform.
6203This gives almost proper forshortening.
6204
6205
6206Projective Mapping:
6207 A projective mapping is a mapping where a changing homogenous
6208coordinated is added to the texture coordinateds to give (U,V,W) and
6209a division is performed at every pixel. This is the mathematically and
6210visual correct for of texture mapping for the square to quadrilateral
6211mappings we are using.
6212 (As an aside it is possible to do a projective mapping without
6213the divide (or 3 multiplies) but that is totally unrelated to the matter
6214in hand...)
6215
6216Ray Casting:
6217 Ray Casting in this context is back-firing 'rays' along a two
6218dinesional map. The rays do however follow heights... more on that later
6219
6220Sprite:
6221 A Sprite is a bitmap that is either a monster or an object. To
6222put it another way it is anything that is not made out of wall or
6223floor sectins.
6224
6225Sprite Scaling:
6226 By this I mean scaling a bitmap in either x or y or both.
6227
6228Right... Now thats over with onto the foundation:
6229
62302: Two Dimensional Ray Casting Techniques
6231===========================================
6232
6233 In order to make this accessible to anyone I will start by
6234explaining 2d raycasting as used in Wolfenstein 3d style games.
6235
6236 2.1: Wolfenstien 3D Style Techniques...
6237 =======================================
6238
6239 Wolfenstein 3d was a game that rocked the world (well me anyway!).
6240 It used a technique where you fire a ray accross a 2d grid based map to
6241 find all its walls and objects. The walls were then drawn vertically
6242 using sprite scaling techniques to simulate texture mapping.
6243
6244 The tracing accross the map looked something like this;
6245
6246
6247 =============================================
6248 = = = = = = /= = = = = =
6249 = = = = = = / = = = = = =
6250 = = = = = =/ = = = = = =
6251 ====================/========================
6252 = = = = = /= = = = = = =
6253 = = = = = / = = = = = = =
6254 = = = = =/ = = = = = = =
6255 ================/============================
6256 = = = = /# = = = = = = =
6257 = = = = / # = = = = = = =
6258 = = = =/ # = = = = = = =
6259 ============/===#########====================
6260 = = = /= = = # = = = = =
6261 = = = / = = = # = = = = =
6262 = = =/ = = = # = = = = =
6263 ========/===============#====================
6264 = = /= = = = # = = = = =
6265 = = P = = = = # = = = = =
6266 = = \= = = = # = = = = =
6267 ========\===============#====================
6268 = = =\ = = = # = = = = =
6269 = = = \ = = = # = = = = =
6270 = = = \= = = # = = = = =
6271 ============\=======#####====================
6272 = = = =\ = # = = = = = =
6273 = = = = \ = # = = = = = =
6274 = = = = \= # = = = = = =
6275 ================\===#========================
6276 = = = = =\ # = = = = = =
6277 = = = = = \ # = = = = = =
6278 = = = = = \# = = = = = =
6279 =============================================
6280
6281 (#'s are walls, = is the grid....)
6282
6283 This is just a case of firing a ray for each vertical
6284 line on the screen. This ray is traced accross the map to
6285 see where it crosses a grid boundry. Where it crosses a
6286 boundry you cjeck to see if there is a wall there we see how
6287 far away it it and draw a scaled vertical line from the texture
6288 on screen. The line we draw is selected from the texture by
6289 seeing where the line has intersected on the side of the square it
6290 hit.
6291 This is repeated with a ray for each vertical line on the
6292 screen that we wish to display.
6293 This is a very quick explaination of how it works missing
6294 out how the sprites are handled. If you want a more detailed
6295 explaination then I suggest getting acksrc.zip from
6296 ftp.funet.fi in /pub/msdos/games/programming
6297
6298 This is someone's source for a Wolfenstien engine written
6299 in Borland C and Assembly language on the Pc.
6300 Its is not the fastest or best but has good documentation
6301 and solves similiar sprite probelms, distance probelms and has
6302 some much better explaination of the tracing technique tahn I have
6303 put here. I recommend to everyone interested taht you get a copy
6304 and have a thorough play around with it.
6305 (Even if you don't have a Pc: Everything but the drawing and video
6306 mode setting is done in 'C' so it should not be too hard to port
6307 ....)
6308
6309
6310 2.2 Ray Casting in the Doom Environment
6311 =======================================
6312
6313 When you look at a screen from Doom you see floors, steps
6314 walls and lots of other trappings.
6315 You look out of windows and accross courtyards and you
6316 say WOW! what a great 3d game!!
6317 Then you fire your gun a baddie who's in line with you but
6318 above you and bang! he's a corpse.
6319 Then you climb up to the level where the corpse is and look
6320 out the window to where you were and you say Gosh! a 3d game!!
6321
6322 Hmmm....
6323
6324 Stop gawping at the graphics for a minute and look at the map
6325 screen. Nice line vectors. But isn't the map a bit simple???
6326 Notice how depite colours showing you that there are different
6327 heights. Then notice that despite the fact that there is NEVER a
6328 place where you can exist on two different levels. Smelling a little
6329 2d yet???
6330 Look where there are bridges (or sort of bridges) : managed to
6331 see under them yet??
6332
6333 The whole point to this is that Doom is a 2D games just like
6334 its ancestor Wolfenstein but it has rather more advanced raycasting
6335 which does a very nice job of fooling the player into thinking its a
6336 3d game that shifting loads of polygons and back-culling, depth
6337 sorting etc...
6338
6339 Right the explaination of how you turn a 2d map into the 3d
6340 doom screen is complex so if you are having difficulty try reading
6341 it a few times and if all else fails mail me....
6342
6343
6344 2.3 What is actually done!
6345 ==========================
6346
6347 Right to start with the raycasting is started in the same
6348 way as Wolfenstien. That is find out where the player is in the 2d
6349 map and get a ray setup for the first vertical line on the screen.
6350
6351 Now we have an extra stage from the Wolfenstein I described
6352 whcih involves a data srtucture that we will use later to actually
6353 draw the screen.
6354
6355 In this data structure we start the ray off as at the bottom
6356 of the screen. This is shown in the diagram below;
6357
6358 =================================
6359 = =
6360 = =
6361 = =
6362 = =
6363 = =
6364 = =
6365 = =
6366 = =
6367 = =
6368 = =
6369 = =
6370 = =
6371 = =
6372 = =
6373 = =
6374 = =
6375 =* =
6376 =================================
6377
6378
6379 Where the '=' show the boundry of the screen and '*' is the virtual
6380 position of the ray.
6381
6382 Note: the Data structure is really two structures:
6383 One which is a set of list for each vertical 'scanline' and
6384 One which is a corresponding list for horizontal scanlines.
6385
6386 Now we start tracing the ray. We skip accross the 2d map until
6387 we hit something interesting. By something interesting I mean something
6388 that is an actual wall or florr section edge.
6389 Right we have hit the edge of either a floor or wall section.
6390 We have several things to do know. These are;
6391
6392 If it was a wall we hit:
6393
6394 1: Find out how 'high' of screen this section of wall should be
6395 due to the distance it is accross the 2d map.
6396 2: Find out at what 'virtual height' it is: This is so that we can see
6397 where in the vertical scanline in comes for testing where to insert
6398 it and for clipping it.
6399 3: Test in our structure to see if you draw it or not.
6400 (This is done so that you can look through windows : how this works
6401 will become apparent later.)
6402 4: If any of the wall segment is visible then we find out where along
6403 the texture we have hit it and write into the structure the area of
6404 the screen it takes up as well as the texture, the point where we
6405 have hit the texture and the size it should be on screen. (This is
6406 so that we can draw it correctly even if the whole span is not on
6407 screen.
6408
6409
6410 If it was a floor section that we hit:
6411
6412 1: Find out where on the vertical line we are working the floor section
6413 that the ray has hit is. (We know the height of the the floor in the
6414 virtual map (2d) and we know the height of the player and the distance
6415 of the floor square from the player so it is easy).
6416 As a side effect of this we now know the U,V value where the ray has
6417 hit the floor square.
6418
6419 2: Trace Accross the floor square till we hit the far edge of the floor
6420 square : we then workout where this is on the vertical scanline using
6421 the same technique as above. We now know the vertical span of the
6422 floor section, and where on the span it is.
6423
6424 3: We check to see if the span is visible on the vertical span.
6425 If it is or part of it is used then we mark that part of the vertical
6426 scanline as used.
6427 We also have to make use of the horizontal buffer I mentioned. We
6428 insert into this in 2 places. The first is the x coordinate of where
6429 we hit the floor square into the y line where we where on the screen.
6430 Phew got that bit?? We also insert here the U,V value which we knew
6431 from the tracing. (I told you we'd need it later....)
6432
6433
6434 As you can see there's a little more to hiting a floor segment than
6435a wall segment. Also note that a you exit a floor segment you may also hit
6436a wall segment.
6437
6438 Tracing the individual ray is continued until we hit a special kind
6439of wall. This wall is marked as a wall that connects to the ceiling.
6440This is one place to stop tracing this ray. However we can stop tracing early
6441if we have found enough to fill the whole vertical scanline then we can stop
6442whenevr we have done this.
6443
6444 Next come a trick. I said we were tracing along a 2d map. Well I
6445lied a bit. There are (In my implementation at least..) TWO 2d maps. One is
6446basically from the floor along including all the 'floor' walls and everything
6447up to and including the walls that join onto the ceiling. The other map
6448is basically the ceiling (with anything coming down from the ceiling on it
6449if you are doing this: this makes life a little more complex as I'll explain
6450below..)
6451 Now when we have traced along the bottom map and hit a wall that
6452connects to the ceiling then we go back and trace along the ceiling from
6453the start to fill in the gaps. There is a problem with this however.
6454The problem is when you have things like a monolith or something else built
6455out of walls jutting down from the ceiling. you have to decide whether to
6456draw it or draw whatever was already in the scanline structure. This means
6457either storing extra information in the buffer ie z coordinates or tracing
6458along both the ceiling and floor at the same time.... for most people I would
6459suggest just not having anything jutting down from the ceiling.
6460 Also you could trace backwards instead of starting a new ray. This
6461would be fasterfor many cases as you wouldn't be tracing through lots
6462of floor squares that aren't on screen. By tracing backwards you can keep
6463going up the vertical scanline and you know that you are on the screen. As
6464soon as something goes off the top of the screen you can handle that and then
6465stop tracing.
6466
6467 Phew. has everyone got that???
6468
6469 Now we just go back and fire rays up the rest of the vertical
6470scanlines. Easy!!???
6471
6472 At the end of this lot we have the necessary data in the two buffers
6473to go back and draw the screen background.
6474(There is one more thing done while tracing but I'll explain that later...)
6475
6476
6477 Oh... one other thing... you have may want to change the raycasting
6478a bit to subdivide the map... it helps with speed.
6479 And don't forget the added complexity that walls aren't all at
648090 degrees to each other...
6481
64823: Drawing the walls and Why it works!!
6483=======================================
6484
6485 If you are familiar with Wolfenstein then please still read this
6486as it is esential background to understanding the floor routine.
6487
6488
6489 As all of you probably know the walls are drawn by scaling the line
6490of the texture to the correct size for the screen. The information in the
6491vertical buffer makes this easy. What you probably don't know is why this
6492creates texture mapping that is good enough to fool us.
6493
6494 The wall function is a Affine texture mapping. (well almost)
6495Now affine texture mappings look abysmal unless you do quite a lot of
6496subdivision (The amount needed varies according to the angle the projected
6497square is at.). So why does the Doom technique work??
6498
6499 Well when we traced the rays we found out exactly where along the
6500side of the square we hit we were in relation to the width of the texture.
6501This means that the top and bottom pixels of the scaled wall piece are
6502calculated correctly. This means that we have effecively subdivided the
6503texture along vertical scanlines and as the effective subdidvisons are
6504calculated exactly with proper forshortening as a result of the tracing.
6505So the ray casting has made the texture mapping easy for us.
6506 (We have enough subdivision by this scanline effect as the wall
6507only rotates about one axis and we have proper foreshortening.)
6508
6509 This knowlege helps us understand how to do the floors and why
6510that works.
6511
6512 We can now draw all the wall segments by just looking at the buffer
6513and drawing the parts marked as walls.(Skiping where we put in the bits used
6514by the floor/ceiling bits: we draw them later.)
6515
65164: Drawing the Floor/Ceiling and why it works!
6517===============================================
6518
6519 If you have grasped why the walls work then you have just about
6520won for the floors.
6521 We have the information needed to draw the floors from the horizontal
6522buffer.
6523 All we have to do is look at the horizontal spans in the buffer
6524and draw them in all.
6525 Each of these spans has 2 end coordinates for which we have
6526exact texture coorinates. This tells us which line across the texture
6527we have to step along to do an Affine or linear mapping.
6528 This is shown below;
6529
6530
6531 =================================
6532 = =
6533 = =
6534 = =
6535 = = U1,V1 (exit)
6536 = **
6537 = *** =
6538 = *** =
6539 = *** =
6540 = *** =
6541 = *** =
6542 = *** =
6543 = *** =
6544 = ** =
6545 = ** =
6546 = ** =
6547 = ** =
6548 U0,V0 ** =
6549(entry) = =
6550 = =
6551 = =
6552 = =
6553 = =
6554 = =
6555 = =
6556 =================================
6557
6558(apologies for the wonky line: it should be straight!!)
6559
6560 Now...as the end coordinates are correct and the axis along
6561which forshortening takes place is not involved (this is a fudge)
6562we can step linearly along this line across the texture to approximate
6563the mapping. (This is far easier than a proper texture map).
6564 This is effectivly a wall lying on its side which works as the
6565texture coordinates at the ends of the span have been calculated correctly.
6566This is a benefit of the raycasting we used to find everything.
6567 Easy huh??
6568
6569
65705: Sprites
6571==========
6572
6573 The Sprites are really quite easy to do. The basic technique is the
6574same as used in Wolfenstein 3d.
6575 This is done as follows:
6576
6577When you enter a 'square' on the floor map you test to see if there are
6578any sprites in the square. If there are you flag that sprite as visible
6579and add it to a list of visible sprites.
6580
6581When you have finished tracing and drawing the walls and floor you
6582depth sort the sprites and draw them from the back to the front. (painters
6583algorithm). The only complication in drawing them is that you have to check
6584buffer that has the walls in, in order to clip the sprites correctly.
6585
6586 (If you're interested in Doom you can occasionally see large
6587explosions (ie BFG) slip partially behind a wall segment.)
6588
6589 On possibly faster way of handling the sprites would be to mark
6590them like wall segments as you find them in the buffer. The only (ONLY!)
6591complication to this approach is that sprites can have holes in them. By
6592this I mean things like the gap between an arm and a leg which should be
6593the background colour.
6594
6595
65966: Lighting and Depth Cueing
6597============================
6598
6599 Lighting and Depth Cueing fits nicely in with the way that we have
6600prepared the screen ready for drawing.
6601 All we have to do is see how far away we are when we found either
6602the floor or wall section and set the light level according to the distance.
6603 The other thing that is applied is a light level. This is taken from
6604the map at the edges where you have hit something. As the map is 2D it is
6605easy to manage lighting, flickering etc.
6606 For things like pools of light on the floor all you have to do
6607is subdivide that patch of floor so that you can set the bit under the
6608skylight to a lighter colour. Its also very easy to frig this for the
6609lighting goggles.
6610
6611
66127: Controlling the Baddies
6613==========================
6614
6615
6616 This is pretty easy: all you have to think about is moving and
6617reacting on a 2d map. the only complications are things like the monsters
6618looking through windows and seeing a player but this all degenerates into
6619a simple 2d problem. Things like deciding whether the player has been hit or
6620has he/she hit a monster is just another case of firing a ray. (Or do it
6621another way...)
6622
6623
66248: Where next???
6625================
6626
6627 Thats all folks... hopefully a useful and intersting insight into
6628my Doom engine works.
6629 As to the question where next... well I already have some enhancements
6630to my Doom enigine and others are in the works...
6631
6632Some of what you may eventually see are:
6633
6634 Proper lighting (I have done this already...its easier than you
6635 think)
6636 Non-Vertical walls (i.e. Aliens style corridors...)
6637 Orgranic Walls (i.e. Curved like the Aliens nest...)
6638 Fractal Landscapes (This one is still very much a theory but how
6639 about being able to go outside and walk up and down
6640 hills etc??)
6641
6642 If there are bits people are really shaky about I may post a new
6643version of this... but I cannot get into implimentation issues as all
6644implementation work is under copyright...
6645
6646 By the way if anyone out there implements this I'd love to here
6647how you get on...
6648
6649 Anyone got any comments or any other interesting algorithms???
6650
6651Brian 'Neuromancer' Marshall 'When do graphics not look like graphics?
6652( Email: brianm@vissci.demon.co.uk ) :when we get it RIGHT.'
6653
6654
6655ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
6656So, that was it. The promised UUE file follows now
6657ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
6658----------------------------- Cut from here ----------------------------------
6659
6660begin 644 support.zip
6661M4$L#!!0````(`".`J1R!)IZM204``(T.```)````5$E-15(N05--S591;]LV
6662M$'X/D/]P!08XP1Q;LAW7<1ZV)F[7/JSIVK3K,.R!$L\19XG42,IV^NMW1TFV
6663MD[C--G3#!`2*CG<?O_ON>/3YR5=[#@_.X25:!.5`@#.531'FQD*!PE56Z1NP
6664MF`NOE@BN1)1@YI":HJP\VAY<9Q171S'22N4YO+ZZAGFE4Z^,AM*:$FU^"Y66
6665M2*A5[I47;H'6=4$X\!G2FD/PJJ!U^BP")X?Y$ET/GGG(B8F'&;H_/BA<=>'J
6666M77\`0DOX66EI5HZH.@=52;O[K,;I$02C[-#C!%-3WEIUDWF(S\Y&G,DU8E'!
6667M&\R]T:A!+`3\5`F[Z+_%`N4MO+%&.D:#5W.X-1441JKY+?'<`'>A9(8(TH`V
6668MGE2R*"0H_P1^X0!QVYHH.4:J=`!1I&5#C70HJC3C-^^1JP6A)I5OD=,,TP6%
6669M"Q9#WU"69LY(!`@B]97(6Z0C9J!TFE>22Q=H4K4*U!X2]"ND))=HO4HI)E<:
6670MW3$)PUAG<?W]9",=PHJXDTC;5F@+WW%-,Q`\[\A$$J0JE<8YE>0-?>5#4QB[
6671MH$IREW5"DQ4BSV%!Q6-P+\B=_PF`;MIL?_GF/6R?J\K3OK`4>14D'$W&LX_]
6672MX?#'EY]H-1J,+K/&_.YC?Q`UYN%L%,S#X#UJS:?/9SOF>-R89Q?/@GDP&0/T
6673MX\8[/HVB8(Z">=1[^I07QE$TSAJJKPW)B4_@`[-SH>!4WCE:F%M3L#940I$8
6674M2F#`;6HL2+/2O=`>+C-5+AG&5CKHZ$E'CB6W.FC.9X_;VH6N#X>%_((8=5,X
6675MQ,*!-PPCRA*%A<)0-4)0#V;*+2`5:=8@&`JWCBQZ<W1XT^VA$7K!<%#<PL7%
6676M.RH:[4D!3(D=-YU5*DSKVIFY7PF+;?,TAV6E7,8X0DK^M@_[AXAL#U!JM!>I
6677M!U'YS(0S#"\0<Y(1D6':]8)"<(D:5+,-2Z@['E9"^SO[A4UZ`>FR!9?24M(L
6678MA<5I.$4\`WIE,P.^=]ZB*'JZRG.-OC=7H#2\TL2:/H,^=V;&]X/I8##HQU&T
6679MZ5;R?Z&DV>\^GDS)=]>?W&<_J)/&_8I4XO-QH7S-A$L`1]\.3R<G@_AD-)P,
6680M!Z/1<2@DR;9$$)L33JGSM!7>6(8Z8CO[71ZS!"=?[3D\<*3E0@$XO`D[E\(*
6681M"$;NE7@,G?#1.3QHLY2K^DV)9R"K$HZ^.][BH);N\.#P0`HOV.L.;EDEN4I;
6682M8'8AW`S72Y$3;E+C=J)X,!R=CI].SIY=7,Z>O^@P.D\MM?5Y^]FKC"<91<B6
6683M;1,1'1ZD#TW)0Y-X:**<U*ZID_6^Z6Q3;%-.C<1'4F:7'2F%<U6!D+HI+W1!
6684MNBF#=L&Y:2UH$-;ZJIQNHPJSK*/77=X+..3AJN1K><V\VI4T5[N?&YB\"T.>
6685MK^T"CRI^1L.,(/+6#.=7[Z_#K$F0\Y%\RZFB0*F$QVWXYYYS-0>+-RH,Q7KF
6686MU3\EXC"8MP!K8S?$1+Z'5Y0]LK!=<GYOSBE)1]M&6<M-U#]RPA3CEK0XA<\_
6687MYT7E?'U?BL5.ZA+3!OZ^O[%APFN(^_%D&_"[_A3>O.&=@*.H%YV>GAY3@5.C
6688M91CBMM)_L9Q?J":';!>5AFU0E.WIHGLU>#S@L1)HO*D=[VOTK"Z!-V8!R;H?
6689MQV?#>!*U`NRM(I&0.QQX0K;VF!XJ<)3L$,GL9GGTL-V2=9?^'NZ2D'N:[Q&:
6690M,JUGUZ_)^K<]2I`0V=^ES929>O+O\TN_R"__O\J:_!/:_Z&LHN6W?V!'9]'>
6691M8T-+9CYWZ*&YZW;/7'V"!_'>O!EUE-Y!O1?17DSU1=4Z8:-/<\$<'OP)4$L#
6692M!!0````(`#$`J!H)W(XF-@(````#```,````4$%,3$545$4N0T],'9*+VFH`
6693M%$0'N1-"DB3))90B)=1^_L<Z_><%9LVL;P`0T7Z_'\=Q&(:^[[NNN]_O3=/4
6694M=5V695$4:9HF21+'<11%81@&0>#[ON=YKNO:MFU9EF$8NJZKJBK+LBB*/,]S
6695M',<PS%_X.'[[_G.[S74]%<68).\H>@?!X'DOVWZ:9J]I#TGJ>+YEV1:X`B60
6696M`3$0`C[@`A:@_Z)"O'S<UBA6B`WX*E;2K_R3Z/JE[$O[+ZT_M/R0,'TP31A>
6697MZ#NT5S0EZ@SG([((QRWV:VQ76!M8J5A*4'@(')ZTOD_69=#/#R6]"_&%"TMF
6698MF\,]P8ZQBF"%,`,L?>@>-!>JC>;;Y'-V&"-O\,R7J?:*TLI2(XD742@%/E\L
6699M3@ONR+$1R^Y89LLP'L,X_\<8@`;(@(AYIF&@KJ.FH:JFO*`DH>A`P8Z\#=D.
6700M&2:I&HD2<0L"0S\-P`2\@`YH@`K(@1-P`';`!O@QS/\`">#G)[VO],SI$5'K
6701M46/21:(2E.%]0!N@<I$8"!0X`C06?$=TF:9\&(Y]'[:MWS1.55E%H9].<A2)
6702M0;#P/-:V&<.`JD(4Q_G['#_WU^?2?\[=G-[G^#:'U\FO)[>:K/.H%Z.2C4+Z
6703M9D]O)GXR48?PAN`"OX)7P$WA'/_\FCLL-W]FE14D`X(&7@8GT/BB5T?]C;J:
6704M[F=J4KH<J8KH'%"^F5-O/*V'H_N,G<?!:2.[":TZ,,_;9;;1D[5V<)70EK>6
6705MY!FBHPN6QB\53I4X66"%!?-[_C]02P,$%`````@`Y#HH&\SEC6=("@```#X`
6706M``P```!33T944D]#2RY&3E3M6HF.W#H.U/?_IB.`'4+0-ZS(XNG)'+LSF;R\
6707M;2,8A&VW6[R*+$KC>7WJFI.:3$Q$\YHN,]/Y-\]C/,['Y^Z4#\[%XR+>*B\^
6708MUQKG?UL>/N]8>^_!YR_C!5S>-_ZLPF?I3>&S_/]&OE_'6+?W31[-P%VFV^]_
6709MQ25&INOF4E_W%3>6?)"N/1^<E<UZDX8L;L;-X[KV\%CT2UD>@WQ_GMO[SH^T
6710MWUNRVER/KC@_,`5.,$%:J0B_XY7G];R>U_]P_3Q7E1\_?CZZ_.,A'SSLT\?/
6711M'_PXW_&''H\'R[_QG=<+_!.`F"@ZUW5IA=(J=<#H0L4Z]4GE@\Z*46.<6G6@
6712MFSB!160N"'B^NQIZS[5OQ637Q\\;]OC+KUZN3_&<53[VJ/A]#-_J^T'N(U_E
6713M]C[/7_."FXXYM]1'Z2ZDYSCWI9Z>BJLMAW@)P+_%G4_\?UY_\I(F>%!O[&H0
6714M2F.W2KZ?J%U_2_J?G&OI))U]DV>_+SG:64-/Q\E=]?O[:C+_5?Y_N[%OLOA_
6715M?.\*;V+_^1MB<G?!N5ME+:$I7\>!I1(*1E,"O=[+;PM+Y+V+\P6\1Y%GL]1Y
6716MOAGNND'[38^[FE'_9]S7^N_N.)]/U'_C/ZSA=R[1:-K2:.EWSF/Z<ZH_ZK_(
6717MJK\T#DOI'?27"J7\U_5W_NOZ2P%3/FSZ2U8HE09#R_HGOSM/GX*G2OTS&H1V
6718M)BRL\M=ET+QZ3>\$56QP;`O]CQF(;'%A#YL'4-@#\P#U@,\#&/:6G,`\0/^W
6719M]E<`9,4N1ON7D7E<EWG*.K0@'WE@T;)0NZO]GRS?'H;_+4`H]`5+37VE:Z&B
6720M+VOXB.^7R9<:0/TOOZBRS4_$_1J@AI(**Z1+4)14=9;'*.NG@QUA&$H:J/:)
6721M#JJ1M+].I_?2;'39XY]C-$.M_UWO]K^B?Y?M>5K9_TU-NEW[/TFGV>(?,R:=
6722M!T@`:<!#@;,&))/7%(M\5%>,HG+"I)$HWW>C3+S0Y6.-TEH"]S0\7X]$TMPD
6723M73G<4N(=;LIX1['+>-?[D@(UWJ_9P5A2J$*@KFE\Z`+.07]BG\Q!W_-WJ?H2
6724M3Y!9%"&KSV33/%8;8W2E:[=Z31'_E[G&XQ_U_XKX1]3,B'_$'D7\#_@_XE^#
6725M>-KW)3[/HL3&<7\@*O8H^:9QD/FX&GH(_M/-+*5@,5P206#^@95E(0:RC!#2
6726M`#%9X$LIY:"+L&HO+E/S%WBW//YEP>9YBW\U\.)A^I'JK_&O^4,8NVK\;RNK
6727M*HD1,XX1LZE2QC]W\"ZR%*DRX=4JF1D+2`LS)?Z-U_"/._Z=.Q7_-,8*_LES
6728M%?_PFL0_EQW_\GZ(]OZL=5A/ZQ>R1TU3R5]3[$+QFN;_"\"M_K\0B2P/R*R:
6729MM+RIHS76IN.?];^!?S/];^Y+_W/VO^)_8<P3^D[@W<&_^3K^Z;LK_@W`1N)?
6730M=`&O0!91!CY;YJQ6#[/$G:Q+(+-X4'NLB`=DZHIX,'M$/31[Z&M6VH-A2L5_
6731M&%\C0)L)K`#%BZR2>N%P>W!X$S<CB">73/Z62_=#LFV09!5GIBRM,D4)@GR<
6732M]J^94"!'3ZA8XBG<*<(NC[BMU<40&9Y?MX!]7O]4]B]]3>GTE.-P\C\-_1K?
6733M[\3_00UQ?X#VI/O[M67YTSN!_YKLO,UF^JRF\A]CXZUES]+KOKV-"2"7_5_V
6734M&FO]&Z/D!/\EU#_?_Y5V\XK)F.+[5>8!P/M5QRJ=VT[F3A-?,M]/[W_Z/`O[
6735MGR.6@$IJ75+L=Z+1T2>WRMOW0,?F(#^J\98@Q[ME.4>1QK77E^Q_2C:1<72;
6736M2Z'Z2E["_][_.O\E]+_!?\G[7V6`#%JD+1UD(SUF"^WUT:BKC/9$;8C^UX86
6737MRV19F_S:ROD'Q@=\ZW\@^_P#3I@^_Y"ZSW7^@2T<PQ+HCW88\Q_5/^BUZ7]9
6738MX(;^1G>*_LJY>:/_1_PW_L.C\Q\>G?]8_`?_.1\HGZ*8_QC_G1_DO];_1</G
6739M_#?]7^=?XG^;?['E/X7^F,9Y_PO^#U.IOE3F'ZG_BNTPUS^GNE5._7U=J\G&
6740M_^CV_5=ET:.^GRPFRX05A'>-ZG^5B_];_"N1K_%/OXQ_-:'S'^-O.>]:`53;
6741MXQ_=L_,_Y*O.?_2!"3HE0*;QC_[9_1W^M_SW^(_\?V/^%_R_Z*_%N^BO_+_H
6742M3V/6^`?_+_HO)$CHK_R?4W_P?R[S+X/_G'])_'.;?VWM"HW?^V0K^+]/1>R^
6743MA],*OHEP6LE'97/5_-_JUTTV_=G#*/7?9?2B^LL,ECZL/U'7G]O\+^8_R7\Q
6744M]0S^RRG3R"%D\-^46T'F7^Q\?CK_I^,?6?SK!OD*_;GE?ZRGS'_4ZK/IO\O\
6745M!X#;]==O%OV!?YH&&(<`__3]R"JXS%AEB7_J^&_\N>0_-?PO^EO^A_X2!_IE
6746MU7]Q"Z7&A]JY.6:^;05&?$E0^0KD;_)=(`=1KW]8'4?]`]YD_7,@<\@>7]Y,
6747MBOO*O!_U</;]#ZKQC]X^XY^@?\[[D?E?-N__Q#&1VVF-+HN"7/6/^O^J_JOK
6748MC\AT_77_K^H_?L/U_?&/-T@7KXB#V9;[?]@K\77>OO^#=L+SG^"-V#]+6K@K
6749M.P%F%!?MW>?DP^K_%^JO^&<YAZ%AONP&Q2]WM6\RW08@[^V*O[=+3K>Q5_0_
6750MG]"?.,!DOX)W[3RP\_]6<U=;J.SG5OYV5<*IO8]"GM!`S:=/X=]OUY^G[?]P
6751MV:Q!_J>;+?Z+??#^W"^W^C_T7=%.\*?U3_X[;^??DO^F_J//OY<1NZS_F.J1
6752M&0N6Q:1&=/YH_ZO/E_[7?1/];\#IQ_K?-\Y_?2'_4_\'_[/QE>(_Y6X262/I
6753MVR@N^WU=P4BVIO;0@8=MHX3^%AVA/^6LE>TM@0)]/_#%^/NM\X]O^5_'!;_)
6754M_PK.Q?]JH^I_&Y2D_W/YYO\H`^;_\:?]?]W\KZU`\;_N!!?_V_Y?^)_J_$.?
6755MW]W_.B6H_F>\ZBW_!]^!PV<@%39]+^4_5DYE^\<6[JCA_,>VZI+_#.]_G/_,
6756M&_^Y/LY_YHW_C.Q_K9.V_M_./T`/#):\Z)+-`8/_:#?Y,?[7NQ=ZL?5N.T[?
6757MQO]LO&`R]6([NSYO\[]6_TQ_KW^\ROD'Q/_X>/\'_5LAO$V6;_V..:R2(LE_
6758MX3_R**6^@?]W_K-Z_5M[U/JG^]^U_C7]T_^F_VCG/\QL37^OYJ$_SDP$6-3#
6759MSL`_;I'5]`7^%?71_X;^@B2J3^A/F)^Z_M@Y#?W)ZXV[<X3_5W8JW]#_N7/[
6760MMD%/([J=8!F^_]\Y\K#^Q^=?G^__[HRN'=(\3UVSS"/)XGWT\P[<^1Y^7`.4
6761M40M@59_/%KZSC.^X/2UIV"8?'.<]O`ML_$;E"NSEW)*?P+HYI&EK!:+3P?;!
6762ML4<UD-JCG(J!/1;?[-'.ORVK_SZP/$^MY>??;,H-_WO'23@^N<H&X!7[_1!G
6763M/4XJ)8ES-]#.FE+];A8\[TU2I8KW\%2YN2K^RVL+_G.>?_(FJIQ_82[XCU-`
6764M9?XU9\=_>HG_N^/_7E3G7WW^.==J\T__29]_KE?GG^-Y/:__X^L_4$L#!!0`
6765M```(`.FNJAP05F*;QP8``(<;```*````0T]04$52+E!!4\U8[4_C.!/_OA+_
6766M@S^L1+N$*FD/6-'KHR6\9-&Q4`4X[H3XX$W,-H_2N$K<7>!T__N-WQ([2=-R
6767MQTG7BA*/Q[\9SUO&_N/];SM_;KV;YO1;CN?HF"X6)!]OO;LM2(&.<P:/\GOS
6768MO"!;[Q`"EI0_HPD*243S6!"M3^@T:4$+S4>'R']F9%R;.LUB(18>IU@+.\IS
6769M_'SO#@;#O;T'1!^U'IK3Q_D:M6`!")0X'N"X-9@Z_Y06+?QM"O//[;2-F=*4
6770MX&S5!OGW5YSKG7J`H#8\UGNR5/@)4*\>]58ES^5RSMD<_G"19*2HC,J_X-B(
6771MQ,N<<.0>;-8!]X`W2N/W@=$GWY),H!T5<ZWKG'Z'W_C)0:/HX\RF8H"Y![`'
6772M3:9+IIAQJFE)%@E:R]*P<Z'!&&S*Z*]FE-;6-J\,$A"F;*)-AL`9+>;1+@J9
6773M$S#'9Y6%UQKNX"T,UQPC!54W[GW('AP3:"5CL"FC7S%*$W)#H,,)6$,.`CX(
6774MU,#G`Y\9]K9M?H<3%A*6XPBL?5049/XU%?6FM%]IO=')$1COTR?O4$Z4.FH5
6775M<19+@JO#\__9"_S"$KYN^(IU?!FL&YIJ5TI?RT#AP0'_":O2M-^^B0BG*3+W
6776M*JB+93&#G15BD,8%_!:)(R$%K27CJJAQQ;@1+E9L2.X(9@_V/PI*3A9R5?%5
6777MZD#YF.O0MM$S').K)>M=4EE2X/<Z>2$MJ0"?,P==P,QYQL@WL7M9Q#B&5<?,
6778M+#FC.3KC(>(A1I$4@V):0L+T13FMI5?S%9#\G(M:6-R?/0R.:7I_\3`(T?^0
6779MBVYF)$,G).K59_OCSM5!Y^I@S6J_<[5?K;8+4B/6OD3?<'=MP>!AU_5&LRI_
6780M>5AX[JRSX`'V#7EBFV"[FV';^"<Y_B$;B-XE%>\B!Z%KAG,FWCN_B\>68+J@
6781M=`'D.YK'XWJTR+F)7LRH?MI!2H:.#RLXSI(T/9[AO/>%S._?8]C0(4?Z,!JZ
6782M#P[\.%JM'4[>E9C*0_4M6@:4^^/EH)8D>G\.[RC4T_4"1RNR1^W9["8X:5C9
6783M0859%H6--BD,[-;I,TX?00WSS6]849M"JLMUO7I$8M1WW'X-85*FW4GR'0WE
6784MK%1B@O9'@JJ8U;L@$#7?'3=<UI+CMH\4[[!DUEIT9CP7.%&)9LR(=.-P*N,X
6785M,*\'@"V%?!#;J*6P!/,V`PLV`AMN!N:W@+4OFM)"+3(280?U1.1Z?5C>4S[;
6786M$0'7ATD)O.O!HP['<3OZ[=0`O\F7Q*Y2K<[2?MH!RYF5^JT=I_>%=J7L_ELY
6787M\57`KW%H!_!_V+DJAWO\/_BTC[[0&(W,:FB7?+,FAI1A1CH+8O4*:)Y14,OG
6788M5E1&>73JC\U#T@W(J1^2;F0#;YWC^*:=\FFXIC!R5-$R.4C7PW]6Q]9W+ESD
6789M?6L8/*@:W(RP6G""E>IQ61-B="F-8)N47JFC=$30&4Z+NM,Z))3>WEP"CU$[
6790M5QHB*OXF;-EWU;7IVWRGL(^:C&S52EN=\@QD)U%)5F<%[M]^+6^L/N)VVM/F
6791M<:HS_"MZB<K95<O(+6#T8!J_!+':'+N9V52#_HK6Z(2>LZ,T-9J<4OR6>4VA
6792M[S6$$#%0@O3=DC$RMSPV.\669*XJRP0-7=6-**$B+]VQ*=HDZ;ZT;&*T%H)I
6793M;*HR07NE\?Z>!Y7Q0[(@F)5Q9131.E`3IY+*L\4XE)P_HE_(\S0G14%B.SL:
6794MI<$L<"ZO6?LCHURMJ"9OI*?20!\V:T@VHYEO8OR4&"^[<O8V8TE:UJ?VX\EQ
6795M3N+"[L+MNQ[E&@^(\.=[+6^IU0%8':Y@<#=+4F(Z(Z;@<AP#15>,YL%KYB#/
6796M)D4MI/(J8,713-[)R"ITX(1.X.B3IZ2X_*LH=WG"R$76VY:%0-XWWN08O)8/
6797M!H-MFZVVQG]&IR^G_);SJ%C,GI\2O&;!,<T8CABZ+1#-T!K\VEHV(Z48Y/O7
6798MJ.>.O#[:10?[>WLC;]@M^72.$]XCR`]Y(9]J_+WMTL-82>E@023^@?.XZ&)!
6799M7T$D>>YBF4>+&3!UHF@P@@N6D$%4#)99/,#1X`5W;YGF""T(`S]J96/,\'>2
6800MLT%$UZX6#VA.4)&!AKO"?)@U7=;;G@ZN!LBG3V@X\D:-V<])FD8Y*5ACYA*T
6801M21O4T?Z>JXFA9Y3DP!SXWHH39ZV0617,O'GLHLDL,:I`58_XB<!#/Z-07O+P
6802MEB&TIP,^'533@3WM\VF_FB[!RSKV[U6%5?=]T3(OFG<Q1CFLE\C*JF65T4PM
6803MS?-;NL02HOQAW[F%MC?LR<#V1>VV;L7E3Z4PK^Y'C(D[DO?NP2:%7KWECJ6)
6804M>7=6=DF\S5#O(Q`V^`M02P,$%`````@`"[\0&]=EF-RA"0``4BP```H```!7
6805M3U)-244N4$%3[5I_3QL]$OX?B>\PE:I[H6RC9%/ZMN$X*?PHH+=0E*3\$$(G
6806M9W>2[.%=Y[Q>PK9ZO]U]L//8N\DFV=#`VW`ZJ:%-6'O\>.;QS-CC\/UUZ^V?
6807MZVO?7U]MZ8]S*?J2A=#YYT#PP-M97UM?^]H^;*^O`<"^5*9A_\M9NV-:+OH,
6808M&G`II`^[\)I5JU4CH'OVN/#N=%]32I;>U"J5=U7'O-^"Z,%>JE"/V,B$Z;51
6809M=>9_:DO^E(S==!Z#7A:X%/PQZ*<`EX`OAGXJ\!SX(NCG`,^`ET,_%W@*O`SZ
6810M45V66.J%T$\#?F3$+/33@1>.FH9^'O`"\"+T\X%+P1^#?@IP"?ABZ*<"SX$O
6811M@GX.\`SX+^A?T+^@?T'_GT&O,*FN="OXJ1O8"K?=!2+/`W[1(\Y*#V8K/4ZN
6812M]!"\TJ/[2@N.E99)?[6X&R-OFH)S?>VBV3)MEP/!\9SQ8NGI;K^GVK,^+CUW
6813M;#F;R"M'OUW3V[[@625K.V70'RC'%Z.HL2<T)(NRB;[_YZ>];+WMH9](A#:J
6814MT_VCY@[`=^@,@AB&XZX^JAA2D4`0*0%UM_K@5O7_[?<0"A\KH''V#H].SDAQ
6815M%H<9-Z&XSS@"]N!4J[7Z(.O1,'E/K6H:,2*S#\\.5F]D!Q]4F9$252(C:Z>V
6816M4FFQS+PE[:O^S^R;&'')`M5")9F'.UK5&,,N1ZDGY:R+G#3A-0>XJUO&AI`=
6817M_H-3/VAJ57FM85N#"!AW_`?[Q"*?'JL?,A/_%7W32%K<74[\FY[875^S-*QR
6818M@8]0G3.^L2^XD&<"&C;<X()):#E'SE[6LFF"+/,!B<R/00T0[AE/,*8HI:<6
6819M^@X<2<3(&+2G^PH2##R4B@61-=&C&8U<[D@:(B1/2D5B0P3[F?"YD.KF==W[
6820M_18:NY#I:L.^12UY_\=;VWA4UK@WUWBX<G;+J%U(:TQ9XPD\9A26,O5AGJF)
6821MZ=35*FL\*FO<>Q&F/C$?#\0H*A(R"=.>[K7<Q)[A122*7*7+F7=GG.6BV0(N
6822MQ+#FT+O;""*%?1/)Y&R=<)CO+W`SWEFZXYT%QG/J?PK#H9!,IA`K_=G7TVN:
6823MI]V=%<C/,]TG_6Q4:.S62+GW[\`7,.Z&J61C6_(A;C;$W=Z>&0,4H4/&8</(
6824M.=J2F]JM^7#M1_UV<VS$20^LP#^JI'`$/GJP89OFI-QY*7=>JCXO59R1B#N9
6825M"W]MUHS76KJ,#<#TBD9"08H*OJ$4DV.'?M%4#LTED<5HDT(W!1'9?=,*G2]+
6826M"*G7UM.0?A&.'&!<H40?-*4<E4*KV!C:[CCYYV3_66&*2-0P>$!MSY5S#0TX
6827MR1P7[`%G+DL,$Q4#`SM&1,6@T#2-9*""J`]^(-%3/"6G"C$4,IT^=9QJ5F\N
6828MCIJ-JZV-ZS=UM[IYV]C5,[[(H6(_B2*M)$]/610,$\X4'0!I->RZ99:&XAYC
6829M2(;&Q/%Z65^`6.AF9A?6^E:V"77I>XQL^;M(7&C&@,Z%%-N,CUB:91(6HLD<
6830M3!KQ0HXH21'D;'D*+R;<4ZWD1GZ&O7%KU=O<(^N;.Q.O)C=D]PB?6:Q,6DXD
6831M%%]_EH!IC`GPK>-6/[[),+\;26BA!OLZ-'PL`-.Z.$7`::4RS<XU047%E(!/
6832M@=3/0Q%G8)2H/AL*=L%FJEI5DUJ(QPWJGLQEGHH6F`9WML'&ZF1[66&<21PR
6833M6>IH9N.=^)EQ,VWB@!9L*/5C"GW)_``C+1=$$"BS(Q!523SE0Y\7>$F>Y\?T
6834MU:MS>=X00YG^AEON&KOTRQMW9X&$JR6JBSKKD\X\H&?TJ-M-:BE%%D[CCK5\
6835M6W^*+G/:O#?:?/SKVCRJQ8RJ"YCY:'2IN4]8HT>L7YJBY92KN5:[[1?6[@=:
6836M;5NM/KR0.RW)U8="KOHY7#U=J]6?G4^B/D:!2&*>4M+?3^2YB$NV4I/?1!RH
6837M0$13VR61--XEF11)Y!?/%5,51G[UL@L;]M=-JOH-QUM0VYGL*F;B`Z'GO13R
6838M#F9>=EL)>O;>QAXPZ7['E"WTN07O`'F,TZUOH;Z3CS3:Y@.O,Y%K/;`^'CAI
6839M?0MN[B$G/8OU#W"WLZ.M44*+?FI^;A_N%*2NM50MES(3%J2FT/X.M2(8R75:
6840M7V?`)D(&JR#T$GYR(-G(_)G'E&_XNC4N^(*@.RMZO#AJ%CP@W^*NC+=?9^>A
6841MDW&9-;W974T=%MX5SPK4?<T7=ENVC"HW1LPQ,]Z"$=;4%03IY)&H<SH*DS->
6842M;5GEB.JMZ_Q7<M$7"<.V8E*U(W87X%"(*8Z#+/BT+(P&J(5'2,<.W1I$?7/X
6843M^)MYQI`.&*&@$'T%.V\WYX+/Q$*MFJ68W,>+#5EXUK)BON3<T\(A,I43.>,6
6844M!N3Q`SJMT>*<\S52`8<_,!U*C&/,[F>IA/?S`E]KP/P[3`OK4C"2R[:75>Z7
6845M,E#((]CX[3@@"B6^@C&E#.*0<0X\4(HC2)&H($);%WP.[G$42/QM<Q:(KE0.
6846M,%(#6S,TV^?'UU<G33U,X@B4Z"/-`WI)J7C@2>0-H"N1W95`*;AG,@Y46H%+
6847MA)XY-,=L1,L:C_4);)'6>7M,?Z$%/H9B'JJ;PN&#DABB-JNG%0F%5C&&+O/N
6848M'',-Y*,7:`HI8*C*T[@*6%RB%,3)D`>A-A&R2![;2"%]H.>'CF1:-0EME`$5
6849MZ$;%>:Q3%O`]\0![>VTP;JMM.4ADET45>/0U`S6+VQE,ELL341S$*KM6&0D9
6850MIJ#2(=K8@*[0*T"_V'UI7L?)1F5YXD+<Q?#OA"C"7@\]%=QC!6A*3_C:A!+.
6851M?.$E1!C=8+!L\]-Z>3A4T$6MAT]L4ZD@`%F<`MZC3$540ED\$`GW]2A@76[J
6852M"*TURE@Q`[*8MR4HHVN/C+;8H7P1>GWFP(@%2MI[)4#E5<P%BV)W&)58FE\,
6853M]*0(IYUCVB<L$72Y;RV:AZ)K8(T@XEDK!X(B`%-:S+O*#^QJ(]KPF/9(*K`,
6854MCJ!O4^P7*7I%%/,4C`(U@"2>0UXTQ3%%2I3"'9K[$(()H@2AHE^PC!=/LI5^
6855MR+_WL0\E.3__SF1&BR;GX)MK+)._1LPD,!8."ZF+`EO9FYQ\66:MU$CGW%R-
6856M9?P75G!Q:$,ADIUYQ,*\66JLP+5>^I"E-(TW@(/#L\[QEY9=9GN=1O<GH@='
6857MK>999QZR?7K2.2Z;G2X'M0'WE.A"C&.Z8-6K,C9B42X:"VB0"MV*6BV2L(LR
6858MMN[<$ET>Q,I,87.D!F[,0TTM\I%DD8)V&*C!#R3/*U\J0&:XOU=_(/H'%Z+W
6859M`YGZ^W<E,)<(`S&T%Q#(I#7,A*$0T:LE7)Z^O9UU>7S0SY5*9=ZA#R._\E]0
6860M2P$"&0`4````"``C@*D<@2:>K4D%``"-#@``"0`````````!`"``````````
6861M5$E-15(N05--4$L!`AD`%`````@`,0"H&@G<CB8V`@````,```P`````````
6862M```@````<`4``%!!3$Q%5%1%+D-/3%!+`0(9`!0````(`.0Z*!O,Y8UG2`H`
6863M```^```,````````````(````-`'``!33T944D]#2RY&3E102P$"&0`4````
6864M"`#IKJH<$%9BF\<&``"'&P``"@`````````!`"````!"$@``0T]04$52+E!!
6865M4U!+`0(9`!0````(``N_$!O799C<H0D``%(L```*``````````$`(````#$9
6866B``!73U)-244N4$%34$L%!@`````%``4`&P$``/HB`````.!T
6867`
6868end
6869-------------------------------- Cut from here -------------------------------