]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/EMM/EMMSUP.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / MEMM / EMM / EMMSUP.ASM
1 page 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
80 FALSE equ 0
81 TRUE equ not FALSE
82 CR equ 0dh
83 LF 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
94 extrn _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 ;
105 extrn _total_pages:word
106
107 ;
108 ; table of offsets into in to the first page table
109 ; for user logical emm page map
110 ;
111 extrn _page_frame_base:dword
112
113 ;
114 ; ptr to table of emm page # for each handle's logical pages.
115 ;
116 extrn _emm_page:word
117
118 ;
119 ; ptr to table of page table entries for the EMM pages
120 ;
121 extrn _pft386:word ; note: actually a dword array
122
123 ;
124 ; handle data structure
125 ;
126 extrn _handle_table:word
127 extrn _handle_table_size:word
128
129 ;
130 ; save area for handles
131 ;
132 extrn _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 ;
145 public __acrtused
146 __acrtused label dword
147 dd (0)
148 _DATA ENDS
149
150 page
151 ;******************************************************************************
152 ; C O D E
153 ;******************************************************************************
154 _TEXT SEGMENT
155 assume 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
183 sa_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 ;
225 sa_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
257 da_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 ;
299 da_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 ;***********************************************
324 destptr = 4
325 srcptr = 8
326 count = 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 ;***********************************************
364 destptr = 4
365 srcptr = 6
366 count = 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 ;***********************************************
409 srcptr = 4
410 destptr = 6
411 count = 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 ;***********************************************
452 srcptr = 4
453 destptr = 6
454 count = 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 ;
512 vh_exit:
513 pop bx
514 pop bp
515 ret
516 vh_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
535 public _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 ;***********************************************
552 name1 = 4
553 name2 = 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
574 Names_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
600 SetDescInfoResident 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
618 SetDescInfoResident 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
634 SegOffTo24Resident 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
648 SegOffTo24Resident endp
649
650 _TEXT ENDS
651 END
652 \1a