;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
;/*****************************************************************************
;*
;* SOURCE FILE NAME = MEMMAN.ASM
;*
;* DESCRIPTIVE NAME = Memory management program
;*
;*
;* VERSION      V2.0
;*
;* DATE         01/13/88
;*
;* DESCRIPTION  This file contains all the routines which interface to the OS|2  
;*              and Presentation Manager memory management functions.
;*
;* FUNCTIONS    Public:     alloc_ddc     
;*                          free_ddc      
;*                          alloc_bm      
;*                          free_bm       
;*                          alloc_far_mem 
;*                          free_far_mem  
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   01/13/88                     Walt Moore [waltm] Created
;*   02/02/88                     Walt Moore [waltm]
;*                                  Firewalled the return value (which is why               
;*                                  we have this routine -                                  
;*                                  gain_access_to_selector)                                
;*
;*   01/12/88                     Walt Moore [waltm] The big rewrite.
;*                                  Wrote private_alloc
;*                                  Wrote private_free
;*   02/27/90                     Viroon Touranachun [viroont]
;*                                  Wrote alloc_far_mem
;*                                  Wrote free_far_mem
;*                                  Changed the heap parameters to minimize 
;*                                  the heap's fragmentation.
;*                                  Wrote  init_far_heap
;*****************************************************************************/

.286p

        .xlist
        include cmacros.inc
        include pmgre.inc
DINCL_GAIN_ACCESS_DEFINED                        equ 1
        include driver.inc
INCL_DOSMEMMGR  equ     1
        include bsedos16.inc                      ;OS|2 memory manager equates
        .list

        externFP DosAllocSeg                      ;OS|2 memory manager functions
        externFP DosAllocHuge
        externFP DosFreeSeg
        externFP SSAllocSeg
        externFP SSAllocHuge
        externFP SSFreeSeg
        externFP DosGetSeg
        externA  DOSPAGESIZE

        externFP WinAllocMem                      ;Winthorn memory manager functions
        externFP WinAvailMem                      ;Winthorn memory manager functions
        externFP WinFreeMem
        externFP WinCreateHeap
        externFP WinAllocFarMem                   ;Winthorn memory manager functions
        externFP WinFreeFarMem
        externFP WinCreateFarHeap

        externFP far_enter_driver_sem
        externFP far_leave_driver
        externFP GreBitmapLimitWarning  ; @DMS

sBegin  Data

        externD hLocalHeap                        ;Handle to our local heap
        externD FarHeap                 ;Farheap
        externW cbHeap                            ;Size of local heap
        externW usNumBitmapHeaders                ;@DMS nmuber of bitmap headers alloced
        externW fsEngineWarned                    ;@DMS engine warned flag

sEnd    Data

sBegin  Code
        assumes cs,Code

        externNP enter_driver_sem                ;Our own routines
        externNP leave_driver
page

;/***************************************************************************
;*
;* FUNCTION NAME = alloc_ddc
;*
;* DESCRIPTION   = Memory for a ddc is allocated.  No initialization is       
;*                 performed on the allocated memory. The memory semaphore 
;*                 is aquired and released around the allocation.                                                 
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:
;*                       WinAllocMem
;*                 
;* INPUT         = DS = DGROUP 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = handle to memory 
;*                 CX = handle to memory
;* RETURN-ERROR  = AX = 0   
;*                 CX = 0   
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   alloc_ddc,<NEAR,PUBLIC,NODATA,NONWIN>
cBegin
        call    enter_driver_sem
        cCall   WinAllocMem,<hLocalHeap,(size DDC)>
        call    leave_driver
        mov     cx,ax
cEnd
page


;/***************************************************************************
;*
;* FUNCTION NAME = free_ddc
;*
;* DESCRIPTION   = Memory for a ddc is freed.  The identifer for the memory is
;*                 set to the deleted object identifier.  The memory semaphore
;*                 is acquired and released around the allocation.
;*
;*                 Registers Preserved:      
;*                       SI,DI,DS,BP         
;*                 Registers Destroyed:      
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:                    
;*                       WinAllocMem         
;*                 
;* INPUT         = DS:SI = hddc to free 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   free_ddc,<NEAR,PUBLIC,NODATA,NONWIN>
cBegin
        call    enter_driver_sem
        ddc?    si,<SURFACE,LEVELS>
        mov     [si].ddc_usId,DELETED_IDENT
        cCall   WinFreeMem,<hLocalHeap,si,(size DDC)>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<Heap Manager returned an error while freeing an object>
@@:
endif

        call    leave_driver
cEnd

page

;/***************************************************************************
;*
;* FUNCTION NAME = alloc_bm
;*
;* DESCRIPTION   = Memory for a bitmap is allocated.  No initialization is  
;*                 performed on the allocated memory.  The memory semaphore
;*                 is aquired and released around the allocation.
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*
;*                 Calls:
;*                       WinAllocMem
;*
;* INPUT         = DS = DGROUP 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = AX = handle to memory
;*                 CX = handle to memory
;* RETURN-ERROR  = AX = 0
;*                 CX = 0
;**************************************************************************/

BITMAP_PANIC_LEVEL equ 1700
HEAP_CHECK_LEVEL   equ 1400
BITMAP_CHECK_LEVEL equ 300

        assumes ds,Data
        assumes es,nothing

cProc   alloc_bm,<FAR,PUBLIC>
cBegin
        call    enter_driver_sem
        cCall   WinAllocMem,<hLocalHeap,(size BITMAP)>
        call    leave_driver

        push ax                 ; save the return code

        ; Check the return code
        or      ax,ax
        jz      abm_error

        ; inc bitmap headers used
        inc     usNumBitmapHeaders

        ; check if we have been warned
        cmp     fsEngineWarned,0
        jnz     amb_warned

abm_check:
        ; NO if over warning level notify the engine
        cmp     usNumBitmapHeaders,BITMAP_PANIC_LEVEL
        jl      abm_ok

abm_warn :
        cCall   GreBitmapLimitWarning,<0,1>
        mov     fsEngineWarned,1
        jmp     abm_ok

amb_warned:
        ; yes if under warning level reset
        cmp     usNumBitmapHeaders,BITMAP_PANIC_LEVEL
        jge     abm_ok
        mov     fsEngineWarned,0
        jmp     abm_ok

abm_error:
        ; pop up the error
        cCall   GreBitmapLimitWarning,<0,0>

abm_ok:
        pop     ax              ; pop the return code

        mov     cx,ax
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = free_bm
;*
;* DESCRIPTION   = Memory for a bitmap is freed.  The identifer for the     
;*                 memory is set to the deleted object identifier.  The
;*                 memory semaphore is acquired and released around the
;*                 allocation.
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:
;*                       WinAllocMem
;*
;* INPUT         = DS:SI = bitmap to free 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   free_bm,<FAR,PUBLIC>
cBegin
        call    enter_driver_sem

ifdef FIREWALLS
        cmp     [si].bm_sd.sd_usId,SURFACE_IDENT
        jne     free_bm_big_problems
        test    [si].bm_sd.sd_fb,SD_DEVICE
        jz      @F
free_bm_big_problems:
        rip     text,<free_bm - Surface is not a bitmap>
@@:
endif

        mov     [si].ddc_usId,DELETED_IDENT
        cCall   WinFreeMem,<hLocalHeap,si,(size BITMAP)>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<Heap Manager returned an error while freeing an object>
@@:
endif

        call    leave_driver
        dec     usNumBitmapHeaders              ;@DMS
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = global_alloc
;*
;* DESCRIPTION   = Allocate global shared memory of the given size 
;*               
;*                 Registers Preserved:
;*                       BX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,CX,DX,FLAGS
;*                 Calls:
;*                       SSAllocSeg
;*                       SSAllocHuge
;*
;* INPUT         = DX:AX = amount of memory needed                                         
;*                 CX    = allocation flags (only valid flag currently is SEG_DISCARDABLE) 
;*                 SS:BX --> where selector is to be returned                              
;*
;* OUTPUT        = None
;*
;* RETURN-NORMAL = CX = 0               
;* RETURN-ERROR  = CX = OS/2 error code
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   far_global_alloc,<FAR,PUBLIC,NODATA,NONWIN>
cBegin
        cCall   global_alloc
cEnd

cProc   global_alloc,<NEAR,PUBLIC>

        localW  fAlloc
cBegin
        mov     fAlloc,cx
        mov     cx,ax                             ;Don't allocate if they want 0 bytes
        or      cx,dx
        jz      global_alloc_done
        cmp     dx,1
        jb      ga_not_huge
        ja      ga_is_huge
        or      ax,ax
        jnz     ga_is_huge
ga_not_huge:
        farPtr  pSel,ss,bx
        cCall   SSAllocSeg,<ax,pSel,fAlloc>
        jmp     short ga_just_tried_alloc
ga_is_huge:
        mov     cx,dx                             ;# of segments required
        or      ax,ax   
        jz      @F
        inc     cx
@@:
        farPtr  pSel,ss,bx
        arg     dx                                ;# of full segments
        arg     ax                                ;# of bytes for last segment
        arg     pSel                              ;Return selector here
        arg     cx                                ;Will never grow it
        arg     fAlloc
        cCall   SSAllocHuge

ga_just_tried_alloc:
        xchg    ax,cx

global_alloc_done:
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = global_free
;*
;* DESCRIPTION   = Free global shared memory 
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 Calls:
;*                       SSFreeSeg
;*
;* INPUT         = CX = selector to free
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX = OS/2 error code 
;* RETURN-ERROR  = AX = OS/2 error code  
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   far_global_free,<FAR,PUBLIC,NODATA,NONWIN>
cBegin
        cCall   global_free
cEnd

cProc   global_free,<NEAR,PUBLIC>
cBegin
        cCall   SSFreeSeg,<cx>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<SSFreeSeg returned error>
@@:
endif

cEnd
page
                   
;/***************************************************************************
;*
;* FUNCTION NAME = gain_access_to_selector 
;*
;* DESCRIPTION   = Access to the given selector is gotten.
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 Calls:
;*                       DosGetSeg
;*
;* INPUT         = None
;* OUTPUT        = None
;*
;* RETURN-NORMAL = None
;* RETURN-ERROR  = None
;*
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

cProc   gain_access_to_selector,<FAR,PUBLIC,NONWIN>
        parmW   selTemp
cBegin
        cCall   DosGetSeg,<selTemp>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<A call to DosGetSeg failed>
@@:
endif
cEnd

sEnd Code

sBegin  Bitmap
        assumes cs,Bitmap

;/***************************************************************************
;*
;* FUNCTION NAME = alloc_far_mem
;*
;* DESCRIPTION   = Allocate shared memory from the FarHeap of the given size
;*
;*                 Registers Preserved:
;*                       BX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:
;*                       WinAllocFarMem
;*
;* INPUT         = DS    = display driver's data segment 
;*                 DX:AX = amount of memory needed       
;* OUTPUT        = None
;*
;* RETURN-NORMAL = DX:AX = far pointer to the memory 
;*                 CX <> 0                           
;* RETURN-ERROR  = CX = 0    
;*                 DX:AX = 0 
;**************************************************************************/

        assumes ds,Data
        assumes es,nothing

        BitmapCodeSegRETF   db                     0CBh   ; RETF instruction

cProc   far_alloc_far_mem,<FAR,PUBLIC,NODATA,NONWIN>
cBegin  <nogen>
        push    OFFSET BitmapCodeSegRETF
        errn$   alloc_far_mem
cEnd    <nogen>

cProc   alloc_far_mem,<NEAR,PUBLIC>
cBegin
        mov     cx,ax                             ;Don't allocate if they want 0 bytes
        or      cx,dx
        jz      afh_done

        save    <ax,dx>
        cCall   far_enter_driver_sem

        farPtr  MyHeap,FarHeap.sel,FarHeap.off
        farPtr  MySize,dx,ax
        cCall   WinAllocFarMem,<MyHeap,MySize>
        call    far_leave_driver
        mov     cx,ax
        or      cx,dx                   ;if error DX:AX = CX = 0

afh_done:
cEnd

page

;/***************************************************************************
;*
;* FUNCTION NAME = free_far_mem
;*
;* DESCRIPTION   = Free shared memory back to the FarHeap. 
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 Calls:
;*                       WinFreeFarMem
;*
;* INPUT         = DX:AX = far pointer to the memory block. 
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX <> 0 
;* RETURN-ERROR  = AX = 0  
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

cProc   far_free_far_mem,<FAR,PUBLIC,NODATA,NONWIN>
cBegin  <nogen>
        push    OFFSET BitmapCodeSegRETF
        errn$   free_far_mem
cEnd    <nogen>

cProc   free_far_mem,<NEAR,PUBLIC>
        localD  lpMem
cBegin

        mov     lpMem.hi,dx
        mov     lpMem.lo,ax

        call    far_enter_driver_sem

        farPtr  MyPtr,lpMem.hi,lpMem.lo
        cCall   WinFreeFarMem,<MyPtr>

ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<WinFreeFarMem returned error>
@@:
endif;FIREWALLS

        call    far_leave_driver

cEnd
page

sEnd Bitmap


page

;/***************************************************************************
;*
;* FUNCTION NAME = private_alloc
;*
;* DESCRIPTION   = Allocate global private memory of the given size 
;*
;*                 Registers Preserved:
;*                       BX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,CX,DX,FLAGS
;*                 Calls:
;*                       DosAllocSeg
;*                       DosAllocHuge
;*
;* INPUT         = DX:AX = amount of memory needed            
;*                 SS:BX --> where selector is to be returned 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = CX = 0               
;* RETURN-ERROR  = CX = OS|2 error code 
;*
;**************************************************************************/

sBegin  InitSeg
        assumes cs,InitSeg

        assumes ds,nothing
        assumes es,nothing

        InitCodeSegRETF   db                     0CBh ; RETF instruction

cProc   far_private_alloc,<FAR,PUBLIC,NODATA,NONWIN>
cBegin  <nogen>
        push    OFFSET InitCodeSegRETF
        errn$   private_alloc
cEnd    <nogen>

cProc   private_alloc,<NEAR,PUBLIC,NODATA,NONWIN>
cBegin
        mov     cx,ax                             ;Don't allocate if they want 0 bytes
        or      cx,dx
        jz      private_alloc_done
        cmp     dx,1
        jb      pa_not_huge
        ja      pa_is_huge
        or      ax,ax
        jnz     pa_is_huge
pa_not_huge:
        farPtr  pSel,ss,bx
        cCall   DosAllocSeg,<ax,pSel,SEG_NONSHARED>
        jmp     short pa_just_tried_alloc
pa_is_huge:
        farPtr  pSel,ss,bx
        arg     dx                                ;# of full segments
        arg     ax                                ;# of bytes for last segment
        arg     pSel                              ;Return selector here
        arg     0                                 ;Will never grow it
        arg     SEG_NONSHARED
        cCall   DosAllocHuge

pa_just_tried_alloc:
        xchg    ax,cx

private_alloc_done:
cEnd
page

;/***************************************************************************
;*
;* FUNCTION NAME = private_free
;*
;* DESCRIPTION   = Free global private memory 
;*
;*                 Registers Preserved:
;*                       BX,CX,DX,SI,DI,DS,ES,BP
;*                 Registers Destroyed:
;*                       AX,FLAGS
;*                 Calls:
;*                       DosFreeSeg
;*
;* INPUT         = CX = selector to free 
;* OUTPUT        =
;*
;* RETURN-NORMAL = AX = OS|2 error code 
;* RETURN-ERROR  = AX = OS|2 error code 
;*
;**************************************************************************/


        assumes ds,nothing
        assumes es,nothing

cProc   far_private_free,<FAR,PUBLIC,NODATA,NONWIN>
cBegin  <nogen>
        push    OFFSET InitCodeSegRETF
        errn$   private_free
cEnd    <nogen>

cProc   private_free,<NEAR,PUBLIC,NODATA,NONWIN>
cBegin
        cCall   DosFreeSeg,<cx>
ifdef FIREWALLS
        or      ax,ax
        jz      @F
        rip     text,<DosFreeSeg returned error>
@@:
endif

cEnd

page


MIN_SEG_INC     equ     16*SIZE DDC
MIN_OBJ_SIZE    equ     4
MAX_OBJ_SIZE    equ     SIZE DDC


;/***************************************************************************
;*
;* FUNCTION NAME = init_heap
;*
;* DESCRIPTION   = The local heap is initialized 
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,ES,FLAGS
;*                 Calls:
;*                       WinInitializeHeap
;*
;* INPUT         = DS = DGROUP 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = CX <> 0  
;* RETURN-ERROR  = CX = 0   
;*
;**************************************************************************/
 
        assumes ds,Data
        assumes es,nothing

cProc   init_heap,<NEAR,PUBLIC>
cBegin
        xor     ax,ax
        arg     ds                                ;Segment address of base of heap
        arg     cbHeap                            ;Size of heap in bytes
        arg     MIN_SEG_INC                       ;Min amount to grow heap by
        arg     MIN_OBJ_SIZE                      ;Min and max sizes of heap objects
        arg     MAX_OBJ_SIZE                      ;  with dedicated free lists
        arg     ax                                ;Options
        cCall   WinCreateHeap
        mov     hLocalHeap.hi,dx
        mov     hLocalHeap.lo,ax
        xchg    ax,cx
        or      cx,dx
ifdef FIREWALLS
        jnz     @F
        rip     text,<Heap initialization failed>
@@:
endif
cEnd

;/***************************************************************************
;*
;* FUNCTION NAME = init_far_heap
;*
;* DESCRIPTION   = The far heap is initialized 
;*
;*                 Registers Preserved:
;*                       SI,DI,DS,BP
;*                 Registers Destroyed:
;*                       CX,FLAGS
;*                 Calls:
;*                       WinCreateFarHeap
;*
;* INPUT         = DS = display data segment 
;* OUTPUT        = None
;*
;* RETURN-NORMAL = far pointer to the FarHeap  
;*                 CX <> 0
;* RETURN-ERROR  = CX = 0                      
;*
;**************************************************************************/ 

        assumes ds,Data
        assumes es,nothing

cProc   init_far_heap,<NEAR,PUBLIC>
cBegin

;/*
;**  Create the Far Heap
;*/

        farPtr  lHeapInit,0,DOSPAGESIZE
        farPtr  lGrow,0,DOSPAGESIZE
        cCall   WinCreateFarHeap,<0,lHeapInit,lGrow,MIN_OBJ_SIZE,DOSPAGESIZE,0>
        mov     cx,ax
        or      cx,dx

ifdef FIREWALLS
        jnz     @F
        rip     text,<FarHeap initialization failed>
@@:
endif;FIREWALLS

        mov     FarHeap.sel,dx      ;DX:AX => Far heap
        mov     FarHeap.off,ax

cEnd

sEnd    InitSeg
end
