page 58,132 ;****************************************************************************** title ALLOCMEM - allocate memory for EMM Pages Pool ;****************************************************************************** ; ; (C) Copyright MICROSOFT Corp. 1986 ; ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver ; ; Module: AllocMem - allocate memory for EMM Pages Pool ; ; Version: 0.05 ; ; Date: May 24,1986 ; ; Author: ; ;****************************************************************************** ; ; Change Log: ; ; DATE REVISION Description ; -------- -------- -------------------------------------------- ; 05/24/86 Original ; 06/28/86 0.02 code read changes to various routines ; 07/05/86 0.04 Changes due to segment re-org ; 07/06/86 0.04 Made EXT_RES a define ; 07/06/86 0.04 Changed to DGROUP assume ; 07/10/86 0.05 added NOHIMEM flag ; 06/02/88 pc change from VDISK allocation to INT-15 method ; 07/26/88 isp completed work in changing over to int15 alloc ; ;****************************************************************************** ; Functional Description: ; This module allocates the pool of memory to be used for the pool of ; EMM pages. The pool of memory is allocated from "high" extended ; memory (located in the 15-16 Meg range)and from "regular" extended memory ; (starting at 1 Meg). This module attempts to allocate high memory first, ; then extended memory. When allocating memory from either area, the memory ; is allocated in 16k byte blocks which are aligned on a physical 4k boundary. ; This module attempts to allocate extended memory using the int15 allocation ; scheme. ; ; NOTE: if this module is compiled with NOHIMEM defined, then ; this code will not attempt to use the OEM specific ; "high" memory. ; ;****************************************************************************** .lfcond .386p ; ; ;****************************************************************************** ; P U B L I C D E C L A R A T I O N S ;****************************************************************************** ; public AllocMem public DeallocMem public xbase_addr_l ; data publics public xbase_addr_h public ext_size public sys_size page ;****************************************************************************** ; L O C A L C O N S T A N T S ;****************************************************************************** ; include vdmseg.inc include vdmsel.inc include emm386.inc include driver.equ include driver.str include romxbios.equ include desc.inc include ascii_sm.equ include oemdep.inc include emmdef.inc ; EXT_RES equ 10h ; must be a power of 2. ; GET_VER equ 30h ; get dos version number MSDOS equ 21h ; DOS interrupt ; FALSE equ 0 TRUE equ not FALSE ;****************************************************************************** ; E X T E R N A L R E F E R E N C E S ;****************************************************************************** ; _DATA segment extrn dos_version:byte extrn pool_size:word extrn msg_flag:word ifndef NOHIMEM extrn hi_size:word ; size of hi memory in kbytes extrn hi_alloc:word ; hi memory allocated extrn hisys_alloc:word ; hi system memory allocated ; in 4k byte blocks endif _DATA ends LAST segment extrn mappable_segs:byte ; mappable segment map extrn set_ext:near ; routine to set amount of ext mem ; reported by int15 handler extrn memreq:near ; memory requirements for move extrn pool_initialise:near ; initialise the pool of extended ; memory ifndef NOHIMEM extrn hbuf_chk:near extrn HiAlloc:near extrn HiMod:near endif LAST ends ; page ;****************************************************************************** ; S E G M E N T D E F I N I T I O N ;****************************************************************************** page ;****************************************************************************** ; Data segment ;****************************************************************************** _DATA segment ASSUME CS:DGROUP,DS:DGROUP xbase_addr_l dw 0000h ; 24 bit address of beginning of xbase_addr_h db 10h ; extended mem pool of EMM pages. (1M initially) ext_size dw 0 ; size of extended memory allocated in kb sys_size dw 0 ; size of system memory from 4000h in emm pool total_mem dw 0 ; size of extended memory available at any moment avail_mem dw 0 ; total size (hi+ext) available for MEMM ; _DATA ends ;****************************************************************************** ; ; Code Segment ; ;****************************************************************************** ; LAST segment assume cs:LAST, ds:DGROUP, es:DGROUP page ;****************************************************************************** ; ; AllocMem Allocate Extended memory for MEMM using the int15 ; method of allocating extended memory. ; ; description: ; This routine attempts to get the requested extended memory ; from two sources: a) the himem area (just below 16M) first ; and if not enough b) extended memory. Extended memory is ; allocated using the int15 scheme. We do not care for ; compatibility with vdisk. The memory we allocate either in ; himem area or in extended memory must start at a 4k boundary ; because we are using them as pages. ; ; entry: DS pts to DGROUP ; DGROUP:[pool_size] = mem size requested (kbytes) ; ; exit: If extended memory pool space is not available then ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. ; ; ; used: none ; ; stack: ; ; modified: ISP 07/26/88 Changed to a simple check for availability ; of hi / ext memory and allocation of ; of appropriate amounts of each. ; ; ;****************************************************************************** ; AllocMem proc near ; push ax push bx push cx push dx push es ; ; 1. Check available hi/extended memory ; AM_getmem: call xbuf_chk test [msg_flag],MEM_ERR_MSG ;Q: memory error found ? jz AM_nba ; N: continue with allocation jmp AM_exit ; Y: exit ; ; 2. Allocate extended memory ; AM_nba: call ExtAlloc ; alloc ext mem ifndef NOHIMEM ; if HI memory in this model ; ; 3. Allocate Hi memory ; AM_halloc: call HiAlloc ; Allocate hi memory jnc AM_exit ; no error or [msg_flag],MEM_ERR_MSG ; memory error endif ; ; 4. Allocate system memory ; call SysAlloc ; AM_exit: pop es pop dx pop cx pop bx pop ax ret AllocMem endp ; End of procedure ; page ;****************************************************************************** ; ; DeallocMem Deallocate Extended memory for MEMM using the int15 ; method of allocating extended memory. Note that since ; we call this routine when we haven't already installed tc.) ; the int15 handler we really don't need to do anything ; as far as the regular extended memory is concerned. We ; only need to deallocate hi memory if allocated. ; ; entry: DS pts to DGROUP ; DGROUP:[hi_alloc] amount of hi memory to deallocate ; ; used: none ; ; stack: ; ; modif: 7/26/88 ISP Removed VDISK deallocation of extended memory ;****************************************************************************** ; DeallocMem proc near push ax push bx push cx push dx push si push es ; ifndef NOHIMEM ; if high memory in this model mov ax,[hi_alloc] ; get hi memory to deallocate or ax,ax ; q: did we ever get any? jz deall_hisys ; n: check hi system memory neg ax ; # of 16 byte pieces to remove mov [hi_alloc],0 ; make sure we never do it again deall_hisys: mov bx,[hisys_alloc] ; get hi system memory to deallocate neg bx ; update by a negative amount add bx,ax ; q: any hi or hisys to deallocate? jz deall_ext ; n: don't waste our time doing it sub bx,ax ; y: straighten our regs out mov [hisys_alloc],0 ; make sure we don't do it again call HImod ; modify memory. ignore any errors deall_ext: ; endif ; end of conditional pop es pop si pop dx pop cx pop bx pop ax ; ret DeallocMem endp ; page ;****************************************************************************** ; ; xbuf_chk Extended memory pool check. ; Check 1) for previously loaded MEMM,VDISKs in extended memory ; 2) available memory pool space. (hi memory and extended) ; ; entry: DS = DGROUP ; DGROUP:[pool_size] = mem size requested (kbytes) ; ; ; exit: If hi memory pool space is available then ; ; DGROUP:[hi_size] = hi memory size allocated (kbytes). ; ; If extended memory pool space is necessary and available then ; ; DGROUP:[xbase_addr_h] and DGROUP:[xbase_addr_l] contain the ; starting 24-bit address of MEMM extended memory pool. ; ; DGROUP:[pool_size] = mem size ALLOCATED (kbytes) ; DGROUP:[total_mem] = total extended memory left after allocation ; DGROUP:[avail_mem] = available memory for MEMM. ; DGROUP:[ext_size] = extended memory size allocated (kbytes) ; ; If hi/extended memory pool space is not available then ; set MEM_ERR_MSG bit in DGROUP:[msg_flag] and exit. ; ; used: none ; ; stack: ; ; modified: ISP 07/26/88 int15 allocation requires different check ; on extended memory. substancial rewrite. ;****************************************************************************** ; xbuf_chk proc near ; push ax push bx push cx push dx push di ; ; determine amount of extended memory and store it in total_mem ; mov ah,EXT_MEM ; function request - ext mem data clc ; clear carry flag int XBIOS ;Q: extended memory supported ? ; jnc store_ext ; Y: go to store the amount got xor ax,ax ; N: Assume zero extended memory store_ext: mov [total_mem],ax ; ifndef NOHIMEM ; if high memory in this model ; ; check for hi memory ; call hbuf_chk ; get available hi memory in AX jc xb_NoHiMem mov [hi_size],ax ; save it mov [avail_mem],ax ; update available memory xb_NoHiMem: mov ax,[pool_size] cmp ax,[hi_size] ; q: enough? ja get_ext ; n: try extended memory mov [hi_size],ax ; y: just use enough jmp x_buf_exit ; and exit endif get_ext: mov ax,[total_mem] ; get size of extended memory available ; Y: how much there ? ; ; we have to reserve enough memory here to ship the segments up hi. ; call memreq ; get memory requirements for our o ; our grand operation in cx in K cmp ax,cx ; lets see if we can satisfy jbe x_buf_no_install ; if not we shan't install memm push ax sub ax,cx cmp ax,64 + 64 ; we should try to leave enough memory ; for himem and atleast four pages of ; expanded memory. pop ax jbe x_buf_no_install ; if we don't have enough for this we ; shouldn't install memm ; ; we can now get memory to shift things up. and intialise the manager of ; this pool. ; sub ax,cx ; ax = start of this pool as an offset ; in K from 1M ; cx = size in K of this pool call pool_initialise ; intialise the pool or ax,ax ;Q: any extended memory ? jz x_buf_2 ; N: If none go to set buf adj or no ; memory error ; ; Y: continue to process ; mov bx,[pool_size] ; get size requested ; ifndef NOHIMEM ; if high memory in this model sub bx,[hi_size] ; adjust by the size already allocated endif ; from the high memory and ax,0fff0h ; round to 16k boundary ; ; it is necessary to support himem. So if we have a 64k block at 1M we ; should leave it for himem. The himem we are talking about here is the ; EMS 4.1 standard himem at 1M ; ; initialise reserved memory for himem ; xor cx,cx ; amount reserved for himem ; ; see if we have 64k available for himem ; cmp ax,64 ; Q:do we have 64k? jb no_himem_alloc ; N: we reserve nothing for himem ; Y: we should reserve 64k for himem ; ; reserve 64k for himem ; mov cx,64 sub ax,cx ; no_himem_alloc: ; cmp ax,bx ; compare amount available to size needed jae enough_mem ; Y: fine mov bx,ax ; N: adjust size reuested to size avail enough_mem: ; ; add back the memory reserved for himem as this figures in the size of ; free extended memory ; add ax,cx ; adjust size to include amnt res. himem sub ax,bx ; adjust the size of extended memory ; after allocation mov [total_mem],ax ; store size of extended mem available ; add [avail_mem],bx ; add memory available to memory pool mov [ext_size],bx ; and indicate size allocated ; ; find the start address of extended memory allocated ; mov cx,1024 ; kb multiplier mul cx ; dx:ax = ax*cx add [xbase_addr_l],ax ; adjsut starting address of allocated mem adc [xbase_addr_h],dl ; higher byte of 24 bit address ; x_buf_2: ; mov ax,[avail_mem] ; ax == Available memory cmp ax,[pool_size] ; Q: Extended memory available? jnb x_buf_exit ; Y: Go to finish ; not_enough: or ax,ax ; Q: Any extended memory available? jz x_buf_no_install ; N: Set error flag and exit mov [pool_size],ax ; Y: Set pool_size to remaining memory or [msg_flag],SIZE_ADJ_MSG ; Set buffer adjusted message bit jmp short x_buf_exit ; And jump to exit ; x_buf_no_install: or [msg_flag],MEM_ERR_MSG ; memory error found in x_bufchk ; x_buf_exit: pop di pop dx pop cx pop bx pop ax ret ; *** return *** ; xbuf_chk endp ; page ;****************************************************************************** ; ; ExtAlloc - allocate extended memory - update break address for ext. mem. ; ; entry: DS pts to DGROUP ; ; exit: extended memory size ; ; used: none. int15 size reported by int 15 handler in MEMM adjusted. ; ; stack: ; ; modified: ISP 07/26/88 Substancially simplified. For int15 scheme ; allocation is by lowering the size of int15 ; reported extended memory size. ; ;****************************************************************************** ExtAlloc proc near ; mov bx,[total_mem] ;size left after allocation to MEMM call set_ext ; set this size in the int15 handler ret ; ExtAlloc endp ; ;****************************************************************************** ; ; SysAlloc - allocate extended memory - update break address for ext. mem. ; ; entry: DS pts to DGROUP ; ; exit: system memory size ; ; used: none. ; ; stack: ; ; written: ISP 07/28/88 This allocates the system memory from 0000H ; to A000h to the EMM pool. This is for the LIM ; 4.0 implementation. ; ;****************************************************************************** SysAlloc proc near ; push ax push bx push cx ; ; find end of memory reported by bios int 12 and round this to upper 16k. ; int 12h add ax,0000fh ; and ax,0fff0h ; round it 16k figure ; ; convert this to the a page # ; shr ax, 4 ; number of 16k pages ; ; start search for pages which can be reclaimed from the system mem. region ; mov cx,ax ; number of pages from pg0 to be examined mov [sys_size],0 ; initialise the system memory allocate xor bx,bx ; page # jcxz find_sys_done find_sys_page: cmp cs:mappable_segs[bx], PAGE_MAPPABLE jne find_next_sys add [sys_size],16 ; page found add 16k to system mem size find_next_sys: inc bx loop find_sys_page find_sys_done: mov ax,[sys_size] ; find the total memory found add [pool_size],ax ; add this to the pool size ; pop cx pop bx pop ax ret SysAlloc endp LAST ends ; End of segment ; end ; End of module