]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/EMM/EMMSUP.ASM
2 ;******************************************************************************
3 title EMMSUP
- EMM support routines
4 ;******************************************************************************
6 ; (C) Copyright MICROSOFT Corp. 1986
8 ; Title: CEMM.EXE - COMPAQ Expanded Memory Manager 386 Driver
9 ; EMMLIB.LIB - Expanded Memory Manager Functions Library
11 ; Module: EMMSUP - EMM support routines
17 ;******************************************************************************
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
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
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 ;******************************************************************************
47 ; Functional Description:
48 ; Support routines for emm/386
52 ;******************************************************************************
53 .lfcond
; list false conditionals
56 ;******************************************************************************
58 ;******************************************************************************
66 public SetDescInfoResident
67 public SegOffTo24Resident
69 ;******************************************************************************
71 ;******************************************************************************
77 ; include instr386.inc
86 ;******************************************************************************
87 ; E X T E R N A L R E F E R E N C E S
88 ;******************************************************************************
92 ; pointer to entry stack frame
93 ; stored as offset, SS
97 ; current state of mapping registers and # of mapping registers emulated
99 ;extrn _current_map:byte
100 ;extrn _map_size:byte
103 ; total # of EMM pages in system
105 extrn _total_pages
:word
108 ; table of offsets into in to the first page table
109 ; for user logical emm page map
111 extrn _page_frame_base
:dword
114 ; ptr to table of emm page # for each handle's logical pages.
119 ; ptr to table of page table entries for the EMM pages
121 extrn _pft386
:word ; note: actually a dword array
124 ; handle data structure
126 extrn _handle_table
:word
127 extrn _handle_table_size
:word
130 ; save area for handles
138 ;******************************************************************************
140 ;******************************************************************************
143 ; kludge to prevent unresolved from C compiler
146 __acrtused
label dword
151 ;******************************************************************************
153 ;******************************************************************************
155 assume
cs:_TEXT
, ds:DGROUP
, ss:DGROUP
157 ;***********************************************
159 ; _source_addr - return far pointer for source address (= int 67 entry DS:SI).
161 ; SYNOPSIS: src = source_addr()
162 ; char far *src; /* ptr to area at DS:SI */
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.
169 ; 05/09/88 ISP No update needed for MEMM
170 ;***********************************************
171 _source_addr proc
near
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
182 ; protected mode - set up selector to client's DS
188 ; load ES with GDT alias
193 ; compute physical address
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
200 ; set up the appropriate table entry
202 mov bx,EMM1_GSEL
; bx <-- selector
203 mov cx,0FFFFh ; cx <-- gets limit (64k)
204 mov ah,D_DATA0
; ah <-- gets access rights
207 ; ah -- access rights
208 ; al -- bits 16-23 of linear address
209 ; dx -- low 16 bits of linear address
212 ; es -- selector to GDT Alias
213 call SetDescInfoResident
; set up descriptor
216 ; set up return pointer
218 xor ax,ax ; ax <-- offset (0)
219 mov dx,bx ; dx <-- selector
231 ;***********************************************
233 ; _dest_addr - return far pointer for destination address (= int 67 entry ES:DI).
235 ; SYNOPSIS: dest = dest_addr()
236 ; char far *dest; /* ptr to area at ES:DI */
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.
243 ; 05/09/88 ISP No update needed for MEMM
244 ;***********************************************
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
256 ; protected mode - set up selector to client's DS
262 ; load ES with GDT alias
267 ; compute physical address
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
274 ; set up the appropriate table entry
276 mov bx,EMM2_GSEL
; bx <-- selector
277 mov cx,0FFFFh ; cx <-- gets limit (64k)
278 mov ah,D_DATA0
; ah <-- gets access rights
281 ; ah -- access rights
282 ; al -- bits 16-23 of linear address
283 ; dx -- low 16 bits of linear address
286 ; es -- selector to GDT Alias
287 call SetDescInfoResident
; set up descriptor
290 ; set up return pointer
292 xor ax,ax ; ax <-- offset (0)
293 mov dx,bx ; dx <-- selector
306 ;***********************************************
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.
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
322 ; 05/09/88 ISP No update needed for MEMM
323 ;***********************************************
328 push bp ; entry prolog
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
339 pop si ; restore reg var
340 pop di ; restore reg var
346 ;***********************************************
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.
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
362 ; 05/09/88 ISP Written for MEMM.
363 ;***********************************************
368 push bp ; entry prolog
375 pop es ; es to dgroup
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
384 pop si ; restore reg var
385 pop di ; restore reg var
390 ;***********************************************
394 ; This routine takes a two near pointers
395 ; and a word count and copies from the
396 ; first address to the second address.
399 ; srcptr --- offset of source data in current D Seg
400 ; destptr -- offset of destination address in DS
401 ; count ---- word count for copy
405 ; (si, di are restored)
407 ; 05/09/88 ISP No update needed for MEMM
408 ;***********************************************
413 push bp ; entry prolog
418 cld ; clear dir flag (forward move)
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
426 pop si ; restore reg var
427 pop di ; restore reg var
432 ;***********************************************
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.
442 ; srcptr --- offset of source data in current D Seg
443 ; destptr -- offset of destination address in DS
444 ; count ---- word count for copy
448 ; (si, di are restored)
450 ; 05/20/88 ISP Shifted in from win386 and updated for 16 bit ptrs
451 ;***********************************************
456 push bp ; entry prolog
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
467 shl cx, 1 ; offset of 'last' word to move
470 mov cx, word ptr [bp+count
] ; recover word count
472 std ; set dir flag (backward move)
474 cld ; 'C' tends to expect this.
476 pop si ; restore reg var
477 pop di ; restore reg var
482 ;***********************************************
484 ; _valid_handle - validate current handle
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 */
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.
495 ; 05/09/88 ISP No update needed for MEMM
496 ;***********************************************
497 _valid_handle proc
near
500 mov bp,[_regp
] ; get entry args pointer
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
517 mov byte ptr [bp.rAX+1],INVALID_HANDLE
; set AH on stack
518 mov ax,NULL_HANDLE
; return NULL_HANDLE to caller
524 ;***********************************************
528 ; no params, no return value, uses eax
530 ; flush the Translation Look-Aside Buffer
532 ; 05/09/88 ISP Shifted in from WIN386
533 ;***********************************************
541 ;***********************************************
545 ; Returns a boolean value (0 = false, FFFF = True) if 2 handle names match
550 ; 05/09/88 ISP Shifted in from WIN386 and modified for 16 bit ptrs
551 ;***********************************************
555 _Names_Match proc
near
556 push bp ; entry prolog
561 mov ax,ds ; initialise es segment to
564 xor ax, ax ; Assume it did NOT work
566 mov di, word ptr [bp+name1
] ; First name
567 mov si, word ptr [bp+name2
] ; Second name
569 mov cx, 2 ; Compare 2 dwords
571 jne SHORT Names_Dont_Match
575 pop si ; restore reg var
576 pop di ; restore reg var
582 ;** SetDescInfoResident - set descriptor information
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.
589 ; ENTRY BX = selector
590 ; ES:0 = descriptor table to use
592 ; AL, DX = 24 bit base address
593 ; AH = access rights byte
595 ; USES Flags, other regs preserved
597 ; WARNING This code only works on a 286. It can be called in
600 SetDescInfoResident proc
near
601 push bx ; save selector
604 ; fill in the limit field
608 ; fill in base address
613 ; fill in access rights byte
618 SetDescInfoResident endp
621 ;** SegOffTo24Resident - convert seg:off to 24 bit physical address
623 ; The specified real mode segment:offset is converted to
624 ; a 24 bit physical address.
628 ; EXIT AL, DX = 24 bit physical address
629 ; USES AH, Flags, other regs preserved.
631 ; WARNING This code only works on a 286. It can be called in
634 SegOffTo24Resident proc
near
637 ; Convert AX:DX into 24 bit addr in AL, DX
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
648 SegOffTo24Resident endp