home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 5 / ctrom5b.zip / ctrom5b / PROGRAM / ASM / ALIB30B / MEMORY1.ASM < prev    next >
Assembly Source File  |  1994-12-01  |  31KB  |  1,141 lines

  1.     PAGE    66,132
  2. ;******************************** MEMORY.ASM *********************************
  3. ;
  4. ; MEM_OPEN     - interrogate memory and setup database
  5. ; MEM_ALLOCATE - allocate a block of memory
  6. ; MEM_PUT      - write to allocated memory area
  7. ; MEM_GET      - read from allocated memory area
  8. ; MEM_RELEASE  - release allocated memory block
  9. ; MEM_CLOSE    - close memory handler
  10. ;
  11. ; Note:  The following calls still need MEM_OPEN & MEM_CLOSE, but
  12. ;     allow the MEM_PUT & MEM_GET calls to be avoided.
  13. ;
  14. ; DOS_MEM_ALLOCATE - returns segment for direct writes to allocated memory
  15. ; DOS_MEM_RELEASE  - releases memory allocated with DOS_MEM_ALLOCATE
  16. ;
  17. ; Note: The memory manager utilizes DOS,XMS, and EMS memory and isolates
  18. ;       the caller from memory minipulation.  All interfaces with memory
  19. ;       are handled through memory manager calls.
  20. ;
  21. ; Note: The mem_open,mem_allocate, and mem_close are required calls if any
  22. ;    part of the memory manager is utilized. For most efficient
  23. ;    memory allocation always let the memory manager decide where to
  24. ;    allocate memory from, and then use only the memory manager calls
  25. ;    to transfer data.  This strategy allows a program to work if any
  26. ;    of the three types of memory is available.
  27. ;
  28. ;    LIMITATIONS - The largest block which can be allocated for use
  29. ;                     is 64k
  30. ;            - The maximum number of allocations active at once
  31. ;              is set to 50.  Contact author to increase/decrease
  32. ;            - The smallest allocation unit is 1 word
  33. ;                   - The maximum amount of memory which can be managed
  34. ;                     is about 32mega bytes
  35. ;
  36. ;----------------------------------------------------------------------------
  37. LIBSEG           segment byte public "LIB"
  38.         assume cs:LIBSEG , ds:nothing
  39.  
  40. ;----------------------------------------------------------------------------
  41. .xlist
  42.     include  mac.inc
  43.     include  common.inc
  44. .list
  45. ;----------------------------------------------------------------------------
  46. ;
  47. mem_pkt struc
  48.  mem_fwd    dw        ?    ;forward memory address ptr. -1=end of chain
  49.  mem_bak    dw        ?    ;backwards memory address ptr. 0=start of chain
  50.  mem_flg    db        ?    ;see below
  51.  mem_blk_sz dd        ?    ; bytes(dos) bytes(xms) bytes(ems)
  52.  mem_loc    dd        ?    ; abs(dos)  index(xms)  index,page(ems)
  53. mem_pkt ends
  54.  
  55. ; mem_flg definitions  80 - pkt in use & memory in use
  56. ;               40 - pkt in use & memory available to be allocated
  57. ;               03 - memory type 1(dos) 2(xms) 3(ems)
  58. ;
  59. mem_pkts    equ    50
  60. pkt_area    label    byte
  61.  db    ((size mem_pkt)*(mem_pkts)) dup (0)    ;all packets reside here
  62. pkt_area_end    label    byte
  63.  
  64. free_srch_ptr    dw    pkt_area    ;circular ptr for free pkt sreach
  65.  
  66. dos_chain    dw    0        ;ptr to dos chain (0=no dos chain)
  67. xms_chain    dw    0        ;ptr to xms chain (0=no xms chain)
  68. ems_chain    dw    0        ;ptr to ems chain (0=no ems chain)
  69.  
  70. dos_initial_seg    dw    0        ;seg of initial dos seg
  71. dos_initial_sz    dw    0        ;paragraphs allocated
  72. ;
  73. ;---------------------------------
  74. ; expanded memory data base
  75. ;---------------------------------
  76.  
  77. ems_handle    dw    0
  78. ems_frame    dw    0        ;seg of ems page, 0=no page
  79. ems_initial_sz    dw    0        ;16k-byte pages avail
  80.  
  81. current_logical_page    dw    -1
  82.  
  83. ;---------------------------------
  84. ; xms extended memory data base
  85. ;---------------------------------
  86.  
  87. xms_handle    dw    0
  88. xms_control    dd    0        ;address of driver entry point
  89. xms_initial_sz    dw    0        ;1k bytes avail.
  90.  
  91.     align    4
  92. write_xms_packet    label    dword
  93.   xms_write_len        dd    0      ;length    of write in bytes
  94.   xms_from_write_handle    dw    0    ;always zero for conventional memory
  95.   xms_from_write_offset    dw    0    ;store buffer offset here
  96.   xms_from_write_segment dw    0    ;store buffer segment here
  97.   xms_to_write_handle    dw    0    ;handle from    xms driver
  98.   xms_to_write_address    dd    0    ;byte address from start of    xms block
  99.  
  100.  
  101.     align    4
  102. read_xms_packet    label    dword
  103.   xms_read_len        dd    0      ;length of read in bytes
  104.   xms_from_read_handle    dw    0    ;from xms driver
  105.   xms_from_read_address    dd    0    ;byte address from start of xms block
  106.   xms_to_read_handle    dw    0    ;always zero
  107.   xms_to_read_offset    dw    0    ;store buffer offset here
  108.   xms_to_read_segment    dw    0    ;store buffer segment here
  109.  
  110. comment 
  111. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  112. MEM_OPEN - interrogate memory and setup database.
  113. ;
  114. ; inputs:  none
  115. ;
  116. ; output:  no carry = success, ax=total 1k blocks allocated
  117. ;        carry = error/warning, if ax=7 DOS memory was not found.
  118. ;                      ax=2 fatal programming error
  119. ;
  120.  
  121. ; processing: 1. determine memory available and setup database
  122. ;           2. allocate all available memory
  123. ;
  124. ; Note: DOS memory is required for many library functions so
  125. ;       it must be available.  See sample programs for method
  126. ;       needed to make DOS memory available.
  127. ;
  128. ;       This function is called once at the start of a program.
  129. ;    The Library_setup function calls mem_open, so it should
  130. ;    not need to be called directly.
  131. ;
  132. ;       The following calls still need MEM_OPEN & MEM_CLOSE, but
  133. ;    allow the MEM_PUT & MEM_GET calls to be avoided.
  134. ;
  135. ;       DOS_MEM_ALLOCATE - returns segment for direct writes to
  136. ;                          allocated memory
  137. ;       DOS_MEM_RELEASE  - releases memory allocated with DOS_MEM_ALLOCATE
  138. ;
  139. ;       The memory manager utilizes DOS,XMS, and EMS memory and isolates
  140. ;       the caller from memory minipulation.  All interfaces with memory
  141. ;       can be handled through memory manager calls.
  142. ;
  143. ;       The mem_open,mem_allocate, and mem_close are required calls if any
  144. ;    part of the memory manager is utilized. For most efficient
  145. ;    memory allocation always let the memory manager decide where to
  146. ;    allocate memory from, and then use only the memory manager calls
  147. ;    to transfer data.  This strategy allows a program to work if any
  148. ;    of the three types of memory is available.
  149. ;
  150. ;    LIMITATIONS - The largest block which can be allocated for use
  151. ;                     is 64k
  152. ;            - The maximum number of allocations active at once
  153. ;              is set to 50.  Contact author to increase/decrease
  154. ;            - The smallest allocation unit is 1 word
  155. ;                   - The maximum amount of memory which can be managed
  156. ;                     is about 32mega bytes
  157. ;
  158. ;      Before doing an exec call to DOS it is necessary to do a mem_close
  159. ;      to make memory available.  Then, do a mem_open upon return.  The
  160. ;      library function SPAWN_DOS is the only function that does an exec
  161. ;      call to DOS.  After the mem_close and mem_open sequence all previous
  162. ;      data is lost.
  163. ;* * * * * * * * * * * * * *
  164. 
  165.     public    mem_open
  166. mem_open    proc    far
  167.     apush    bx,cx,dx,si,di,ds,es
  168.     cld
  169.     mov    ax,cs
  170.     mov    ds,ax
  171.     mov    es,ax
  172.  
  173.     cmp    dos_initial_sz,0
  174.     je    mop_1            ;jmp if first entry
  175.     mov    ax,2
  176.     stc
  177.     jmp    mop_exit        ;jmp if memory already allocated
  178. ;
  179. ; clear the packet area
  180. ;
  181. mop_1:    mov    di,offset pkt_area
  182.     mov    cx,(size mem_pkt)*mem_pkts
  183.     cld
  184.     mov    al,0
  185.     rep    stosb
  186. ;
  187. ; check if any DOS memory is available, and if not return warning
  188. ;
  189.     mov    bx,-1
  190.     mov    ah,48h
  191.     int    21h            ;try to allocate impossible amount
  192. ;
  193. ; we should have the carry set here (error) and -bx- has maximum amount
  194. ; of memory available.
  195. ;
  196.     cmp    bx,0            ;check if any memory is available
  197.     je    mop_error7        ;jmp if no memory
  198. ;
  199. ; When using PS (periscope) it takes all of DOS memory, so we need to
  200. ; debug by using PSKEY and not RUN.COM.
  201. ;    
  202.     mov    dos_initial_sz,bx    
  203.     mov    ah,48h
  204.     int    21h            ;now allocate the maximum amount.
  205.     jnc    mop_dos_setup        ;jmp if DOS memory allocated ok
  206. mop_error7:    
  207.     mov    ax,7            ;get error code
  208.     stc
  209.     jmp    mop_exit
  210. ;
  211. ; build one DOS packet with all available memory
  212. ;
  213. mop_dos_setup:
  214.     mov    dos_initial_seg,ax
  215.     call    get_free_pkt        ;returns free pkt ptr -bx-
  216.     mov    dos_chain,bx
  217.     mov    [bx.mem_fwd],-1        ;end of chain
  218.     mov    [bx.mem_bak],0        ;start of chain
  219.     mov    [bx.mem_flg],41h    ;pkt has memory, type=DOS
  220.     mov    ax,dos_initial_sz
  221.     call    seg_to_abs
  222.     mov    word ptr [bx.mem_blk_sz],ax
  223.     mov    word ptr [bx.mem_blk_sz+2],dx
  224.  
  225.     mov    ax,dos_initial_seg
  226.     call    seg_to_abs
  227.     mov    word ptr [bx.mem_loc],ax    ;store abs loc
  228.     mov    word ptr [bx.mem_loc+2],dx    ; in packet
  229.  
  230. ;----------------------
  231. ; check if any XMS memory is available, and setup database if it is
  232. ;
  233. check_for_xms:
  234.     mov    ax,4300h
  235.     int    2fh
  236.     cmp    al,80h        ;check if driver found
  237.     jne    check_ems    ;jmp if no xms memory present
  238. ;
  239.     mov    ax,4310h
  240.     int    2fh        ;request control address
  241.     mov    word ptr xms_control,bx
  242.     mov    word ptr xms_control+2,es
  243.  
  244. ; request size of largest block in -ax- (k bytes)
  245.  
  246.     mov    ah,8
  247.     call    xms_control    ;returns ax=largest k-blk  dx=total k-blks
  248.     cmp    ax,0
  249.     je    check_ems    ;jmp if no xms available
  250. ;
  251. ; allocate largest xms block
  252. ;
  253. mop_lp:    mov    dx,ax        ;put largest block in -dx-
  254.     mov    xms_initial_sz,ax
  255.     mov    ah,9
  256.     call    xms_control
  257.     cmp    ax,01
  258.     je    mop_2        ;jmp if allocation sucessful
  259. ;
  260. ; xms will not allocated this block size, reduce size and retry
  261. ;    
  262.     mov    ax,xms_initial_sz
  263.     shr    ax,1
  264.     cmp    ax,0
  265.     jne    mop_lp        ;jmp if reduced allocation greater than zero
  266.     mov    ax,2
  267.     stc
  268.     jmp    mop_exit
  269.  
  270. mop_2:    mov    xms_from_read_handle,dx
  271.     mov    xms_to_write_handle,dx
  272.     mov    xms_handle,dx
  273. ;
  274. ; setup the XMS packet with all available memory
  275. ;
  276.     call    get_free_pkt        ;returns free pkt ptr -bx-
  277.     mov    xms_chain,bx
  278.     mov    [bx.mem_fwd],-1        ;end of chain
  279.     mov    [bx.mem_bak],0        ;start of chain
  280.     mov    [bx.mem_flg],42h    ;pkt has memory, type=XMS
  281.  
  282.     mov    ax,xms_initial_sz    ;get size in 1k blocks
  283.     mov    dx,1024            ;size of 1k blk
  284.     mul    dx
  285.     mov    word ptr [bx.mem_blk_sz],ax      ;save size
  286.     mov    word ptr [bx.mem_blk_sz+2],dx    ;save size
  287.  
  288.     mov    word ptr [bx.mem_loc],0        ;store relative loc
  289.     mov    word ptr [bx.mem_loc+2],0    ; in packet
  290.  
  291. ;---------------------
  292. ; check if any EMS memory is available, and setup database if it is
  293. ;
  294. check_ems:
  295.     call    CHECK_FOR_EMS
  296.     jc    mop_exit1        ;jmp if no ems avail
  297.     mov    ems_frame,bx        ;save page frame
  298.     
  299.     mov    ah,42h            ;get avail. page count
  300.     int    67h
  301.     or    ah,ah
  302.     jz    mop_3            ;jmp if no error
  303.     mov    ax,2
  304.     stc
  305.     jmp    mop_exit
  306. ;
  307. ; allocate ems pages, bx=unallocated page count
  308. ;
  309. mop_3:    mov    ems_initial_sz,bx    ;save # 16k pages avail.
  310.     cmp    bx,0
  311.     je    mop_exit1        ;jmp if no ems pages avail.
  312.     mov    ah,43h            ;allocate pages request code
  313.     int    67h
  314.     cmp    ah,0
  315.     je    mop_4            ;jmp if success
  316. ;
  317. ; try to allocate reduced amount
  318. ;
  319.     shr    bx,1
  320.     jmp    mop_3    
  321. ;
  322. ; setup the EMS packet will all available ems memory
  323. ;
  324. mop_4:    mov    ems_handle,dx        ;save ems handle
  325.     call    get_free_pkt        ;returns free pkt ptr -bx-
  326.     mov    ems_chain,bx
  327.     mov    [bx.mem_fwd],-1        ;end of chain
  328.     mov    [bx.mem_bak],0        ;start of chain
  329.     mov    [bx.mem_flg],43h    ;pkt has memory, type=EMS
  330.  
  331.     mov    ax,ems_initial_sz
  332.     mov    dx,1024*16        ;16k page size
  333.     mul    dx
  334.     mov    word ptr [bx.mem_blk_sz],ax      ;save size
  335.     mov    word ptr [bx.mem_blk_sz+2],dx    ;save size
  336.  
  337.     mov    word ptr [bx.mem_loc],0        ;store relative loc
  338.     mov    word ptr [bx.mem_loc+2],0    ; in packet
  339.     
  340. ;
  341. ; compute total amount of memory allocated in 1k blocks
  342. ;
  343. mop_exit1:
  344.     mov    ax,dos_initial_sz
  345.     mov    cx,3
  346.     shr    ax,cl
  347.     push    ax
  348.     mov    ax,ems_initial_sz
  349.     mov    cx,3
  350.     shl    ax,cl
  351.     pop    bx
  352.     add    ax,bx
  353.     add    ax,xms_initial_sz
  354.     clc
  355.  
  356. mop_exit:
  357.     apop    es,ds,di,si,dx,cx,bx
  358.     retf
  359.  
  360. mem_open    endp
  361. comment 
  362. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  363. MEM_ALLOCATE - allocate a block of memory.
  364. ;
  365. ; inputs:     dx,ax=number of bytes to allocate, dx=high word ax=low word
  366. ;             bx=allocation method, 0=normal allocation
  367. ;                                   1=only allocate DOS memory
  368. ;
  369. ; outputs:   no carry  bx=memory mgr handle, use to read/write/release
  370. ;         carry     insufficient memory, or too many allocations active
  371. ;                      or -bx- not set correctly
  372. ;
  373. ; note:   This function is called each time a new block of memory is needed.
  374. ;         If register BX is set to normal allocation, then the MEM_GET and
  375. ;         MEM_PUT calls must be used to access memory.
  376. ;* * * * * * * * * * * * * *
  377. 
  378.     public    mem_allocate
  379. mem_allocate    proc    far
  380.     apush    ax,cx,dx,si,di,ds,es
  381.     mov    cx,cs
  382.     mov    ds,cx
  383.     mov    es,cx
  384.  
  385.     cmp    bx,0
  386.     je    normal_allocation
  387.     cmp    bx,1
  388.     je    dos_allocation
  389.     stc
  390.     jmp    ma_exit                ;jmp if -bx- not set correctly
  391. ;
  392. ; allocate DOS memory
  393. ;
  394. dos_allocation:
  395.     mov    bx,dos_chain
  396.     call    find_memory            ;check if any DOS memory
  397.     jnc    ma_got_pkt            ;jmp if memory found
  398.     jmp    ma_failure            ;jmp if no dos memory
  399.             
  400. normal_allocation:
  401.     mov    bx,ems_chain
  402.     call    find_memory            ;check if any ems memory
  403.     jnc    ma_got_pkt            ; jmp if ems memory found
  404.  
  405.     mov    bx,xms_chain
  406.     call    find_memory            ;check if any xms memory
  407.     jnc    ma_got_pkt            ; jmp if xms memory found
  408.  
  409.     mov    bx,dos_chain
  410.     call    find_memory            ;check if any dos memory
  411.     jc    ma_failure            ; jmp if no dos memory
  412. ;
  413. ; we have a packet with enough memory, check if exact match
  414. ;
  415. ma_got_pkt:
  416.     cmp    dx,word ptr [bx.mem_blk_sz+2]
  417.     jne    ma_extract_mem
  418.     cmp    ax,word ptr [bx.mem_blk_sz]
  419.     je    ma_exit1            ;jmp if exact match
  420. ma_extract_mem:    
  421.     mov    si,bx
  422. ;
  423. ; -si- points to a packet with memory, strip out some for the caller
  424. ; -ax,dx- has amount of memory requested by caller
  425. ;
  426.     call    get_free_pkt            ;returns pkt in -bx-
  427.     jc    ma_failure            ;jmp if out of packets
  428. ;
  429. ; remove memory from the mother packet
  430. ;
  431.     sub    word ptr [si.mem_blk_sz],ax
  432.     sbb    word ptr [si.mem_blk_sz+2],dx
  433. ;
  434.     mov    cl,[si.mem_flg]            ;copy flg data
  435.     mov    [bx.mem_flg],cl
  436.  
  437.     mov    word ptr [bx.mem_blk_sz],ax    ;put size in new pkt
  438.     mov    word ptr [bx.mem_blk_sz+2],dx
  439. ;
  440. ; compute address for new packet
  441. ;   dx,ax=memory allocated  si=mother pkt  bx=new packet
  442. ;
  443. ; Note: we must take the memory from the end of the mother packet, so that
  444. ;    insert_mem_packet never has to insert at front of chain.
  445. ;
  446.         mov     ax,word ptr [si.mem_loc]        ;get mother pkt's location
  447.     mov    dx,word ptr [si.mem_loc+2]
  448.  
  449.         add     ax,word ptr [si.mem_blk_sz]        ;compute end of mother's
  450.     adc    dx,word ptr [si.mem_blk_sz+2]       ;  memory (start of new pkt)
  451.  
  452.         mov     word ptr [bx.mem_loc],ax        ;store new pkt's
  453.     mov    word ptr [bx.mem_loc+2],dx    ;  memory location
  454.  
  455.     call    insert_mem_packet
  456.  
  457. ma_exit1:
  458.     and    [bx.mem_flg],3fh            ;remove flags from pkt
  459.     or    [bx.mem_flg],80h            ;set in-use flag
  460.     clc
  461.     jmp    ma_exit
  462. ma_failure:
  463.     stc    
  464. ma_exit:
  465.     apop    es,ds,di,si,dx,cx,ax
  466.     retf
  467. mem_allocate    endp
  468.  
  469. ;------------------------------
  470. ; find_memory - scan one chain to look for free memory
  471. ;  inputs:  ds:bx - points to first packet on chain
  472. ;           dx,ax - number of bytes to allocate
  473. ;  output:  no carry, bx=packet with memory
  474. ;           carry = insufficient memory
  475. ;
  476. find_memory:
  477.     cmp    bx,0
  478.     je    fm_failure            ;jmp if no chain
  479.          test    [bx.mem_flg],040h        ;check if avail. memory here
  480.     jz    fm_next_pkt            ; jmp if memory in-use
  481.     cmp    dx,word ptr [bx.mem_blk_sz+2]    ;check high word
  482.     jb    fm_got_pkt            ;jmp if sufficient mem in pkt
  483.     ja    fm_next_pkt            ;jmp if insufficient mem in pkt
  484.     cmp    ax,word ptr [bx.mem_blk_sz]    ;check low word
  485.     jbe    fm_got_pkt            ;jmp if memory found
  486. fm_next_pkt:
  487.     mov    bx,[bx.mem_fwd]            ;get next packet
  488.     cmp    bx,-1
  489.     jne    find_memory            ;jmp if more packets to check
  490. fm_failure:    
  491.     stc
  492.     jmp    fm_exit                ;no memory exit
  493. fm_got_pkt:
  494.     clc
  495. fm_exit:
  496.     ret        
  497. ;
  498. comment 
  499. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  500. MEM_PUT - write to allocated memory area.
  501. ;
  502. ; inputs:     bx = memory mgr handle
  503. ;       bp:si = ptr to data
  504. ;             di = put location (index from start of block) 0=start of blk
  505. ;          cx = length of bp:si data in words
  506. ;
  507. ;  output:   no carry = success
  508. ;            carry = error code in -ax- (from EMS/XMS driver)
  509. ;
  510. ; note:  This function is called to transfer data to allocated memory.
  511. ;            
  512. * * * * * * * * * * * * * *
  513. 
  514.     public    mem_put
  515. mem_put proc    far
  516.     apush    ax,bx,cx,dx,si,di,bp,ds,es
  517.     cld
  518.     push    cs
  519.     pop    ds
  520.     mov    al,[bx.mem_flg]
  521.     and    al,3                ;isolate memory type
  522.     cmp    al,3
  523.     je    mp_ems
  524.     cmp    al,2
  525.     je    mp_xms
  526. ;
  527. ; move dos memory
  528. ;
  529.     call    copy_to_dos_mem
  530.     jmp    mp_exit
  531. mp_xms: call    copy_to_xms_mem
  532.     jmp    mp_exit
  533. mp_ems: call    copy_to_ems_mem
  534. mp_exit:
  535.     apop    es,ds,bp,di,si,dx,cx,bx,ax
  536.     retf
  537. mem_put endp
  538.  
  539. comment 
  540. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  541. MEM_GET - read from allocated memory area.
  542. ;
  543. ; inputs:      bx = memory mgr handle
  544. ;        bp:di = location to store data
  545. ;           si = get location (index from start of block)
  546. ;           cx = number of words to read
  547. ;
  548. ; output:  no carry = success
  549. ;       carry    = error code in -ax- (from EMS/XMS driver)
  550. ;
  551. ; processing: data is read from the start of block for -cx- bytes
  552. ;
  553. ; note:  This function is called to transfer data from allocated memory.
  554. ;* * * * * * * * * * * * * *
  555. 
  556.     public    mem_get
  557. mem_get proc    far
  558.     apush    ax,bx,cx,dx,si,di,bp,ds,es
  559.     cld
  560.     push    cs
  561.     pop    ds
  562.     mov    al,[bx.mem_flg]
  563.     and    al,3                ;isolate memory type
  564.     cmp    al,3
  565.     je    mg_ems
  566.     cmp    al,2
  567.     je    mg_xms
  568. ;
  569. ; move dos memory
  570. ;
  571.     call    copy_from_dos_mem
  572.     jmp    mg_exit
  573. mg_xms: call    copy_from_xms_mem
  574.     jmp    mg_exit
  575. mg_ems: call    copy_from_ems_mem
  576. mg_exit:
  577.     apop    es,ds,bp,di,si,dx,cx,bx,ax
  578.     retf
  579. mem_get endp
  580.  
  581. comment 
  582. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  583. MEM_RELEASE  - release allocated memory block.
  584. ;
  585. ; inputs:     bx = memory mgr handle
  586. ; output:     none
  587. ; processing:  1. convert packet into free memory.
  588. ;           2. garbage collect on both sides of chain.
  589. ;
  590. ; note:  This function releases blocks of memory which were allocated
  591. ;     by mem_allocate.
  592. ;* * * * * * * * * * * * * *
  593. 
  594.     public    mem_release
  595. mem_release    proc    far
  596.     apush    ax,bx,cx,dx,si,di,bp,ds,es
  597.     push    cs
  598.     pop    ds
  599.     xor    [bx.mem_flg],0c0h        ;set memory available (4x)
  600.     cmp    [bx.mem_bak],0            ;check if at start of chain
  601.     je    mr_ck_fwd            ;jmp if at top of chain
  602. ;
  603. ; there is a packet preceeding this one, check if we can combine packets
  604. ;
  605.     mov    si,[bx.mem_bak]
  606.     test    [si.mem_flg],80h        ;check if mem available
  607.     jnz    mr_ck_fwd            ; jmp if memory is in-use
  608. ;
  609. ; the previous packet is not in-use, combine it with this pkt
  610. ;
  611.     mov    ax,word ptr [bx.mem_blk_sz]
  612.     mov    dx,word ptr [bx.mem_blk_sz+2]    ;get released blk size
  613.  
  614.     add    word ptr [si.mem_blk_sz],ax
  615.     adc    word ptr [si.mem_blk_sz +2],dx
  616.  
  617.     mov    [bx.mem_flg],0            ;free this pkt
  618.     call    extract_mem_pkt            ;remove pkt from chain
  619.     mov    bx,di                ;move to previous pkt
  620. ;
  621. ; check if we can combine this packet with the forward pkt
  622. ;
  623. mr_ck_fwd:
  624.     cmp    [bx.mem_fwd],-1
  625.     je    mr_exit                ;jmp if at end of chain
  626.     mov    si,[bx.mem_fwd]            ;get forward pkt ptr
  627.  
  628.     test    [si.mem_flg],80h        ;check if forward pkt in-use
  629.     jnz    mr_exit                ;jmp if memory in-use
  630. ;
  631. ; the fwd packet is not in-use, so combine it with mother pkt (bx)
  632. ;
  633.     mov    ax,word ptr [si.mem_blk_sz]
  634.     mov    dx,word ptr [si.mem_blk_sz+2]    ;get released blk size
  635.  
  636.     add    word ptr [bx.mem_blk_sz],ax
  637.     adc    word ptr [bx.mem_blk_sz +2],dx
  638.  
  639.     mov    [si.mem_flg],0            ;free this pkt
  640.     xchg    si,bx
  641.     call    extract_mem_pkt            ;remove pkt from chain
  642.  
  643. mr_exit:
  644.     apop    es,ds,bp,di,si,dx,cx,bx,ax
  645.     retf
  646. mem_release    endp
  647.  
  648. comment 
  649. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  650. MEM_CLOSE - close memory handler.
  651. ;
  652. ; inputs:     none
  653. ; output:     none
  654. ; note:  This function is called just before the program exits
  655. ;     to return all memory back to the SYSTEM.  Normally,
  656. ;     this is accomplished in the LIBRARY_TERMINATE function.
  657. ;* * * * * * * * * * * * * *
  658. 
  659.     public    mem_close
  660. mem_close    proc    far
  661.     apush    ax,bx,cx,dx,si,di,bp,ds,es
  662.     push    cs
  663.     pop    ds
  664.     cmp    dos_initial_seg,0
  665.     je    mc_xms                ;jmp if dos mem not allocated
  666. ;
  667. ; release DOS memory
  668. ;
  669.     mov    es,dos_initial_seg
  670.     mov    ah,49h
  671.     int    21h                ;release DOS memory
  672.     mov    dos_initial_seg,0
  673. ;
  674. ; check if xms memory allocated
  675. ;
  676. mc_xms: mov    dx,xms_handle
  677.     cmp    dx,0
  678.     je    mc_ems                ;jmp if no xms allocated
  679.     mov    ah,0ah
  680.     call    xms_control            ;release xms memory block
  681.     mov    xms_handle,0
  682. ;
  683. ; check if ems memory allocated
  684. ;
  685. mc_ems: mov    dx,ems_handle
  686.     cmp    dx,0
  687.     je    mc_exit                ;jmp if no ems allocated
  688. ;
  689. ; release ems memory block
  690. ;
  691.     mov    ah,45h
  692.     int    67h                ;release ems memory block
  693.     mov    ems_handle,0
  694. mc_exit:
  695.     apop    es,ds,bp,di,si,dx,cx,bx,ax
  696.     retf
  697. mem_close    endp
  698. comment 
  699. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  700. DOS_MEM_ALLOCATE - allocate dos memory for direct writes
  701. ;
  702. ; inputs:  dx,ax - number of bytes to allocate
  703. ; output:   no carry  es = segment of memory allocated
  704. ;           carry     = failure allocating memory
  705. ;
  706. ; note:  This function is used only if the program wants to read and
  707. ;        write memory directly.  Is is faster than MEM_GET and MEM_PUT
  708. ;        but is limited to DOS memory only.           
  709. ;* * * * * * * * * * * * * *
  710. 
  711.     public    dos_mem_allocate
  712. dos_mem_allocate    proc    far
  713.     apush    ax,bx,dx,ds
  714.     push    cs
  715.     pop    ds
  716.     mov    bx,1                ;allocate only DOS memory
  717.     add    ax,15                ;adjust for segment
  718.     adc    dx,0                ;adjust for segment usage
  719.     and    ax,0fff0h            ;mod 16
  720.     call    mem_allocate
  721.     jc    dma_exit
  722.     mov    ax,word ptr cs:[bx.mem_loc]
  723.     mov    dx,word ptr cs:[bx.mem_loc+2]
  724.     test    ax,000fh            ;check if even seg boundry
  725.     jz    dma_make_seg
  726.     or    ax,000fh
  727.     add    ax,1
  728.     adc    dx,0
  729. dma_make_seg:    
  730.     call    abs_to_seg
  731.     mov    es,ax
  732.     clc
  733. dma_exit:
  734.     apop    ds,dx,bx,ax
  735.     retf
  736. dos_mem_allocate    endp
  737. comment 
  738. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  739. DOS_MEM_RELEASE - release memory allocated with DOS_MEM_ALLOCATE
  740. ;
  741. ;  inputs:  es = segment of memory to release
  742. ;  
  743. ;  output:  no carry = success
  744. ;           carry = bad segment
  745. ;* * * * * * * * * * * * * *
  746. 
  747.     public    dos_mem_release
  748. dos_mem_release proc    far
  749.     apush    ax,bx,cx,dx,ds
  750.     push    cs
  751.     pop    ds
  752.     mov    cx,es
  753.     mov    bx,dos_chain
  754. dmr_lp: cmp    bx,0
  755.     je    dmr_failure
  756.     mov    ax,word ptr [bx.mem_loc]
  757.     mov    dx,word ptr [bx.mem_loc+2]
  758.     test    ax,000fh            ;check if even seg boundry
  759.     jz    dmr_make_seg
  760.     or    ax,000fh
  761.     add    ax,1
  762.     adc    dx,0
  763. dmr_make_seg:
  764.     call    abs_to_seg
  765.     cmp    ax,cx
  766.     je    dmr_found_it            ;jmp if we have found the pkt
  767.     mov    bx,[bx.mem_fwd]
  768.     jmp    dmr_lp
  769. ;
  770. ; we have found the packet for this segment, release it
  771. ;
  772. dmr_found_it:
  773.     call    mem_release
  774.     clc
  775.     jmp    dmr_exit
  776. dmr_failure:
  777.     stc
  778. dmr_exit:
  779.     apop    ds,dx,cx,bx,ax
  780.     retf
  781. dos_mem_release endp
  782. ;---------------------------------------------------------------------------
  783. ; memory subroutines
  784. ;---------------------------------------------------------------------------
  785. ; copy_to_dos_mem - copy callers data to memory
  786. ;   inputs:  bp:si = from address
  787. ;        cx = number of words to transfer
  788. ;        di = index into block
  789. ;        bx = DOS memory handle (structure ptr)
  790. ;
  791. copy_to_dos_mem:
  792.     apush    ax,cx,dx,si,di,ds
  793. ;
  794. ; compute memory destination address, use info. in packet for base adr
  795. ;
  796.     mov    ax,word ptr [bx.mem_loc]    ;get block base adr
  797.     mov    dx,word ptr [bx.mem_loc+2]    ;  assumes seg of zero
  798.     add    ax,di                ;add in callers
  799.     adc    dx,0                ;  index
  800. ;
  801. ; convert absolute address in ds,ax into seg:offset
  802. ;
  803.     mov    di,ax
  804.     and    di,000fh            ;isolate offset
  805.     call    abs_to_seg
  806.     mov    es,ax
  807.  
  808.     mov    ds,bp                ; setup -from- segment
  809.     rep    movsw                ;move cx data blocks
  810.     apop    ds,di,si,dx,cx,ax
  811.     ret
  812. ;--------------------------------------------------------------------------
  813. ; copy_to_xms_mem - copy callers data to memory
  814. ;   inputs:  bp:si = from address
  815. ;        cx = number of words to transfer
  816. ;        di = index into segment
  817. ;        bx = current packet ptr
  818. ;   output:   carry set if error
  819. ;
  820. copy_to_xms_mem:
  821.     push    bx
  822.     mov    ax,word ptr [bx.mem_loc]    ;compute abs
  823.     mov    dx,word ptr [bx.mem_loc+2]    ; address to write
  824.     add    ax,di
  825.     adc    dx,0
  826.  
  827.     mov    word ptr [xms_to_write_address],ax
  828.     mov    word ptr [xms_to_write_address+2],dx
  829.  
  830.     shl    cx,1                ;convert words to bytes
  831.     mov    word ptr xms_write_len,cx
  832.  
  833.     mov    xms_from_write_offset,si
  834.     mov    xms_from_write_segment,bp
  835.  
  836.     mov    si,offset write_xms_packet
  837.     mov    ah,0bh
  838.     call    xms_control
  839.     pop    bx
  840.     cmp    ax,1
  841.     jne    xms_failure1
  842.     clc
  843.     ret
  844. xms_failure1:
  845.     stc
  846.     ret
  847.  
  848. ;--------------------------------------------------------------------------
  849. ; copy_to_ems_mem - copy callers data to memory
  850. ;   inputs:  bp:si = from address
  851. ;        cx = number of words to transfer
  852. ;        di = index into segment
  853. ;        bx = current packet ptr
  854. ;   output:     carry set if error
  855. ;
  856. ;
  857. copy_to_ems_mem:
  858.     apush     bx,ds,es
  859.     add    si,word ptr [bx.mem_loc]    ;compute page offset
  860.     mov    bx,word ptr [bx.mem_loc+2]    ;get page
  861.  
  862. ; di = offset into emm page
  863. ; bx = page number
  864. ; bp:si = from address
  865. ; cx = number of bytes to transfer
  866. ;
  867.     cmp    bx,CURRENT_LOGICAL_PAGE    ;check if this sector is in mem.
  868.     jz    ctem_1            ;jump if page in memory
  869.     mov    CURRENT_LOGICAL_PAGE,bx    ;save new logical page indicator
  870.     mov    dx,ems_handle        ;get our handle
  871.     mov    ax,4400h        ;get request code & phys. page
  872.     int    67h            ;get data from eem handler
  873.     or    ah,ah
  874.     jnz    t_err
  875. ;
  876. ; compute the address of sector    returned by emm    handler
  877. ;
  878. ctem_1: MOV    es,ems_frame        ;destination (segment)
  879. ;
  880. ; setup    source address (users buffer)
  881. ;
  882.     mov    ds,bp            ;get -from- segment
  883.     cld
  884.     rep    movsw            ;move block
  885.     clc
  886.     jmp    ctem_exit
  887. t_err:    stc
  888. ctem_exit:
  889.     apop     es,ds,bx
  890.     ret
  891. ;
  892. ;--------------------------------------------------------------------------
  893. ; copy from memory to caller
  894. ;--------------------------------------------------------------------------
  895. ;   inputs:  bp:di = to address
  896. ;        si = index into memory block
  897. ;        cx = number of words to transfer
  898. ;        bx = current packet ptr
  899. ;
  900. copy_from_dos_mem:
  901.     apush     bx,ds,es
  902.     mov    es,bp
  903.     mov    ax,word ptr [bx.mem_loc]
  904.     mov    dx,word ptr [bx.mem_loc+2]
  905.     add    ax,si
  906.     adc    dx,0
  907.     mov    si,ax
  908.     and    si,0fh                ;isolate offset
  909.     call    abs_to_seg
  910.     mov    ds,ax                ;move seg to -ds-
  911.     rep    movsw                ;move data
  912.     apop     es,ds,bx
  913.     ret
  914. ;---------------------------------
  915. ;** **XMS memory -> buffer
  916. ;---------------------------------
  917. ;   inputs:  bp:di = to address
  918. ;        si = index into memory block
  919. ;        cx = number of words to transfer
  920. ;        bx = current packet ptr
  921. ;
  922. copy_from_xms_mem:
  923.     push    bx
  924.     mov    ax,si
  925.     mov    dx,0
  926.     add    ax,word ptr [bx.mem_loc]
  927.     adc    dx,word ptr [bx.mem_loc+2]
  928.  
  929.     mov    word ptr [xms_from_read_address],ax
  930.     mov    word ptr [xms_from_read_address+2],dx
  931.  
  932.     shl    cx,1                ;convert words to bytes
  933.     mov    word ptr xms_read_len,cx
  934.  
  935.     mov    xms_to_read_offset,di    ;save buffer offset
  936.     mov    xms_to_read_segment,bp    ;save buffer segment
  937.  
  938.     mov    si,offset read_xms_packet
  939.     mov    ah,0bh
  940.     call    xms_control
  941.     pop    bx
  942.     cmp    ax,1
  943.     jne    xms_failure2
  944.     clc
  945.     ret
  946. xms_failure2:
  947.     stc
  948.     ret
  949. ;---------------------------------
  950. ;** **expanded memory -> buffer
  951. ;---------------------------------
  952. ;   inputs:  bp:di = to address
  953. ;        si = index into memory block
  954. ;        cx = number of words to transfer
  955. ;        bx = current packet ptr
  956. ;
  957. copy_from_ems_mem:
  958.     apush    bx,ds,es
  959.     add    si,word ptr [bx.mem_loc]    ;compute offset
  960.     mov    bx,word ptr [bx.mem_loc+2]  ;get emm page
  961. ;
  962. ; si = offset into emm page
  963. ; bx = page number
  964.  
  965. ;  inputs bx = emm page
  966. ;  output si = pointer to data
  967. ;
  968.     cmp    bx,CURRENT_LOGICAL_PAGE    ;check if this sector is in mem.
  969.     jz    dfem_1            ;jmp if page already present
  970.     mov    CURRENT_LOGICAL_PAGE,bx    ;save new logical page indicator
  971.     mov    dx,ems_handle        ;get our handle
  972.     mov    ax,4400h        ;get request code & phys. page
  973.     int    67h            ;get    data from eem handler
  974.     or    ah,ah            ;check for errors
  975.     jnz    terr
  976. dfem_1:
  977.     MOV    ds,ems_frame        ;source (segment)
  978.     mov    es,bp
  979.     cld
  980.     rep    movsw            ;move block
  981.     sti
  982.     clc
  983.     jmp    dfem_exit
  984. terr:    stc
  985. dfem_exit:
  986.     apop     es,ds,bx
  987.     ret
  988. ;
  989. comment 
  990. ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(  MEMORY )
  991. CHECK_FOR_EMS:      detects EMS driver
  992. ;
  993. ; inputs:  none
  994. ;
  995. ; output:  if CF = 1, no Expanded Memory manager installed
  996. ;          if CF = 0, AH = EMM error code
  997. ;          if AH = 0, BX = page frame segment address
  998. ;          registers changed  AX,BX           
  999. ;* * * * * * * * * * * * * *
  1000. 
  1001. emm_name  DB      'EMMXXXX0',0
  1002.  
  1003. CHECK_FOR_EMS    proc    near
  1004.     apush    cx,si,di,ds
  1005.     cld
  1006. ;
  1007. ; get the interrupt handler attached to int 67h
  1008. ;
  1009.     mov    ah,35h
  1010.     mov    al,67h
  1011.     int    21h            ;ask DOS for int 67 handler
  1012. ;
  1013. ; setup to scan vector for name of EMM handler (EMMXXXX0)
  1014. ;
  1015.     push    cs
  1016.     pop    ds
  1017.     mov    si,offset emm_name    ;offset of our copy of handler name
  1018.     mov    di,0ah            ;offset of name within handler
  1019.     mov    cx,8            ;length of name string
  1020.     repz    cmpsb
  1021.     jne    no_ems            ;jmp if name not found
  1022. ;
  1023. ; ask EMS driver for the page frame
  1024. ;
  1025.     mov    ah,41h
  1026.     int    67h            ;return the page frame in -bx-
  1027.     or    ah,ah            ;check if error
  1028.     jz    ie_exit            ; jmp if no errors
  1029. no_ems:
  1030.     stc
  1031. ie_exit:
  1032.     apop    ds,di,si,cx
  1033.     ret
  1034. CHECK_FOR_EMS    endp
  1035.  
  1036. ;--------------------------------------------------------------------------
  1037. ; get_free_pkt - returns free packet offset in -bx-
  1038. ;  inputs:  ds points to database
  1039. ;  output:  no carry  -  ds:bx - pointer to free pkt
  1040. ;           carry     -  out of free packets
  1041. ;
  1042. get_free_pkt:
  1043.     push    cx
  1044.     mov    bx,free_srch_ptr        ;search from top
  1045.     mov    cx,mem_pkts            ;number of avail. pkts
  1046. gfp_lp:    cmp    bx,offset pkt_area_end
  1047.     jb    gfp_1
  1048.     mov    bx,offset pkt_area
  1049. gfp_1:    test    [bx.mem_flg],0c0h        ;check if pkt in use
  1050.     jz    gfp_got_pkt
  1051.     add    bx,size mem_pkt
  1052.     loop    gfp_lp
  1053. ;
  1054. ; we have gone around once and no free packets were found. Abort
  1055. ;    
  1056.     stc
  1057.     jmp    gfp_exit
  1058. gfp_got_pkt:
  1059.     mov    free_srch_ptr,bx
  1060.     clc
  1061. gfp_exit:    
  1062.     pop    cx        
  1063.     ret
  1064. ;---------------------------------------------------------------------------
  1065. ; extract_mem_pkt - unchains one packet
  1066. ;  inputs: ds:bx - points at packet
  1067. ;
  1068. extract_mem_pkt:
  1069.     mov    si,[bx.mem_fwd]            ;get fwd
  1070.     mov    di,[bx.mem_bak]            ;get bak
  1071.     mov    [di.mem_fwd],si            ;put new fwd ptr in bak packet
  1072.     cmp    si,-1
  1073.     je    emp_exit            ;exit if extracted pkt at end
  1074.     mov    [si.mem_bak],di            ;put new bak ptr in fwd packet
  1075. emp_exit:
  1076.     ret
  1077. ;---------------------------------------------------------------------------
  1078. ; insert_packet - insert packet in chain
  1079. ;  inputs: ds:bx - points to free packet (unchaned)
  1080. ;       ds:si - mother packet to insert after (mother packet)
  1081. ;
  1082. ; processing: Memory is always allocated from the end of a mother packet
  1083. ;          so this new packet is inserted after a mother packet.
  1084. ;
  1085. insert_mem_packet:
  1086.  
  1087. ; bx=new pkt,  si=insert after pkt
  1088. ;
  1089. imp_3:    mov    di,[si.mem_fwd]            ;get fwd packet
  1090. ;
  1091. ; fill in the new packet
  1092. ;
  1093.         mov     [bx.mem_fwd],di             ;new fwd (old mother's fwd)
  1094.     mov    [bx.mem_bak],si            ;new bak (mother)
  1095. ;
  1096. ; adjust chain of packets on both sides of new packet
  1097. ;
  1098.     mov    [si.mem_fwd],bx            ;point mother -> new
  1099.     cmp    di,-1                ;check if forward pkt exists
  1100.     je    imp_exit
  1101.     mov    [di.mem_bak],bx            ;point forward pkt mem_bak->new
  1102. imp_exit:
  1103.     ret
  1104. ;---------------------------------------------------------------------------
  1105. ; abs_to_seg - convert absolute adr to segment
  1106. ;  inputs:  dx,ax = absolute address
  1107. ;  output:  ax = segment
  1108. ;
  1109. abs_to_seg:
  1110.     push    cx
  1111.     mov    cx,4
  1112.     and    ax,0fff0h        ;remove non seg bits
  1113. ats_lp: shr    dx,1
  1114.     rcr    ax,1
  1115.     loop    ats_lp
  1116.     pop    cx
  1117.     ret
  1118.  
  1119. ;---------------------------------------------------------------------------
  1120. ; seg_to_abs - convert seg to absolute address
  1121. ;  inputs: ax=segment
  1122. ;  output: dx,ax = absolute addrss
  1123. ;
  1124. seg_to_abs:
  1125.     push    cx
  1126.     mov    cx,4
  1127.     sub    dx,dx
  1128. sta_lp: shl    ax,1
  1129.     rcl    dx,1
  1130.     loop    sta_lp
  1131.     pop    cx
  1132.     ret
  1133.  
  1134.  
  1135. LIBSEG    ENDS
  1136.     end
  1137.