summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/EMM/EMMSUP.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/MEMM/EMM/EMMSUP.ASM')
-rw-r--r--v4.0/src/MEMM/EMM/EMMSUP.ASM652
1 files changed, 652 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/EMM/EMMSUP.ASM b/v4.0/src/MEMM/EMM/EMMSUP.ASM
new file mode 100644
index 0000000..4034e18
--- /dev/null
+++ b/v4.0/src/MEMM/EMM/EMMSUP.ASM
@@ -0,0 +1,652 @@
1page 58,132
2;******************************************************************************
3 title EMMSUP - EMM support routines
4;******************************************************************************
5;
6; (C) Copyright MICROSOFT Corp. 1986
7;
8; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver
9; EMMLIB.LIB - Expanded Memory Manager Functions Library
10;
11; Module: EMMSUP - EMM support routines
12;
13; Version: 0.04
14;
15; Date: May 13, 1986
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 5/13/86 Original Initial _TEXT
24; 6/14/86 Added _sotofar routine and removed stack define.
25; And added protected mode check to Map_Page (SBP).
26; 6/14/86 map_page now sets _current_map(SBP).
27; 6/14/86 moved save_current_map and restore_map from C code (SBP)
28; 6/14/86 brought SegOffTo24 and SetDescInfo in from LAST code
29; segment as local routines(SBP).
30; 6/21/86 0.02 cld in copyout (SBP).
31; 6/21/86 0.02 MapHandlePage added.
32; 6/23/86 0.02 make_addr, sotofar removed. source_addr and dest_addr
33; added.
34; 6/27/86 0.02 Fix for restore_map.
35; 6/28/86 0.02 Name change from CEMM386 to CEMM (SBP).
36; 7/06/86 0.04 Changed _emm_page,_emm_free, & _pft386 to ptrs (SBP).
37; 7/06/86 0.04 Changed assumes from _DATA to DGROUP (SBP).
38; 7/06/86 0.04 Changed internal save area structure (SBP).
39; 7/06/86 0.04 moved SavePageMap and RestorePageMap to .ASM (SBP).
40; 7/07/86 0.04 moved MapHandlePage,SavePageMap, and RestorePageMap to
41; emmp.asm (SBP).
42; 5/09/88 1.01 moved routines names_match and flush_tlb from win386
43; 9/01/88 rename SegOffTo24/SetDescInfo to
44; SegOffTo24Resident/SetDescInfoResdient and made public
45;******************************************************************************
46;
47; Functional Description:
48; Support routines for emm/386
49; C callable
50;
51;
52;******************************************************************************
53.lfcond ; list false conditionals
54.386p
55
56;******************************************************************************
57; P U B L I C S
58;******************************************************************************
59 public _source_addr
60 public _dest_addr
61 public _copyout
62 public _copyin
63 public _wcopy
64 public _wcopyb
65 public _valid_handle
66 public SetDescInfoResident
67 public SegOffTo24Resident
68;
69;******************************************************************************
70; D E F I N E S
71;******************************************************************************
72
73 include vdmseg.inc
74 include vdmsel.inc
75 include desc.inc
76 include page.inc
77; include instr386.inc
78 include emmdef.inc
79
80FALSE equ 0
81TRUE equ not FALSE
82CR equ 0dh
83LF equ 0ah
84
85 page
86;******************************************************************************
87; E X T E R N A L R E F E R E N C E S
88;******************************************************************************
89
90_DATA SEGMENT
91;
92; pointer to entry stack frame
93; stored as offset, SS
94extrn _regp:word
95
96;
97; current state of mapping registers and # of mapping registers emulated
98;
99;extrn _current_map:byte
100;extrn _map_size:byte
101
102;
103; total # of EMM pages in system
104;
105extrn _total_pages:word
106
107;
108; table of offsets into in to the first page table
109; for user logical emm page map
110;
111extrn _page_frame_base:dword
112
113;
114; ptr to table of emm page # for each handle's logical pages.
115;
116extrn _emm_page:word
117
118;
119; ptr to table of page table entries for the EMM pages
120;
121extrn _pft386:word ; note: actually a dword array
122
123;
124; handle data structure
125;
126extrn _handle_table:word
127extrn _handle_table_size:word
128
129;
130; save area for handles
131;
132extrn _save_map:byte
133
134_DATA ENDS
135
136
137 page
138;******************************************************************************
139; L O C A L D A T A
140;******************************************************************************
141_DATA SEGMENT
142;
143; kludge to prevent unresolved from C compiler
144;
145public __acrtused
146__acrtused label dword
147 dd (0)
148_DATA ENDS
149
150 page
151;******************************************************************************
152; C O D E
153;******************************************************************************
154_TEXT SEGMENT
155assume cs:_TEXT, ds:DGROUP, ss:DGROUP
156
157;***********************************************
158;
159; _source_addr - return far pointer for source address (= int 67 entry DS:SI).
160;
161; SYNOPSIS: src = source_addr()
162; char far *src; /* ptr to area at DS:SI */
163;
164; DESCRIPTION: This function generates a far pointer equivalent to the client's
165; DS:SI pointer. If this code was called in protected mode, the
166; address is a (selector,offset) pair; otherwise, it is a segment
167; offset pair. EMM1_GSEL is used if a selector is needed.
168;
169; 05/09/88 ISP No update needed for MEMM
170;***********************************************
171_source_addr proc near
172;
173 push bp
174;
175 mov bp,[_regp] ; get entry stack frame pointer
176 test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ?
177 jnz sa_pm ; N: go get selector/offset
178 mov ax,word ptr [bp.rSI] ; Y: get offset
179 mov dx,word ptr [bp.rDS] ; get segment
180 jmp sa_exit ; return DX:AX = seg:offset
181;
182; protected mode - set up selector to client's DS
183sa_pm:
184 push bx
185 push cx
186 push es ; save ES
187 ;
188 ; load ES with GDT alias
189 ;
190 push GDTD_GSEL
191 pop es ; ES -> GDT
192 ;
193 ; compute physical address
194 ;
195 mov ax,word ptr [bp.rDS] ; ax <-- base addr
196 mov dx,word ptr [bp.rSI] ; dx <-- offset
197 call SegOffTo24Resident ; converts to physical addr
198
199 ;
200 ; set up the appropriate table entry
201 ;
202 mov bx,EMM1_GSEL ; bx <-- selector
203 mov cx,0FFFFh ; cx <-- gets limit (64k)
204 mov ah,D_DATA0 ; ah <-- gets access rights
205 ;
206 ; at this point:
207 ; ah -- access rights
208 ; al -- bits 16-23 of linear address
209 ; dx -- low 16 bits of linear address
210 ; cx -- limit = 64k
211 ; bx -- selector
212 ; es -- selector to GDT Alias
213 call SetDescInfoResident ; set up descriptor
214
215 ;
216 ; set up return pointer
217 ;
218 xor ax,ax ; ax <-- offset (0)
219 mov dx,bx ; dx <-- selector
220 ;
221 pop es ; restore ES
222 pop cx
223 pop bx
224;
225sa_exit:
226 pop bp
227 ret
228;
229_source_addr endp
230
231;***********************************************
232;
233; _dest_addr - return far pointer for destination address (= int 67 entry ES:DI).
234;
235; SYNOPSIS: dest = dest_addr()
236; char far *dest; /* ptr to area at ES:DI */
237;
238; DESCRIPTION: This function generates a far pointer equivalent to the client's
239; ES:DI pointer. If this code was called in protected mode, the
240; address is a (selector,offset) pair; otherwise, it is a segment
241; offset pair. EMM2_GSEL is used if a selector is needed.
242;
243; 05/09/88 ISP No update needed for MEMM
244;***********************************************
245_dest_addr proc near
246;
247 push bp
248;
249 mov bp,[_regp] ; get entry stack frame pointer
250 test [bp.PFlag],PFLAG_VIRTUAL ;Q: real/virtual mode ?
251 jnz da_pm ; N: go get selector/offset
252 mov ax,word ptr [bp.rDI] ; Y: get offset
253 mov dx,word ptr [bp.rES] ; get segment
254 jmp da_exit ; return DX:AX = seg:offset
255;
256; protected mode - set up selector to client's DS
257da_pm:
258 push bx
259 push cx
260 push es ; save ES
261 ;
262 ; load ES with GDT alias
263 ;
264 push GDTD_GSEL
265 pop es ; ES -> GDT
266 ;
267 ; compute physical address
268 ;
269 mov ax,word ptr [bp.rES] ; ax <-- base addr
270 mov dx,word ptr [bp.rDI] ; dx <-- offset
271 call SegOffTo24Resident ; converts to physical addr
272
273 ;
274 ; set up the appropriate table entry
275 ;
276 mov bx,EMM2_GSEL ; bx <-- selector
277 mov cx,0FFFFh ; cx <-- gets limit (64k)
278 mov ah,D_DATA0 ; ah <-- gets access rights
279 ;
280 ; at this point:
281 ; ah -- access rights
282 ; al -- bits 16-23 of linear address
283 ; dx -- low 16 bits of linear address
284 ; cx -- limit = 64k
285 ; bx -- selector
286 ; es -- selector to GDT Alias
287 call SetDescInfoResident ; set up descriptor
288
289 ;
290 ; set up return pointer
291 ;
292 xor ax,ax ; ax <-- offset (0)
293 mov dx,bx ; dx <-- selector
294 ;
295 pop es ; restore ES
296 pop cx
297 pop bx
298;
299da_exit:
300 pop bp
301 ret
302;
303_dest_addr endp
304
305 page
306;***********************************************
307;
308; _copyout
309;
310; This routine takes a far pointer, a near pointer
311; and a byte count and copies from the near address
312; to the far address.
313;
314; Parameters:
315; destptr -- sel:off 286 pointer to target area
316; srcptr --- offset of source data in current D Seg
317; count ---- byte count for copy
318;
319; uses:
320; cx, ax, es
321;
322; 05/09/88 ISP No update needed for MEMM
323;***********************************************
324destptr = 4
325srcptr = 8
326count = 10
327_copyout proc near
328 push bp ; entry prolog
329 mov bp,sp
330 push di ; reg var
331 push si ; reg var
332
333 les di,[bp+destptr] ; es:di <-- destination address
334 mov si,[bp+srcptr] ; ds:si <-- source address
335 mov cx,[bp+count] ; cx <-- byte count
336 cld ; strings foward
337 rep movsb ; do it
338
339 pop si ; restore reg var
340 pop di ; restore reg var
341 pop bp
342 ret
343_copyout endp
344 page
345
346;***********************************************
347;
348; _copyin
349;
350; This routine takes a near pointer, a far pointer
351; and a byte count and copies from the far address
352; to the near address.
353;
354; Parameters:
355; destptr -- offset of dest in current D Seg
356; srcptr --- sel:off 286 pointer to source data area
357; count ---- byte count for copy
358;
359; uses:
360; cx, ax, es
361;
362; 05/09/88 ISP Written for MEMM.
363;***********************************************
364destptr = 4
365srcptr = 6
366count = 10
367_copyin proc near
368 push bp ; entry prolog
369 mov bp,sp
370 push di ; reg var
371 push si ; reg var
372 push ds
373
374 push ds
375 pop es ; es to dgroup
376
377 mov di,[bp+destptr] ; es:di <-- destination address
378 lds si,[bp+srcptr] ; ds:si <-- source address
379 mov cx,[bp+count] ; cx <-- byte count
380 cld ; strings foward
381 rep movsb ; do it
382
383 pop ds
384 pop si ; restore reg var
385 pop di ; restore reg var
386 pop bp
387 ret
388_copyin endp
389 page
390;***********************************************
391;
392; _wcopy
393;
394; This routine takes a two near pointers
395; and a word count and copies from the
396; first address to the second address.
397;
398; Parameters:
399; srcptr --- offset of source data in current D Seg
400; destptr -- offset of destination address in DS
401; count ---- word count for copy
402;
403; uses:
404; si, di, cx, ax
405; (si, di are restored)
406;
407; 05/09/88 ISP No update needed for MEMM
408;***********************************************
409srcptr = 4
410destptr = 6
411count = 8
412_wcopy proc near
413 push bp ; entry prolog
414 mov bp,sp
415 push di ; reg var
416 push si ; reg var
417
418 cld ; clear dir flag (forward move)
419 mov ax,ds ;
420 mov es,ax ; mov es,ds
421 mov di,[bp+destptr] ; es:di <-- destination address
422 mov si,[bp+srcptr] ; ds:si <-- source address
423 mov cx,[bp+count] ; cx <-- word count
424 rep movsw ; do it
425
426 pop si ; restore reg var
427 pop di ; restore reg var
428 pop bp
429 ret
430_wcopy endp
431 page
432;***********************************************
433;
434; _wcopyb
435;
436; This routine takes a two near pointers
437; and a word count and copies from the
438; first address to the second address.
439; The copy is done backwards to allow certain overlap of source and destination.
440;
441; Parameters:
442; srcptr --- offset of source data in current D Seg
443; destptr -- offset of destination address in DS
444; count ---- word count for copy
445;
446; uses:
447; si, di, cx, ax, es
448; (si, di are restored)
449;
450; 05/20/88 ISP Shifted in from win386 and updated for 16 bit ptrs
451;***********************************************
452srcptr = 4
453destptr = 6
454count = 8
455_wcopyb proc near
456 push bp ; entry prolog
457 mov bp,sp
458 push di ; reg var
459 push si ; reg var
460
461 mov ax,ds ;
462 mov es,ax ; mov es,ds
463 mov di, word ptr [bp+destptr] ; destination address
464 mov si, word ptr [bp+srcptr] ; source address
465 mov cx, word ptr [bp+count] ; word count
466 dec cx
467 shl cx, 1 ; offset of 'last' word to move
468 add si, cx
469 add di, cx
470 mov cx, word ptr [bp+count] ; recover word count
471
472 std ; set dir flag (backward move)
473 rep movsw ; do it
474 cld ; 'C' tends to expect this.
475
476 pop si ; restore reg var
477 pop di ; restore reg var
478 pop bp
479 ret
480_wcopyb endp
481 page
482;***********************************************
483;
484; _valid_handle - validate current handle
485;
486; SYNOPSIS: hp = _valid_handle()
487; struct handle_ptr *hp; /* ptr to handle's structure */
488; /* OR NULL_HANDLE if invalid handle */
489; /* also sets AH = INVALID_HANDLE if it fails */
490;
491; DESCRIPTION: This routine validates the current handle in regp->rDX and
492; returns either an error or a ptr to the handle's index and
493; page count structure.
494;
495; 05/09/88 ISP No update needed for MEMM
496;***********************************************
497_valid_handle proc near
498;
499 push bp
500 mov bp,[_regp] ; get entry args pointer
501 push bx
502;
503 mov bx,word ptr [bp.rDX] ; BX = entry handle
504 cmp bx,[_handle_table_size] ;Q: handle in range ?
505 jae vh_fail ; N: return invalid handle error
506 shl bx,2 ; Y: BX = handle's table offset
507 add bx,offset DGROUP:_handle_table ; BX = offset to handle's data
508 cmp [bx.ht_index],NULL_PAGE ;Q: is this an active handle ?
509 je vh_fail ; N: return invalid handle error
510 mov ax,bx ; Y: return ptr to handle's data
511;
512vh_exit:
513 pop bx
514 pop bp
515 ret
516vh_fail:
517 mov byte ptr [bp.rAX+1],INVALID_HANDLE ; set AH on stack
518 mov ax,NULL_HANDLE ; return NULL_HANDLE to caller
519 jmp short vh_exit
520
521;
522_valid_handle endp
523
524;***********************************************
525;
526; flush_tlb:
527;
528; no params, no return value, uses eax
529;
530; flush the Translation Look-Aside Buffer
531;
532; 05/09/88 ISP Shifted in from WIN386
533;***********************************************
534_flush_tlb proc near
535public _flush_tlb
536 mov eax, cr3
537 mov cr3, eax
538 ret
539_flush_tlb endp
540
541;***********************************************
542;
543; _Names_Match
544;
545; Returns a boolean value (0 = false, FFFF = True) if 2 handle names match
546;
547; uses:
548; cx, ax
549;
550; 05/09/88 ISP Shifted in from WIN386 and modified for 16 bit ptrs
551;***********************************************
552name1 = 4
553name2 = 6
554 public _Names_Match
555_Names_Match proc near
556 push bp ; entry prolog
557 mov bp,sp
558 push di ; reg var
559 push si ; reg var
560
561 mov ax,ds ; initialise es segment to
562 mov es,ax ; DGROUP
563
564 xor ax, ax ; Assume it did NOT work
565
566 mov di, word ptr [bp+name1] ; First name
567 mov si, word ptr [bp+name2] ; Second name
568 cld
569 mov cx, 2 ; Compare 2 dwords
570 rep cmpsd ; do it
571 jne SHORT Names_Dont_Match
572 not ax ; They match!
573
574Names_Dont_Match:
575 pop si ; restore reg var
576 pop di ; restore reg var
577 pop bp
578 ret
579_Names_Match endp
580
581 page
582;** SetDescInfoResident - set descriptor information
583;
584; The limit field of a specified descriptor is set.
585; (limit = size - 1).
586; The base address of the specified descriptor is set.
587; The access field of the specified descriptor is set.
588;
589; ENTRY BX = selector
590; ES:0 = descriptor table to use
591; CX = limit
592; AL, DX = 24 bit base address
593; AH = access rights byte
594; EXIT None
595; USES Flags, other regs preserved
596;
597; WARNING This code only works on a 286. It can be called in
598; either mode.
599
600SetDescInfoResident proc near
601 push bx ; save selector
602 and bl,SEL_LOW_MASK
603
604; fill in the limit field
605
606 mov es:[bx],cx
607
608; fill in base address
609
610 mov es:[bx + 2],dx
611 mov es:[bx + 4],al
612
613; fill in access rights byte
614
615 mov es:[bx + 5],ah
616 pop bx
617 ret
618SetDescInfoResident endp
619
620 page
621;** SegOffTo24Resident - convert seg:off to 24 bit physical address
622;
623; The specified real mode segment:offset is converted to
624; a 24 bit physical address.
625;
626; ENTRY AX = segment
627; DX = offset
628; EXIT AL, DX = 24 bit physical address
629; USES AH, Flags, other regs preserved.
630;
631; WARNING This code only works on a 286. It can be called in
632; either mode.
633
634SegOffTo24Resident proc near
635 push cx
636
637; Convert AX:DX into 24 bit addr in AL, DX
638
639 mov ch,ah
640 shl ax,4
641 shr ch,4 ; CH = high byte
642 add dx,ax ; DX = low word
643 mov al,ch ; AL = high byte
644 adc al,0 ; propagate cy from low word
645
646 pop cx
647 ret
648SegOffTo24Resident endp
649
650_TEXT ENDS
651END
652 \ No newline at end of file