home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / caway349.zip / SOURCE / ALL / MEMORY.ASM < prev    next >
Assembly Source File  |  1996-06-12  |  51KB  |  2,530 lines

  1. ;-------------------------------------------------------------------------------
  2. ;
  3. ;Get memory using RAW/VCPI.
  4. ;
  5. ;On Entry:-
  6. ;
  7. ;BX:CX    - Size of block.
  8. ;
  9. ;On Exit:-
  10. ;
  11. ;Carry on error else,
  12. ;
  13. ;SI:DI    - Handle.
  14. ;BX:CX    - Logical address of block.
  15. ;
  16. RAWGetMemory    proc    near
  17.      call    RAWCopyCheck
  18.     ;
  19.     pushm    eax,edx,ebp,ds,es
  20.     mov    ax,KernalDS        ;make data addresable.
  21.     mov    ds,ax
  22.     assume ds:_cwRaw
  23.  
  24.     push    ebx
  25.     push    ecx
  26.     push    edx
  27.     xor    ebx,ebx
  28.     mov    bx,ss
  29.     mov    ecx,esp
  30.     pushf
  31.     cli
  32.     mov    edx,d[RawStackPos]
  33.     sub    d[RawStackPos],RawStackDif
  34.     popf
  35.     mov    ax,KernalSS
  36.     mov    ss,ax
  37.     mov    esp,edx
  38.     add    ecx,4+4+4
  39.     pushm    ebx,ecx
  40.     sub    ecx,4+4+4
  41.     push    es
  42.     mov    es,bx
  43.     mov    edx,es:[ecx]
  44.     mov    ebx,es:[ecx+4+4]
  45.     mov    ecx,es:[ecx+4]
  46.     pop    es
  47.  
  48.     mov    ax,KernalZero
  49.     mov    es,ax
  50.     shl    ebx,16        ;get block size as 32-bit.
  51.     mov    bx,cx
  52.     add    ebx,4095        ;round up to next 4k.
  53.     shr    ebx,12
  54.     or    ebx,ebx
  55.     jz    @@error
  56. @@start:    mov    edi,LinearBase    ;Get starting point.
  57.     mov    ecx,LinearLimit
  58.     sub    ecx,edi        ;Get memory present.
  59.     shr    ecx,12        ;Get pages.
  60.     shr    edi,12        ;Get page number.
  61.     shl    edi,2        ;dword per entry.
  62.     add    edi,1024*4096*1022    ;point to page details.
  63.     ;
  64.     ;Look for a big enough block of free memory.
  65.     ;
  66.     xor    eax,eax        ;value to look for.
  67.     cld
  68.  
  69.     ;
  70.     ;EAX    - zero, what we're looking for.
  71.     ;ECX    - entries to check.
  72.     ;EDI    - address of entries to check.
  73.     ;
  74.     ;EBX    - number of entries we want.
  75.     ;
  76.  
  77. @@l0:    repne    scasd
  78.  
  79.     ;
  80.     ;Nothing found means extend end of memory map.
  81.     ;
  82.     jnz    @@ExtendNew
  83.  
  84.     ;
  85.     ;Point everything back to the matching value.
  86.     ;
  87.     sub    edi,4
  88.     inc    ecx
  89.  
  90.     ;
  91.     ;Save current position as start of last free block incase
  92.     ;this block extends to the end of memory.
  93.     ;
  94.     mov    esi,edi        ;save last position.
  95.  
  96.     ;
  97.     ;If we only wanted one page then we're done, this is it!
  98.     ;
  99.     cmp    ebx,1
  100.     jz    @@l2        ;Speed up 4K allocations.
  101.  
  102.     ;
  103.     ;Set the number of pages to scan. This should be the number of
  104.     ;pages we want but has to be reduced to the number of pages
  105.     ;actually available when the request would go off the end of
  106.     ;memory.
  107.     ;
  108.     mov    edx,ebx
  109.     cmp    ecx,ebx        ;Enough space to check?
  110.     jnc    @@l1
  111.     mov    edx,ecx
  112.  
  113.     ;
  114.     ;Scan specified number of entries to see if their all free.
  115.     ;
  116. @@l1:    pushm    ecx,edi
  117.     mov    ecx,edx
  118.     repe    scasd        ;Scan for free pages.
  119.     popm    ecx,edi
  120.     jnz    @@l3        ;not enough free entries.
  121.  
  122.     ;
  123.     ;All the entries were free, now check if we were truncating the
  124.     ;length to stop us running off the end of memory.
  125.     ;
  126.     cmp    edx,ebx        ;Truncated length?
  127.     jnz    @@ExtendEnd
  128.     jmp    @@l2
  129.  
  130.     ;
  131.     ;One way or another we didn't find the number of entries we were
  132.     ;after so restart the search.
  133.     ;
  134. @@l3:    add    edi,4
  135.     dec    ecx
  136.     jmp    @@l0
  137.  
  138.     ;
  139.     ;We've found what we wanted without any extra messing around so
  140.     ;hand this over to the marker.
  141.     ;
  142. @@l2:    sub    esi,1024*4096*1022    ;point to page details.
  143.     shr    esi,2
  144.     jmp    @@MarkMemRet
  145.  
  146.  
  147.     ;
  148.     ;Last block is free so use it as the basis for extension.
  149.     ;
  150. @@ExtendEnd:    mov    edi,ecx        ;remaining entries.
  151.     sub    esi,(1024*4096*1022)
  152.     shr    esi,2        ;Get start page number.
  153.     mov    ecx,ebx        ;Total pages needed.
  154.     sub    ecx,edi        ;Pages found so far.
  155.     jmp    @@Extend
  156.     ;
  157. @@ExtendNew:    ;Last block not free so new block will start at LinearLimit.
  158.     ;
  159.     mov    ecx,ebx        ;Set pages needed.
  160.     mov    esi,LinearLimit    ;New start address.
  161.     shr    esi,12
  162.     ;
  163. @@Extend:    ;Memory map needs extending so get on with it.
  164.     ;
  165.     call    ExtendLinearMemory    ;Try and extend memory map.
  166.     jnc    @@MarkMemRet        ;Mark the block as used.
  167.     ;
  168.     ;Not enough memory so report failure.
  169.     ;
  170.     stc
  171.     jmp    @@exit
  172.     ;
  173. @@MarkMemRet:    ;Got the memory so mark it in use.
  174.     ;
  175.     sub    FreePages,ebx    ;reduce free page count.
  176.     add    medAllocPages,ebx
  177.     ;
  178.     mov    ecx,ebx        ;Get number of pages again.
  179.     mov    edx,esi
  180.     mov    edi,esi        ;Get base page again.
  181.     shl    edi,2
  182.     add    edi,1024*4096*1022
  183.     mov    eax,MEM_END
  184.     rep    stosd
  185.     mov    es:d[(1024*4096*1022)+edx*4],MEM_START
  186.     ;
  187.     ;Now return details to caller.
  188.     ;
  189.     shl    esi,12        ;Convert back to a real address.
  190.     mov    di,si
  191.     shr    esi,16
  192.     mov    cx,di
  193.     mov    bx,si
  194.     clc
  195.     jmp    @@exit
  196.     ;
  197. @@error:    stc
  198.     ;
  199. @@exit:
  200.  
  201.     lss    esp,f[esp]
  202.     pushf
  203.     add    d[RawStackPos],RawStackDif
  204.     popf
  205.  
  206.     popm    eax,edx,ebp,ds,es
  207.     ret
  208.     assume ds:_cwDPMIEMU
  209. RAWGetMemory    endp
  210.  
  211.  
  212. ;-------------------------------------------------------------------------------
  213. ;
  214. ;Re-size a block of memory.
  215. ;
  216. ;On Entry:-
  217. ;
  218. ;SI:DI    - Handle.
  219. ;BX:CX    - New block size.
  220. ;
  221. ;On Exit:-
  222. ;
  223. ;SI:DI    - New handle.
  224. ;BX:CX    - New address.
  225. ;
  226. RAWResMemory    proc    near
  227.     call    RAWCopyCheck
  228.     ;
  229.     pushm    eax,edx,ebp,ds,es
  230.     mov    ax,KernalDS
  231.     mov    ds,ax
  232.     assume ds:_cwRaw
  233.  
  234.     push    ebx
  235.     push    ecx
  236.     push    edx
  237.     xor    ebx,ebx
  238.     mov    bx,ss
  239.     mov    ecx,esp
  240.     pushf
  241.     cli
  242.     mov    edx,d[RawStackPos]
  243.     sub    d[RawStackPos],RawStackDif
  244.     popf
  245.     mov    ax,KernalSS
  246.     mov    ss,ax
  247.     mov    esp,edx
  248.     add    ecx,4+4+4
  249.     pushm    ebx,ecx
  250.     sub    ecx,4+4+4
  251.     push    es
  252.     mov    es,bx
  253.     mov    edx,es:[ecx]
  254.     mov    ebx,es:[ecx+4+4]
  255.     mov    ecx,es:[ecx+4]
  256.     pop    es
  257.  
  258.     mov    ax,KernalZero
  259.     mov    es,ax
  260.     shl    esi,16
  261.     mov    si,di        ;Get real address.
  262.     shl    ecx,16
  263.     mov    cx,bx
  264.     ror    ecx,16
  265.     add    ecx,4095
  266.     shr    ecx,12        ;Get new block size.
  267.     or    ecx,ecx
  268.     jz    @@error
  269.     ;
  270.     ;Check for a valid address.
  271.     ;
  272.     test    esi,4095        ;all memory on page boundaries.
  273.     jnz    @@error
  274.     cmp    esi,LinearBase
  275.     jc    @@error
  276.     cmp    esi,LinearLimit
  277.     jnc    @@error
  278.     shr    esi,12        ;Get page number.
  279.     mov    eax,es:d[1024*4096*1022+esi*4]
  280.     and    eax,MEM_MASK
  281.     cmp    eax,MEM_START
  282.     jnz    @@error
  283.     ;
  284.     ;Work out the blocks current size.
  285.     ;
  286.     push    ecx
  287.     mov    ebp,1
  288.     mov    edx,esi
  289.     inc    edx
  290.     mov    ecx,LinearLimit
  291.     shr    ecx,12
  292.     sub    ecx,edx
  293.     jz    @@l1
  294. @@l0:    mov    eax,es:d[(1024*4096*1022)+edx*4]
  295.     and    eax,MEM_MASK
  296.     cmp    eax,MEM_END
  297.     jnz    @@l1
  298.     inc    ebp
  299.     inc    edx
  300.     dec    ecx
  301.     jnz    @@l0
  302.     ;
  303. @@l1:    ;Shrinking or expanding?
  304.     ;
  305.     pop    ecx
  306.     cmp    ecx,ebp
  307.     jz    @@RetNewAddr
  308.     jnc    @@Bigger
  309.     ;
  310. @@Smaller:    ;Shrinking the block so get on with it.
  311.     ;
  312.     ;ECX - New size in pages.
  313.     ;EBP - Current size in pages.
  314.     ;ESI - Current start page.
  315.     ;
  316.     mov    edx,esi
  317.     add    edx,ecx        ;move to new block end.
  318.     sub    ebp,ecx        ;get number of pages to lose.
  319.     mov    ecx,ebp
  320.     ;
  321.     add    FreePages,ebp    ;update number of free pages.
  322.     sub    medAllocPages,ebp
  323.     ;
  324. @@s0:    and    es:d[(1024*4096*1022)+edx*4],not MEM_MASK
  325.     or    es:d[(1024*4096*1022)+edx*4],MEM_FREE
  326.     and    es:d[(1024*4096*1023)+edx*4],not (1 shl 6)
  327.     inc    edx
  328.     dec    ecx
  329.     jnz    @@s0
  330.     call    EMUCR3Flush
  331.     jmp    @@RetNewAddr
  332.     ;
  333. @@Bigger:    ;Want to expand the block so get on with it.
  334.     ;
  335.     ;ECX - New size in pages.
  336.     ;EBP - Current size in pages.
  337.     ;ESI - Current start page.
  338.     ;
  339. @@b0:    mov    edx,esi
  340.     add    edx,ebp        ;move to end of this block.
  341.     mov    ebx,LinearLimit
  342.     shr    ebx,12
  343.     sub    ebx,edx        ;get pages to end of memory.
  344.     or    ebx,ebx
  345.     jz    @@Extend
  346.     ;
  347.     ;See if the next block is free.
  348.     ;
  349.     mov    eax,es:d[(1024*4096*1022)+edx*4]
  350.     and    eax,MEM_MASK
  351.     cmp    eax,MEM_FREE
  352.     jnz    @@NewBlock        ;no hope so get a new block.
  353.     ;
  354.     ;Check how big this next block is.
  355.     ;
  356.     mov    edi,ebp        ;use current size as basis.
  357. @@b1:    mov    eax,es:d[(1024*4096*1022)+edx*4]
  358.     and    eax,MEM_MASK
  359.     cmp    eax,MEM_FREE
  360.     jnz    @@NewBlock        ;No hope so get a new block.
  361.     inc    edi
  362.     cmp    edi,ecx        ;Got enough yet?
  363.     jz    @@MarkAndRet
  364.     inc    edx
  365.     dec    ebx
  366.     jnz    @@b1        ;keep trying.
  367.     ;
  368.     ;Reached the end of the memory map so try extending it.
  369.     ;
  370.     pushad
  371.     sub    ecx,edi        ;pages still needed.
  372.     call    ExtendLinearMemory
  373.     popad
  374.     jc    @@error
  375.     jmp    @@MarkAndRet
  376.     ;
  377. @@Extend:    ;Need to extend the memory map to provide a block of free memory
  378.     ;after the current block.
  379.     ;
  380.     pushad
  381.     sub    ecx,ebp        ;pages needed.
  382.     call    ExtendLinearMemory
  383.     popad
  384.     jc    @@error
  385.     ;
  386. @@MarkAndRet:    ;Mark the new memory as in use and exit.
  387.     ;
  388.     ;ECX - New size in pages.
  389.     ;EBP - Current size in pages.
  390.     ;ESI - Current start page.
  391.     ;
  392.     mov    edx,esi
  393.     add    edx,ebp        ;move to start of new memory.
  394.     sub    ecx,ebp        ;pages to mark.
  395.     ;
  396.     sub    FreePages,ecx    ;update number of free pages.
  397.     add    medAllocPages,ecx
  398.     ;
  399. @@mr0:    and    es:d[(1024*4096*1022)+edx*4],not MEM_MASK
  400.     or    es:d[(1024*4096*1022)+edx*4],MEM_END
  401.     inc    edx
  402.     dec    ecx
  403.     jnz    @@mr0
  404.     jmp    @@RetNewAddr
  405.     ;
  406. @@NewBlock:    ;Nothing for it but to try and allocate a new block of memory.
  407.     ;
  408.     pushm    ecx,ebp,esi
  409.     shl    ecx,12
  410.     mov    ebx,ecx
  411.     shr    ebx,16
  412.     call    RawGetMemory
  413.     pushf
  414.     shl    ebx,16
  415.     mov    bx,cx
  416.     popf
  417.     popm    ecx,ebp,esi
  418.     jc    @@error
  419.     ;
  420.     ;Copy current block to new block.
  421.     ;
  422.     pushad
  423.     mov    ecx,ebp
  424.     shl    ecx,12
  425.     shl    esi,12
  426.     mov    edi,ebx
  427.     pushm    ds,es
  428.     pop    ds
  429.     shr    ecx,2
  430.     rep    movsd
  431.     pop    ds
  432.     popad
  433.     ;
  434.     ;Release current block.
  435.     ;
  436.     pushad
  437.     shl    esi,12
  438.     mov    di,si
  439.     shr    esi,16
  440.     call    RawRelMemory
  441.     popad
  442.     ;
  443.     ;Use new block in place of origional.
  444.     ;
  445.     mov    esi,ebx
  446.     shr    esi,12
  447.     ;
  448. @@RetNewAddr:    ;Return possibly new address/handle to caller.
  449.     ;
  450.     shl    esi,12        ;Get a real address again and
  451.     mov    di,si        ;use it as both the memory
  452.     mov    cx,si        ;address to return and the handle.
  453.     shr    esi,16
  454.     mov    bx,si
  455.     clc
  456.     jmp    @@exit
  457.     ;
  458. @@error:    stc
  459. @@exit:
  460.  
  461.     lss    esp,f[esp]
  462.     pushf
  463.     add    d[RawStackPos],RawStackDif
  464.     popf
  465.  
  466.     popm    eax,edx,ebp,ds,es
  467.     ret
  468.     assume ds:_cwDPMIEMU
  469. RAWResMemory    endp
  470.  
  471.  
  472. ;-------------------------------------------------------------------------------
  473. ;
  474. ;Release block of memory using RAW/VCPI.
  475. ;
  476. ;On Entry:-
  477. ;
  478. ;SI:DI    - handle (Base linear address).
  479. ;
  480. RAWRelMemory    proc    near
  481.     call    RAWCopyCheck
  482.     ;
  483.     pushad
  484.     pushm    ds,es
  485.     ;
  486.     shl    esi,16        ;Get block base address.
  487.     mov    si,di
  488.     mov    ax,KernalDS        ;make data addresable.
  489.     mov    ds,ax
  490.     assume ds:_cwRaw
  491.  
  492.     push    ebx
  493.     push    ecx
  494.     push    edx
  495.     xor    ebx,ebx
  496.     mov    bx,ss
  497.     mov    ecx,esp
  498.     pushf
  499.     cli
  500.     mov    edx,d[RawStackPos]
  501.     sub    d[RawStackPos],RawStackDif
  502.     popf
  503.     mov    ax,KernalSS
  504.     mov    ss,ax
  505.     mov    esp,edx
  506.     add    ecx,4+4+4
  507.     pushm    ebx,ecx
  508.     sub    ecx,4+4+4
  509.     push    es
  510.     mov    es,bx
  511.     mov    edx,es:[ecx]
  512.     mov    ebx,es:[ecx+4+4]
  513.     mov    ecx,es:[ecx+4]
  514.     pop    es
  515.  
  516.     mov    ax,KernalZero
  517.     mov    es,ax
  518.     ;
  519.     ;Check for a legal address.
  520.     ;
  521.     test    esi,4095
  522.     jnz    @@error
  523.     cmp    esi,LinearBase    ;inside logical memory map?
  524.     jc    @@error
  525.     cmp    esi,LinearLimit
  526.     jnc    @@error
  527.     shr    esi,12        ;Get page number.
  528.     mov    eax,es:d[1024*4096*1022+esi*4]
  529.     and    eax,MEM_MASK
  530.     cmp    eax,MEM_START
  531.     jnz    @@error
  532.     ;
  533.     ;Mark all this blocks pages as free.
  534.     ;
  535.     inc    FreePages
  536.     dec    medAllocPages
  537.     ;
  538.     and    es:d[1024*4096*1022+esi*4],not MEM_MASK
  539.     or    es:d[1024*4096*1022+esi*4],MEM_FREE
  540.     and    es:d[1024*4096*1023+esi*4],not (1 shl 6)
  541.     inc    esi
  542.     mov    ecx,LinearLimit
  543.     shr    ecx,12
  544.     sub    ecx,esi        ;Get pages remaining.
  545.     jz    @@1
  546. @@0:    mov    eax,es:d[1024*4096*1022+esi*4]
  547.     and    eax,MEM_MASK
  548.     cmp    eax,MEM_END
  549.     jnz    @@1
  550.     inc    FreePages
  551.     dec    medAllocPages
  552.     and    es:d[1024*4096*1022+esi*4],not MEM_MASK
  553.     or    es:d[1024*4096*1022+esi*4],MEM_FREE
  554.     and    es:d[1024*4096*1023+esi*4],not (1 shl 6)
  555.     inc    esi
  556.     dec    ecx
  557.     jnz    @@0
  558.     ;
  559. @@1:    call    EMUCR3Flush
  560.     ;
  561.     clc
  562.     jmp    @@exit
  563.     ;
  564. @@error:    stc
  565. @@exit:
  566.  
  567.     lss    esp,f[esp]
  568.     pushf
  569.     add    d[RawStackPos],RawStackDif
  570.     popf
  571.  
  572.     popm    ds,es
  573.     popad
  574.     ret
  575.     assume ds:_cwDPMIEMU
  576. RAWRelMemory    endp
  577.  
  578.  
  579. ;-------------------------------------------------------------------------------
  580. ;
  581. ;Reset dirty bit for specified memory.
  582. ;
  583. ;On Entry:
  584. ;
  585. ;BX:CX    Starting linear address of pages to discard
  586. ;SI:DI    Number of bytes to discard
  587. ;
  588. ;On Exit:
  589. ;
  590. ;Carry clear, all other registers preserved.
  591. ;
  592. ;-------------------------------------------------------------------------------
  593. RawDiscardPages proc    near
  594.     pushm    ds,es
  595.     pushad
  596.     mov    ax,KernalDS
  597.     mov    ds,ax
  598.     assume ds:_cwRaw
  599.     mov    ax,KernalZero
  600.     mov    es,ax
  601. ;
  602. ;Get base address.
  603. ;
  604.     shl    ebx,16
  605.     mov    bx,cx
  606. ;
  607. ;Get length.
  608. ;
  609.     shl    esi,16
  610.     mov    si,di
  611. ;
  612. ;Round start up a page.
  613. ;
  614.     mov    eax,ebx
  615.     add    ebx,4095
  616.     and    ebx,not 4095
  617.     sub    eax,ebx
  618.     neg    eax
  619.     cmp    eax,esi
  620.     jnc    @@8
  621.     sub    esi,eax
  622. ;
  623. ;Round length down a page.
  624. ;
  625.     and    esi,not 4095
  626.     or    esi,esi
  627.     jz    @@8
  628. ;
  629. ;Get page values.
  630. ;
  631.     mov    edx,ebx
  632.     shr    ebx,12
  633.     shr    esi,12
  634.     mov    ecx,esi
  635. ;
  636. ;Modify all page tables.
  637. ;
  638.     mov    esi,4096*1024*1023    ;base of page alias memory.
  639. @@0:    cmp    edx,LinearBase
  640.     jc    @@1
  641.     cmp    edx,LinearLimit
  642.     jnc    @@2
  643.     and    es:d[esi+ebx*4],not ((1 shl 6)+(1 shl 11)) ;clear dirty & disk bits.
  644. @@1:    add    edx,4096
  645.     inc    ebx
  646.     dec    ecx
  647.     jnz    @@0
  648. ;
  649. @@2:    call    EMUCR3Flush        ;update page cache.
  650. ;
  651. @@8:    clc
  652.     popad
  653.     assume ds:_cwDPMIEMU
  654.     popm    ds,es
  655.     ret
  656. RawDiscardPages endp
  657.  
  658.  
  659. ;-------------------------------------------------------------------------------
  660. ;
  661. ;Map physical memory into address space and return linear access address.
  662. ;
  663. ;BX:CX    Physical address of memory
  664. ;SI:DI    Size of region to map in bytes
  665. ;
  666. ;Returns
  667. ;
  668. ;Carry set on error else,
  669. ;
  670. ;BX:CX    Linear address that can be used to access the physical memory.
  671. ;
  672. RawMapPhys2Lin    proc    near
  673.     pushm    ds,es
  674.     pushm    eax,edx,esi,edi,ebp
  675.     mov    ax,KernalDS
  676.     mov    ds,ax
  677.     assume ds:_cwRaw
  678.     mov    ax,KernalZero
  679.     mov    es,ax
  680. ;
  681. ;Get physical address as 32-bit & check for none-page boundary.
  682. ;
  683.     shl    ebx,16
  684.     mov    bx,cx
  685.     test    ebx,4095
  686.     jnz    @@9
  687. ;
  688. ;Get length as number of pages.
  689. ;
  690.     shl    esi,16
  691.     mov    si,di
  692.     add    esi,4095
  693.     shr    esi,12
  694.     test    esi,esi
  695.     jz    @@9
  696.  
  697. ; MED 06/13/96, remove 4M restriction
  698. ;; MED 04/18/96, don't allow more than a 4M mapping (not supported by CW)
  699. ;    cmp    esi,400h
  700. ;    ja    @@9
  701.  
  702. ;
  703. ;Deal with addresses below 1 Meg.
  704. ;
  705.     mov    edi,ebx
  706.     mov    eax,esi
  707.     shl    eax,12
  708.     add    eax,edi
  709.     dec    eax
  710.     cmp    eax,100000h+10000h
  711.     jc    @@8
  712. ;
  713. ;Find first un-used physical mapping space.
  714. ;
  715.     mov    ebp,PageDirLinear
  716.     mov    eax,1021
  717. @@0:
  718.  
  719. ; MED 04/18/96
  720.     mov    ecx,es:[ebp+eax*4]
  721.     and    ecx,(NOT 4095)    ; get linear address
  722.     cmp    ecx,ebx            ; see if matches desired linear address
  723.     jne    med2            ; no, continue as before
  724.     mov    edi,eax
  725.     shl    edi,22            ; convert index to 4M space
  726.     jmp    @@8
  727.  
  728. med2:
  729.     cmp    es:d[ebp+eax*4],0
  730.     jz    @@1
  731.  
  732. ;    dec    eax
  733.     sub    eax,1
  734.     jc    @@9
  735.  
  736.     jmp    @@0
  737. ;
  738. ;Work out how many page tables we need and set first tables index.
  739. ;
  740. @@1:    mov    ecx,esi
  741.     shr    ecx,10
  742.     sub    eax,ecx
  743.     inc    ecx
  744. ;
  745. ;Make sure we can get enough memory for physical page tables.
  746. ;
  747.     call    PhysicalGetPages
  748.     add    edx,NoneLockedPages
  749.     cmp    edx,ecx
  750.     jc    @@9
  751. ;
  752. ;Put all the page tables into place.
  753. ;
  754.     lea    edi,[ebp+eax*4]
  755.     push    edi
  756.     mov    ebp,ecx
  757. @@2:    call    PhysicalGetPage
  758.     jnc    @@3
  759.     call    UnMapPhysical
  760.     jc    @@10
  761. @@3:    and    ecx,1        ;put user bits in useful place.
  762.     shl    ecx,10
  763.     and    edx,0FFFFFFFFh-4095    ;lose user bits.
  764.     or    edx,111b        ;present+user+write.
  765.     or    edx,ecx        ;set use flags.
  766.     mov    es:d[edi],edx    ;store this tables address.
  767.     push    edi
  768.     sub    edi,PageDIRLinear
  769.     add    edi,PageAliasLinear    ;get alias table address.
  770.     mov    es:d[edi],edx    ;setup in alias table as well.
  771.     pop    edi
  772.     ;
  773.     ;Clear this page to 0.
  774.     ;
  775.     pushm    ecx,edi
  776.     sub    edi,PageDIRLinear
  777.     shl    edi,10
  778.     add    edi,1024*4096*1023    ;base of page alias's.
  779.     mov    ecx,4096/4
  780.     xor    eax,eax
  781.     cld
  782.     rep    stosd
  783.     popm    ecx,edi
  784.     ;
  785.     add    edi,4
  786.     dec    ebp
  787.     jnz    @@2
  788.     pop    edi
  789. ;
  790. ;Now map specified physical address range into place.
  791. ;
  792.     sub    edi,PageDIRLinear
  793.     shl    edi,10        ;start of first page table
  794.     push    edi
  795.     add    edi,1024*4096*1023
  796.     or    ebx,111b
  797. @@4:    mov    es:[edi],ebx
  798.     add    edi,4
  799.     add    ebx,4096
  800.     dec    esi
  801.     jnz    @@4
  802.     pop    edi
  803. ;
  804. ;Return linear address to caller.
  805. ;
  806.     shl    edi,12-2
  807. @@8:    xor    ecx,ecx
  808.     xor    ebx,ebx
  809.     mov    cx,di
  810.     shr    edi,16
  811.     mov    bx,di
  812.     clc
  813.     jmp    @@11
  814. ;
  815. @@10:    pop    edi
  816. @@9:    stc
  817. @@11:    popm    eax,edx,esi,edi,ebp
  818.     assume ds:_cwDPMIEMU
  819.     popm    ds,es
  820.     ret
  821. RawMapPhys2Lin    endp
  822.  
  823.  
  824. ;-------------------------------------------------------------------------------
  825. ;
  826. ;Un-Do a physical to linear address mapping.
  827. ;
  828. RawUnMapPhys2Lin proc near
  829.     clc
  830.     ret
  831. RawUnMapPhys2Lin endp
  832.  
  833.  
  834. ;-------------------------------------------------------------------------------
  835. RAWLockMemory    proc    near
  836.     call    RAWCopyCheck
  837.     ;
  838.     pushm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  839.     mov    ax,KernalDS
  840.     mov    ds,ax
  841.     assume ds:_cwRaw
  842.  
  843.     push    ebx
  844.     push    ecx
  845.     push    edx
  846.     xor    ebx,ebx
  847.     mov    bx,ss
  848.     mov    ecx,esp
  849.     pushf
  850.     cli
  851.     mov    edx,d[RawStackPos]
  852.     sub    d[RawStackPos],RawStackDif
  853.     popf
  854.     mov    ax,KernalSS
  855.     mov    ss,ax
  856.     mov    esp,edx
  857.     add    ecx,4+4+4
  858.     pushm    ebx,ecx
  859.     sub    ecx,4+4+4
  860.     push    es
  861.     mov    es,bx
  862.     mov    edx,es:[ecx]
  863.     mov    ebx,es:[ecx+4+4]
  864.     mov    ecx,es:[ecx+4]
  865.     pop    es
  866.  
  867.     ;
  868.     shl    ebx,16
  869.     mov    bx,cx
  870.     shl    esi,16
  871.     mov    si,di
  872.     add    esi,ebx
  873.     and    ebx,not 4095        ;round down to nearest page.
  874.     mov    d[_LM_BlockBase],ebx
  875.     add    esi,4095
  876.     and    esi,not 4095        ;round up to next page.
  877.     dec    esi
  878.     mov    d[_LM_BlockEnd],esi    ;store address of last page.
  879.     ;
  880.     ;Check if start above end now!
  881.     ;
  882.     mov    eax,d[_LM_BlockBase]
  883.     cmp    eax,d[_LM_BlockEnd]
  884.     jnc    @@10
  885.     ;
  886.     ;Count number of pages we need for this range.
  887.     ;
  888.     mov    d[_LM_Needed],0
  889.     mov    eax,NoneLockedPages
  890.     mov    d[_LM_Got],eax
  891.     mov    eax,d[_LM_BlockBase]
  892. @@04:    cmp    eax,LinearBase    ;must be in our memory pool.
  893.     jc    @@05
  894.     cmp    eax,LinearLimit
  895.     jnc    @@05
  896.     push    eax
  897.     call    GetPageStatus
  898.     pop    eax
  899.     jc    @@15        ;ignore not present tables.
  900.     test    edx,1
  901.     jz    @@005        ;already present.
  902.     call    RawPageLocked    ;locked page?
  903.     jnz    @@05
  904.     dec    d[_LM_Got]        ;reduce available pages.
  905.     jmp    @@05
  906. @@005:    inc    d[_LM_Needed]
  907. @@05:    add    eax,4096
  908.     cmp    eax,d[_LM_BlockEnd]    ;done them all yet?
  909.     jc    @@04
  910. ;
  911. ;Check if we actually need any more pages to lock this region.
  912. ;
  913.     cmp    d[_LM_Needed],0
  914.     jz    @@OK
  915. ;
  916. ;If VMM isn't active then pages can always be locked assumeing they exist.
  917. ;
  918.     cmp    VMMHandle,0
  919.     jnz    @@VMM
  920.     mov    eax,d[_LM_Needed]
  921.     cmp    eax,d[_LM_Got]
  922.     jc    @@OK
  923.     jz    @@OK
  924.     jmp    @@15
  925. ;
  926. ;VMM is active and pages are required so we need to make sure enough pages are
  927. ;left for swapping.
  928. ;
  929. @@VMM:    mov    eax,d[_LM_Needed]
  930.     add    eax,16        ;arbitrary safety buffer.
  931.     cmp    eax,d[_LM_Got]
  932.     jc    @@OK
  933.     jz    @@OK
  934.     jmp    @@15
  935. ;
  936. ;Enough free pages so lock the region.
  937. ;
  938. @@OK:    mov    eax,d[_LM_BlockBase]
  939. @@4:    cmp    eax,LinearBase    ;must be in our memory pool.
  940.     jc    @@5
  941.     cmp    eax,LinearLimit
  942.     jnc    @@5
  943.     push    eax
  944.     call    GetPageStatus
  945.     pop    eax
  946.     jc    @@15        ;ignore not present tables.
  947.     test    edx,1        ;is it present?
  948.     jnz    @@6
  949.     ;
  950. @@11:    ;Need to allocate a physical page first.
  951.     ;
  952.     push    eax
  953.     call    UnMapPhysical
  954.     pop    eax
  955.     jc    @@15        ;this shouldn't happen.
  956.     mov    LinearEntry,eax
  957.     shr    LinearEntry,12    ;store page number to allocate at.
  958.     push    eax
  959.     call    MapPhysical        ;map this page in.
  960.     pop    eax
  961.     ;
  962. @@6:    ;Now mark this page as locked.
  963.     ;
  964.     call    RawLockPage
  965.     ;
  966. @@5:    add    eax,4096
  967.     cmp    eax,d[_LM_BlockEnd]    ;done them all yet?
  968.     jc    @@4
  969.     ;
  970. @@10:    clc
  971.     jmp    @@1
  972.     ;
  973. @@15:    stc
  974.     ;
  975. @@1:
  976.     lss    esp,f[esp]
  977.     pushf
  978.     add    d[RawStackPos],RawStackDif
  979.     popf
  980.  
  981.     popm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  982.     ret
  983.     assume ds:_cwDPMIEMU
  984. RAWLockMemory    endp
  985.  
  986.  
  987. ;-------------------------------------------------------------------------------
  988. RAWUnLockMemory proc near
  989.     call    RAWCopyCheck
  990.     ;
  991.     pushm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  992.     mov    ax,KernalDS
  993.     mov    ds,ax
  994.     assume ds:_cwRaw
  995.     ;
  996.  
  997.     push    ebx
  998.     push    ecx
  999.     push    edx
  1000.     xor    ebx,ebx
  1001.     mov    bx,ss
  1002.     mov    ecx,esp
  1003.     pushf
  1004.     cli
  1005.     mov    edx,d[RawStackPos]
  1006.     sub    d[RawStackPos],RawStackDif
  1007.     popf
  1008.     mov    ax,KernalSS
  1009.     mov    ss,ax
  1010.     mov    esp,edx
  1011.     add    ecx,4+4+4
  1012.     pushm    ebx,ecx
  1013.     sub    ecx,4+4+4
  1014.     push    es
  1015.     mov    es,bx
  1016.     mov    edx,es:[ecx]
  1017.     mov    ebx,es:[ecx+4+4]
  1018.     mov    ecx,es:[ecx+4]
  1019.     pop    es
  1020.  
  1021.     shl    ebx,16
  1022.     mov    bx,cx
  1023.     shl    esi,16
  1024.     mov    si,di
  1025.     add    esi,ebx
  1026.     and    ebx,0FFFFFFFFh-4095    ;round down to nearest page.
  1027.     mov    d[_LM_BlockBase],ebx
  1028.     add    esi,4095
  1029.     and    esi,0FFFFFFFFh-4095    ;round up to next page.
  1030.     dec    esi
  1031.     mov    d[_LM_BlockEnd],esi    ;store address of last page.
  1032.     ;
  1033.     ;Now run through all pages in this range un-locking them.
  1034.     ;
  1035.     mov    eax,d[_LM_BlockBase]
  1036. @@4:    cmp    eax,LinearBase    ;must be in our memory pool.
  1037.     jc    @@5
  1038.     cmp    eax,LinearLimit
  1039.     jnc    @@5
  1040.     push    eax
  1041.     call    GetPageStatus
  1042.     pop    eax
  1043.     jc    @@5        ;ignore not present tables.
  1044.     test    edx,1        ;is it present?
  1045.     jz    @@5
  1046.     call    RawUnLockPage    ;unlock the page.
  1047. @@5:    add    eax,4096
  1048.     cmp    eax,d[_LM_BlockEnd]    ;done them all yet?
  1049.     jc    @@4
  1050.     clc
  1051. @@1:
  1052.  
  1053.     lss    esp,f[esp]
  1054.     pushf
  1055.     add    d[RawStackPos],RawStackDif
  1056.     popf
  1057.  
  1058.     popm    eax,ebx,ecx,edx,esi,edi,ebp,ds,es,fs,gs
  1059.     ret
  1060.     assume ds:_cwDPMIEMU
  1061. RAWUnLockMemory endp
  1062.  
  1063.  
  1064. ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  1065. RAWGetMemoryMax proc near
  1066. ;
  1067. ;Work out biggest memory block remaining.
  1068. ;
  1069.     call    RAWCopyCheck
  1070.     ;
  1071.     pushm    eax,ecx,edx,esi,edi,ebp,ds,es
  1072.     mov    ax,KernalDS        ;make data addresable.
  1073.     mov    ds,ax
  1074.     assume ds:_cwRaw
  1075.  
  1076.     push    ebx
  1077.     push    ecx
  1078.     push    edx
  1079.     xor    ebx,ebx
  1080.     mov    bx,ss
  1081.     mov    ecx,esp
  1082.     pushf
  1083.     cli
  1084.     mov    edx,d[RawStackPos]
  1085.     sub    d[RawStackPos],RawStackDif
  1086.     popf
  1087.     mov    ax,KernalSS
  1088.     mov    ss,ax
  1089.     mov    esp,edx
  1090.     add    ecx,4+4+4
  1091.     pushm    ebx,ecx
  1092.     sub    ecx,4+4+4
  1093.     push    es
  1094.     mov    es,bx
  1095.     mov    edx,es:[ecx]
  1096.     mov    ebx,es:[ecx+4+4]
  1097.     mov    ecx,es:[ecx+4]
  1098.     pop    es
  1099.  
  1100.     mov    ax,KernalZero
  1101.     mov    es,ax
  1102.     ;
  1103.     ;Look in existing memory first.
  1104.     ;
  1105.     mov    edx,LinearBase    ;Get starting point.
  1106.     mov    ecx,LinearLimit
  1107.     sub    ecx,edx        ;Get memory present.
  1108.     shr    ecx,12        ;Get pages.
  1109.     shr    edx,12        ;Get page number.
  1110.     xor    edi,edi        ;Clear flag.
  1111.     xor    ebp,ebp        ;Clear biggest so far.
  1112.     ;
  1113. @@l0:    ;Look for a bigest block of free memory.
  1114.     ;
  1115.     mov    eax,es:d[(1024*4096*1022)+edx*4] ;Get page details.
  1116.     and    eax,MEM_MASK
  1117.     cmp    eax,MEM_FREE        ;Free block?
  1118.     jnz    @@l2
  1119.     or    edi,edi        ;Got any yet?
  1120.     jnz    @@l1
  1121.     mov    esi,edx        ;Get base page number.
  1122. @@l1:    inc    edi
  1123.     cmp    edi,ebp        ;Biggest yet?
  1124.     jc    @@l3
  1125.     mov    ebx,esi        ;Get base.
  1126.     mov    ebp,edi        ;Get size.
  1127.     jmp    @@l3
  1128. @@l2:    xor    edi,edi
  1129. @@l3:    inc    edx        ;Next page.
  1130.     dec    ecx
  1131.     jnz    @@l0
  1132.     ;
  1133.     ;See if biggest block found is the last block in the map.
  1134.     ;
  1135.     xor    edx,edx        ;reset end of chain value.
  1136.     or    edi,edi        ;last block free?
  1137.     jz    @@l4
  1138.     cmp    ebx,esi        ;same base?
  1139.     jnz    @@l4
  1140.     mov    edx,ebp        ;setup extra block size.
  1141.     mov    ebp,0        ;reset normal block size.
  1142.     jmp    @@l5
  1143.     ;
  1144. @@l4:    ;Get size of the last block in the memory map.
  1145.     ;
  1146.     mov    eax,LinearBase
  1147.     mov    esi,LinearLimit
  1148.     shr    esi,12
  1149.     dec    esi
  1150.     shr    eax,12
  1151.     mov    ecx,esi
  1152.     sub    ecx,eax
  1153. @@l6:    jecxz    @@l5
  1154.     mov    eax,es:d[(1024*4096*1022)+esi*4] ;Get page details.
  1155.     and    eax,MEM_MASK
  1156.     cmp    eax,MEM_FREE        ;Free block?
  1157.     jnz    @@l5
  1158.     dec    esi
  1159.     inc    edx
  1160.     dec    ecx
  1161.     jmp    @@l6
  1162.     ;
  1163. @@l5:    ;See what extra memory we can get hold of.
  1164.     ;
  1165.     mov    ebx,edx
  1166.     call    PhysicalGetPages    ;Get extra memory available.
  1167.     mov    ecx,ebx        ;Save origional value.
  1168.     add    ebx,edx        ;update extra memory value.
  1169.     ;
  1170.     ;See how many pages of real memory would be lost to page tables.
  1171.     ;
  1172.     mov    eax,LinearLimit
  1173.     shr    eax,12
  1174.     add    eax,edx
  1175.     shr    eax,10
  1176.     mov    edx,LinearLimit
  1177.     shr    edx,12
  1178.     dec    edx
  1179.     shr    edx,10
  1180.     sub    eax,edx
  1181.     add    eax,eax        ;Page + Det
  1182.     sub    ebx,eax
  1183.     ;
  1184.     ;See what extra memory the VMM can get hold of.
  1185.     ;
  1186.     cmp    VMMHandle,0
  1187.     jz    @@l8
  1188.     mov    ebx,ecx
  1189.     pushm    ebx,ebp
  1190.     ;
  1191.     ;Get free disk space remaining.
  1192.     ;
  1193.     mov    dl,VMMName        ;get drive letter for this media.
  1194.     sub    dl,'A'        ;make it real.
  1195.     inc    dl        ;adjust for current type select.
  1196.     mov    ah,36h        ;get free space.
  1197.     int    21h        ;/
  1198.     xor    edx,edx
  1199.     cmp    ax,-1        ;invalid drive?
  1200.     jz    @@l7
  1201.     mul    cx        ;Get bytes per cluster.
  1202.     mul    bx        ;Get bytes available.
  1203.     shl    edx,16
  1204.     mov    dx,ax
  1205. @@l7:    ;
  1206.     ;Get current swap file size.
  1207.     ;
  1208.     push    edx
  1209.     mov    bx,VMMHandle
  1210.     mov    ax,4202h
  1211.     xor    cx,cx
  1212.     mov    dx,cx
  1213.     int    21h
  1214.     shl    edx,16
  1215.     mov    dx,ax
  1216.     pop    eax
  1217.     add    edx,eax
  1218.     and    edx,not 65535
  1219.     shr    edx,12
  1220.     popm    ebx,ebp
  1221.     ;
  1222.     ;Work out how much of the VMM space is extra.
  1223.     ;
  1224.     mov    eax,LinearLimit
  1225.     sub    eax,LinearBase
  1226.     shr    eax,12
  1227.     sub    edx,eax
  1228.     add    ebx,edx
  1229.  
  1230.     ;
  1231. @@l8:    ;Check which block is bigger and exit.
  1232.     ;
  1233.     push    ecx
  1234.     mov    eax,ebx
  1235.     shl    eax,12
  1236.     mov    ecx,LinearLimit
  1237.     sub    ecx,LinearBase
  1238.     sub    eax,ecx
  1239.     js    @@l89
  1240.     cmp    eax,MaxMemLin
  1241.     jc    @@l89
  1242.     mov    ebx,MaxMemLin
  1243.     sub    ebx,ecx
  1244.     shr    ebx,12
  1245. @@l89:    pop    ecx
  1246.  
  1247.     cmp    ebx,ebp
  1248.     jnc    @@l9
  1249.     mov    ebx,ebp
  1250. @@l9:    shl    ebx,12
  1251.     clc
  1252.  
  1253.     lss    esp,f[esp]
  1254.     pushf
  1255.     add    d[RawStackPos],RawStackDif
  1256.     popf
  1257.  
  1258.     popm    eax,ecx,edx,esi,edi,ebp,ds,es
  1259.     ret
  1260.     assume ds:_cwDPMIEMU
  1261. RAWGetMemoryMax endp
  1262.  
  1263.  
  1264. ;-------------------------------------------------------------------------------
  1265. ;
  1266. ;Extend the linear memory map by allocateing physical memory if available or
  1267. ;virtual memory if not, or even a combination of the two.
  1268. ;
  1269. ;On Entry:
  1270. ;
  1271. ;ECX    - Pages to extend by.
  1272. ;
  1273. ;On Exit:
  1274. ;
  1275. ;Carry set on error else memory map extended.
  1276. ;
  1277. ExtendLinearMemory proc near
  1278.     pushad
  1279.     pushm    ds,es
  1280.     mov    ax,KernalDS
  1281.     mov    ds,ax
  1282.     assume ds:_cwRaw
  1283.     mov    ax,KernalZero
  1284.     mov    es,ax
  1285.     mov    ebp,ecx
  1286.  
  1287.     mov    eax,ecx
  1288.     shl    eax,12
  1289.     dec    eax
  1290.     add    eax,LinearLimit
  1291.     dec    eax
  1292.     sub    eax,LinearBase
  1293.     cmp    eax,MaxMemLin
  1294.     jnc    @@error
  1295.  
  1296.     ;
  1297.     ;Try extending useing physical memory first.
  1298.     ;
  1299. @@f0:    mov    eax,LinearLimit    ;get new entry number.
  1300.     shr    eax,12        ;page number.
  1301.     mov    LinearEntry,eax
  1302.     shr    eax,10        ;/1024 for page dir entry.
  1303.     mov    edi,PageDirLinear    ;get page table address.
  1304.     mov    eax,es:d[edi+eax*4]    ;this page present?
  1305.     test    eax,1        ;do we have a page table?
  1306.     jnz    @@f1        ;keep going till we do.
  1307. ;
  1308. ;No page table so make sure we can get 2 pages (page and det)
  1309. ;
  1310.     call    PhysicalGetPages
  1311.     cmp    edx,2
  1312.     jc    @@virtual
  1313. ;
  1314. ;both pages available so go to it.
  1315. ;
  1316. @@f2:    call    PhysicalGetPage    ;get a page.
  1317.     jc    @@error        ;it lied.
  1318.     mov    eax,LinearLimit    ;get new entry number.
  1319.     shr    eax,12        ;page number.
  1320.     mov    LinearEntry,eax
  1321.     push    LinearEntry
  1322.     call    MapPhysical        ;use this page for page table.
  1323.     call    PhysicalGetPage    ;get a page.
  1324.     pop    LinearEntry
  1325.     jc    @@error        ;it lied.
  1326.     call    MapPhysical        ;use this page for page table.
  1327.     ;
  1328. @@f1:    call    PhysicalGetPage    ;get a page.
  1329.     jc    @@Virtual        ;use virtual memory.
  1330.     mov    eax,LinearLimit    ;get new entry number.
  1331.     shr    eax,12        ;page number.
  1332.     mov    LinearEntry,eax
  1333.     call    MapPhysical        ;use this page for page table.
  1334.     ;
  1335.     ;Update details.
  1336.     ;
  1337.     mov    eax,LinearLimit
  1338.     shr    eax,12
  1339.     mov    es:d[(1024*4096*1022)+eax*4],0
  1340.     inc    FreePages
  1341. ;    dec    medAllocPages
  1342.     inc    TotalPages
  1343.     add    LinearLimit,4096    ;bump up the end of the memory map.
  1344.     dec    ebp        ;update the counter.
  1345.     jnz    @@f0        ;keep looking.
  1346.     clc
  1347.     jmp    @@exit        ;All physical so exit.
  1348.     ;
  1349. @@Virtual:    ;Virtual memory will be needed so see if we can provide any.
  1350.     ;
  1351.     cmp    VMMHandle,0        ;Virtual memory active?
  1352.     jz    @@error
  1353.     ;
  1354.     ;Find out how much disk space is left for swap file to grow into.
  1355.     ;
  1356.     mov    dl,VMMName        ;get drive letter for this media.
  1357.     sub    dl,'A'        ;make it real.
  1358.     inc    dl        ;adjust for current type select.
  1359.     mov    ah,36h        ;get free space.
  1360.     push    ebp
  1361.     int    21h        ;/
  1362.     pop    ebp
  1363.     cmp    ax,-1        ;invalid drive?
  1364.     jz    @@error
  1365.     mul    cx        ;Get bytes per cluster.
  1366.     mul    bx        ;Get bytes available.
  1367.     shl    edx,16
  1368.     mov    dx,ax        ;make 32 bit.
  1369.     and    edx,not 65535
  1370.     add    edx,SwapFileLength    ;add existing size.
  1371.     mov    eax,LinearLimit
  1372.     sub    eax,LinearBase    ;get current real memory.
  1373.     sub    edx,eax
  1374.     shr    edx,12        ;get it as pages.
  1375.     cmp    edx,ebp        ;Enough pages?
  1376.     jc    @@error
  1377.     ;
  1378.     ;Find out how many un-locked pages we currently have.
  1379.     ;
  1380.     mov    edx,NoneLockedPages
  1381.     ;
  1382.     ;Enough page's for minimum requirement?
  1383.     ;
  1384.     cmp    edx,16        ;un-locked pages < 16?
  1385.     jc    @@error        ;force minimum of 16.
  1386.     sub    edx,16
  1387.     ;
  1388.     ;Work out how many new page/det tables are required.
  1389.     ;
  1390.     mov    eax,LinearLimit
  1391.     shr    eax,12
  1392.     mov    ebx,eax
  1393.     dec    eax        ;Last definatly valid page table.
  1394.     add    ebx,ebp        ;New end page.
  1395.     shr    eax,10
  1396.     shr    ebx,10        ;Get page table units (4Meg)
  1397.     sub    ebx,eax        ;get the differance.
  1398.     jz    @@DoneTables
  1399.     add    ebx,ebx        ;Page + Det
  1400.     mov    ecx,ebp
  1401.     cmp    ebx,edx
  1402.     jc    @@OK
  1403.     jz    @@OK
  1404.     jmp    @@error
  1405.     ;
  1406. @@OK:    ;Allocate new page tables.
  1407.     ;
  1408.     mov    esi,PageDirLinear    ;get page directory address.
  1409.     mov    edx,LinearLimit
  1410.     shr    edx,12
  1411. @@v2:    mov    eax,edx        ;get new entry number.
  1412.     shr    eax,10        ;/1024 for page dir entry.
  1413.     test    es:d[esi+eax*4],1    ;this page present?
  1414.     jnz    @@v3
  1415.     ;
  1416.     ;get DET page.
  1417.     ;
  1418.     pushm    ecx,edx
  1419.     call    UnMapPhysical    ;get a physical page for us to use.
  1420.     mov    eax,edx
  1421.     mov    ebx,ecx
  1422.     popm    ecx,edx
  1423.     jc    @@error        ;not enough physical memory to support virtual memory.
  1424.     pushm    ecx,edx
  1425.     mov    LinearEntry,edx    ;set logical page address.
  1426.     mov    edx,eax        ;get physical address again.
  1427.     mov    ecx,ebx
  1428.     call    MapPhysical        ;use this to add a new page table.
  1429.     popm    ecx,edx
  1430.     ;
  1431.     ;And again for page table.
  1432.     ;
  1433.     pushm    ecx,edx
  1434.     call    UnMapPhysical    ;get a physical page for us to use.
  1435.     mov    eax,edx
  1436.     mov    ebx,ecx
  1437.     popm    ecx,edx
  1438.     jc    @@error        ;not enough physical memory to support virtual memory.
  1439.     pushm    ecx,edx
  1440.     mov    LinearEntry,edx    ;set logical page address.
  1441.     mov    edx,eax        ;get physical address again.
  1442.     mov    ecx,ebx
  1443.     call    MapPhysical        ;use this to add a new page table.
  1444.     popm    ecx,edx
  1445. @@v3:    inc    edx
  1446.     dec    ecx
  1447.     jnz    @@v2
  1448.     ;
  1449. @@DoneTables:    ;Now mark all the new pages as un-locked/free
  1450.     ;
  1451.     mov    eax,LinearLimit
  1452.     mov    ecx,ebp
  1453. @@v4:    call    RawClearPageLock    ;clear page locking for this entry.
  1454.     push    eax
  1455.     shr    eax,12
  1456.     mov    es:d[1024*4096*1022+eax*4],0
  1457.     pop    eax
  1458.     add    eax,4096
  1459.     dec    ecx
  1460.     jnz    @@v4
  1461.     ;
  1462.     ;Extend the swap file.
  1463.     ;
  1464.     mov    ecx,LinearLimit    ;current end position.
  1465.     sub    ecx,LinearBase    ;length.
  1466.     mov    eax,ebp        ;extension needed in pages.
  1467.     shl    eax,12
  1468.     add    ecx,eax        ;New extremity desired.
  1469.     cmp    ecx,SwapFileLength
  1470.     jc    @@Extended
  1471.     add    ecx,65535
  1472.     and    ecx,not 65535
  1473.     push    ecx
  1474.     mov    dx,cx
  1475.     shr    ecx,16
  1476.     mov    bx,VMMHandle        ;get swap file handle.
  1477.     mov    ax,4200h
  1478.     mov    edi,offset PageInt
  1479.     push    edi
  1480.     mov    Real_EAX[edi],eax
  1481.     mov    Real_EBX[edi],ebx
  1482.     mov    Real_ECX[edi],ecx
  1483.     mov    Real_EDX[edi],edx
  1484.     mov    Real_SS[edi],0
  1485.     mov    Real_SP[edi],0
  1486.     mov    bl,21h
  1487.     push    ds
  1488.     pop    es
  1489.     call    EMURawSimulateInt    ;move to right place.
  1490.     pop    edi
  1491.     mov    ah,40h
  1492.     mov    bx,VMMHandle        ;get swap file handle.
  1493.     mov    cx,0
  1494.     push    edi
  1495.     mov    edi,offset PageInt
  1496.     mov    Real_EAX[edi],eax
  1497.     mov    Real_EBX[edi],ebx
  1498.     mov    Real_ECX[edi],ecx
  1499.     mov    Real_EDX[edi],edx
  1500.     mov    Real_SS[edi],0
  1501.     mov    Real_SP[edi],0
  1502.     mov    bl,21h
  1503.     push    ds
  1504.     pop    es
  1505.     call    EMURawSimulateInt    ;move to right place.
  1506.     pop    edi
  1507.     pop    ecx
  1508.     test    Real_Flags[edi],1
  1509.     jnz    @@disk_error
  1510.     mov    SwapFileLength,ecx
  1511.     ;
  1512.     xor    cx,cx
  1513.     xor    dx,dx
  1514.     mov    ax,4201h
  1515.     mov    bx,VMMHandle
  1516.     push    edi
  1517.     mov    edi,offset PageInt
  1518.     mov    Real_EAX[edi],eax
  1519.     mov    Real_EBX[edi],ebx
  1520.     mov    Real_ECX[edi],ecx
  1521.     mov    Real_EDX[edi],edx
  1522.     mov    Real_SS[edi],0
  1523.     mov    Real_SP[edi],0
  1524.     mov    bl,21h
  1525.     push    ds
  1526.     pop    es
  1527.     call    EMURawSimulateInt    ;move to right place.
  1528.     pop    edi
  1529.     test    Real_Flags[edi],1
  1530.     jnz    @@disk_error
  1531.     mov    edx,Real_EDX[edi]
  1532.     mov    eax,Real_EAX[edi]
  1533.     shl    edx,16
  1534.     mov    dx,ax
  1535.     cmp    edx,SwapFileLength
  1536.     jnz    @@disk_error
  1537.     ;
  1538. @@Extended:    ;Update the end of the memory map.
  1539.     ;
  1540.     add    FreePages,ebp
  1541. ;    sub    medAllocPages,ebp
  1542.     shl    ebp,12
  1543.     add    LinearLimit,ebp
  1544.     clc
  1545.     jmp    @@Exit
  1546.     ;
  1547. @@error:    stc
  1548. @@Exit:    ;
  1549.     popm    ds,es
  1550.     popad
  1551.     ret
  1552.     ;
  1553. @@Disk_Error:    jmp    @@error
  1554.     assume ds:_cwDPMIEMU
  1555. ExtendLinearMemory endp
  1556.  
  1557.  
  1558. ;-------------------------------------------------------------------------------
  1559. ;
  1560. ;Map physical page supplied into logical address space. If a new page table is needed, the page
  1561. ;supplied will become a page table.
  1562. ;
  1563. ;On Entry:-
  1564. ;
  1565. ;CL    - Use flags 0-3. 1 being used for VCPI memory to allow release later.
  1566. ;EDX    - Physical address to map.
  1567. ;
  1568. MapPhysical    proc    near
  1569.     pushad
  1570.     pushm    ds,es
  1571.     mov    ax,KernalDS
  1572.     mov    ds,ax
  1573.     assume ds:_cwRaw
  1574.     mov    ax,KernalZero    ;make everything addresable.
  1575.     mov    es,ax
  1576.     ;
  1577.     and    ecx,1        ;put user bits in useful place.
  1578.     shl    ecx,10
  1579.     and    edx,0FFFFFFFFh-4095    ;lose user bits.
  1580.     mov    eax,LinearEntry    ;get new entry number.
  1581.     shr    eax,10        ;/1024 for page dir entry.
  1582.     ;
  1583.     mov    esi,PageDirLinear    ;get page table address.
  1584.     test    es:d[esi+eax*4],1    ;this page present?
  1585.     jnz    @@AddPage
  1586.     ;
  1587.     cmp    PageDETLinear,0    ;DET in use yet?
  1588.     jz    @@AddTable
  1589.     mov    esi,PageDETLinear    ;get page table address.
  1590.     test    es:d[esi+eax*4],1    ;DET page present?
  1591.     jnz    @@AddTable
  1592.     ;
  1593. @@AddDET:    ;Need a new DET page.
  1594.     ;
  1595.     or    edx,111b        ;present+user+write.
  1596.     or    edx,ecx        ;set use flags.
  1597.     mov    es:d[esi+eax*4],edx    ;store this tables address.
  1598.     ;
  1599.     ;Clear this page to locked.
  1600.     ;
  1601.     mov    edi,1024*4096*1022    ;base of page DET's.
  1602.     mov    eax,LinearEntry    ;get the entry number again.
  1603.     shl    eax,2        ;4 bytes per entry.
  1604.     add    edi,eax
  1605.     mov    ecx,4096/4
  1606.     mov    eax,MEM_FILL
  1607.     cld
  1608.     rep    stosd
  1609.     ;
  1610.     jmp    @@Finished
  1611.     ;
  1612. @@AddTable:    ;Need a new page table.
  1613.     ;
  1614.     mov    eax,LinearEntry    ;get new entry number.
  1615.     shr    eax,10        ;/1024 for page dir entry.
  1616.     mov    esi,PageDirLinear    ;get page table address.
  1617.     or    edx,111b        ;present+user+write.
  1618.     or    edx,ecx        ;set use flags.
  1619.     mov    es:d[esi+eax*4],edx    ;store this tables address.
  1620.     mov    esi,PageAliasLinear    ;get alias table address.
  1621.     mov    es:d[esi+eax*4],edx    ;setup in alias table as well.
  1622.     ;
  1623.     ;Clear this page to 0.
  1624.     ;
  1625.     mov    edi,1024*4096*1023    ;base of page alias's.
  1626.     mov    eax,LinearEntry    ;get the entry number again.
  1627.     shl    eax,2        ;4 bytes per entry.
  1628.     add    edi,eax
  1629.     mov    ecx,4096/4
  1630.     xor    eax,eax
  1631.     cld
  1632.     rep    stosd
  1633.     ;
  1634.     jmp    @@Finished
  1635.     ;
  1636. @@AddPage:    ;Update recent page usage stack.
  1637.     ;
  1638.     pushm    ecx,es,ds
  1639.     pop    es
  1640.     mov    edi,offset RecentMapStack+(4*PageStackSize)-4
  1641.     mov    esi,offset RecentMapStack+(4*PageStackSize)-8
  1642.     mov    ecx,PageStackSize-1
  1643.     std
  1644.     rep    movsd
  1645.     popm    ecx,es
  1646.     cld
  1647.     mov    eax,LinearEntry
  1648.     shl    eax,12
  1649.     mov    RecentMapStack,eax
  1650.     ;
  1651.     ;Add this to the relavent page table.
  1652.     ;
  1653.     mov    eax,LinearEntry    ;get the entry number again.
  1654.     mov    esi,1024*4096*1023    ;base of page alias's.
  1655.     mov    ebx,es:d[esi+eax*4]    ;get current details.
  1656.     and    ebx,1 shl 11
  1657.     or    edx,ebx
  1658.     or    edx,111b        ;present+user+write.
  1659.     or    edx,ecx        ;set use flags.
  1660.     mov    es:d[esi+eax*4],edx    ;set physical address.
  1661.     ;
  1662.     cmp    PageDETLinear,0
  1663.     jz    @@NoLocking
  1664.     mov    eax,LinearEntry
  1665.     shl    eax,12
  1666.     call    RawClearPageLock    ;clear page locking for this entry.
  1667.     ;
  1668.     ;Update number of un-locked physical pages present.
  1669.     ;
  1670.     inc    NoneLockedPages
  1671.     ;
  1672. @@NoLocking:    ;Check if this page needs fetching from swap space.
  1673.     ;
  1674.     cmp    VMMHandle,0
  1675.     jz    @@NoRead
  1676.     ;
  1677.     test    ebx,1 shl 11
  1678.     jz    @@NoRead
  1679.     ;
  1680.     mov    esi,BreakAddress
  1681.     mov    al,es:[esi]
  1682.     mov    es:b[esi],0
  1683.     push    eax
  1684.     ;
  1685.     mov    ecx,LinearEntry    ;get page number.
  1686.     shl    ecx,12        ;get linear address.
  1687.     sub    ecx,LinearBase
  1688.     mov    dx,cx
  1689.     shr    ecx,16
  1690.     mov    bx,VMMHandle
  1691.     mov    ax,4200h
  1692.     mov    edi,offset PageInt
  1693.     mov    Real_EBX[edi],ebx
  1694.     mov    Real_EAX[edi],eax
  1695.     mov    Real_EDX[edi],edx
  1696.     mov    Real_ECX[edi],ecx
  1697.     mov    Real_SS[edi],0
  1698.     mov    Real_SP[edi],0
  1699.     mov    bl,21h
  1700.     pushm    es,ds
  1701.     pop    es
  1702.     call    EMURawSimulateInt    ;move to right place.
  1703.     mov    edi,offset PageInt
  1704.     mov    ax,VMMHandle
  1705.     mov    Real_EBX[edi],eax
  1706.     mov    ax,PageBufferReal
  1707.     mov    Real_DS[edi],ax
  1708.     mov    Real_EAX[edi],3f00h
  1709.     mov    Real_EDX[edi],0
  1710.     mov    Real_ECX[edi],4096
  1711.     mov    Real_SS[edi],0
  1712.     mov    Real_SP[edi],0
  1713.     mov    bl,21h
  1714.     call    EMURawSimulateInt    ;read it from disk.
  1715.     pop    es
  1716.     test    Real_Flags[edi],1
  1717.     jz    @@ok
  1718.     mov    esi,BreakAddress
  1719.     pop    eax
  1720.     mov    es:[esi],al
  1721.     jmp    @@Finished2
  1722.     ;
  1723. @@ok:    mov    esi,BreakAddress
  1724.     pop    eax
  1725.     mov    es:[esi],al
  1726.     ;
  1727.     mov    esi,PageBufferLinear
  1728.     mov    edi,LinearEntry
  1729.     shl    edi,12        ;get linear address again.
  1730.     mov    ecx,4096/4
  1731.     pushm    ds,es
  1732.     pop    ds
  1733.     cld
  1734.     rep    movsd        ;copy back into place.
  1735.     pop    ds
  1736.     ;
  1737.     mov    eax,LinearEntry    ;get new entry number.
  1738.     mov    esi,1024*4096*1023    ;base of page alias's.
  1739.     and    es:d[esi+eax*4],0FFFFFFFFh-(3 shl 5)    ;clear accesed & dirty bits.
  1740.     call    EMUCR3Flush
  1741.     ;
  1742. @@NoRead:    inc    LinearEntry        ;update counter.
  1743.     ;
  1744. @@Finished:    clc
  1745.     ;
  1746. @@Finished2:    popm    ds,es
  1747.     popad
  1748.     ret
  1749.     assume ds:_cwDPMIEMU
  1750. MapPhysical    endp
  1751.  
  1752.  
  1753. ;-------------------------------------------------------------------------------
  1754. ;
  1755. ;Retrieve the address of the most un-needed physical memory and mark its current page table entry
  1756. ;as not present after writing to disk if needed.
  1757. ;
  1758. ;On Entry:-
  1759. ;
  1760. ;On Exit:-
  1761. ;
  1762. ;EDX    - Physical address of page.
  1763. ;CL    - User flags.
  1764. ;
  1765. UnMapPhysical    proc    near
  1766.     pushm    eax,ebx,esi,edi,ebp,ds,es,fs
  1767.     ;
  1768.     mov    ax,KernalDS
  1769.     mov    ds,ax
  1770.     mov    es,ax
  1771.     assume ds:_cwRaw
  1772.     mov    ax,KernalZero
  1773.     mov    fs,ax
  1774.     ;
  1775.     mov    ProposedPresentFlag,0
  1776.     mov    ProposedRecentFlag,0
  1777.     mov    CompareCount,0
  1778.     ;
  1779.     mov    esi,PageDirLinear
  1780.     mov    edi,1024*4096*1023    ;base of page alias's.
  1781.     mov    ebp,1024*4096*1022
  1782.     mov    ecx,PageingPointer    ;get current position.
  1783.     mov    ebx,LinearLimit    ;maximum size of scan we can do.
  1784.     sub    ebx,LinearBase
  1785.     shr    ebx,12
  1786.     inc    ebx
  1787.     cld
  1788.     ;
  1789. @@ScanLoop:    dec    ebx
  1790.     jnz    @@80        ;shit, we've been all the way round.
  1791.     ;
  1792.     cmp    ProposedPresentFlag,0
  1793.     jnz    @@UseProposed
  1794.     jmp    @@8
  1795.     ;
  1796. @@80:    cmp    ecx,LinearBase
  1797.     jnc    @@80_0
  1798.     mov    ecx,LinearBase
  1799.     sub    ecx,4096
  1800. @@80_0:    add    ecx,4096
  1801.     cmp    ecx,LinearLimit    ;End of memory map yet?
  1802.     jc    @@NoWrap
  1803.     mov    ecx,LinearBase
  1804.     ;
  1805. @@NoWrap:    mov    eax,ecx
  1806.     shr    eax,12        ;get page number.
  1807.     test    fs:d[edi+eax*4],1    ;this page present?
  1808.     jz    @@ScanLoop
  1809.     test    fs:d[ebp+eax*4],MEM_LOCK_MASK shl MEM_LOCK_SHIFT
  1810.     jnz    @@ScanLoop
  1811.     ;
  1812.     inc    CompareCount
  1813.     ;
  1814.     ;Check against recent stack.
  1815.     ;
  1816.     pushm    ecx,edi
  1817.     mov    eax,ecx
  1818.     mov    edi,offset RecentMapStack
  1819.     mov    ecx,PageStackSize
  1820.     repnz    scasd
  1821.     popm    ecx,edi
  1822.     jz    @@IsRecent
  1823.     shr    eax,12        ;get page number again.
  1824.     test    fs:d[edi+eax*4],1 shl 6
  1825.     jz    @@GotPage
  1826.     ;
  1827.     cmp    ProposedPresentFlag,0
  1828.     jz    @@SetProposed
  1829.     cmp    ProposedRecentFlag,0
  1830.     jz    @@UseProposed?
  1831. @@SetProposed:    mov    ProposedPresentFlag,-1
  1832.     mov    ProposedPage,ecx
  1833.     mov    CompareCount,0
  1834.     mov    ProposedRecentFlag,0
  1835.     jmp    @@ScanLoop
  1836.     ;
  1837. @@UseProposed?: mov    eax,NoneLockedPages
  1838.     shr    eax,2
  1839.     cmp    eax,4096
  1840.     jc    @@UP0
  1841.     mov    eax,4096
  1842. @@UP0:    cmp    CompareCount,eax
  1843.     jc    @@UseProposed
  1844.     jmp    @@ScanLoop
  1845.     ;
  1846. @@IsRecent:    cmp    ProposedPresentFlag,0
  1847.     jnz    @@ProposedRecent?
  1848.     mov    ProposedPresentFlag,-1
  1849.     mov    ProposedPage,ecx
  1850.     mov    ProposedRecentFlag,-1
  1851.     mov    CompareCount,0
  1852.     jmp    @@ScanLoop
  1853.     ;
  1854. @@ProposedRecent?:
  1855.     cmp    ProposedRecentFlag,0
  1856.     jnz    @@LookedEnough?
  1857.     mov    eax,NoneLockedPages
  1858.     shr    eax,2
  1859.     cmp    eax,4096
  1860.     jc    @@PR0
  1861.     mov    eax,4096
  1862. @@PR0:    cmp    CompareCount,eax
  1863.     jnc    @@UseProposed
  1864.     jmp    @@ScanLoop
  1865.     ;
  1866. @@LookedEnough?:
  1867.     mov    eax,NoneLockedPages
  1868.     cmp    CompareCount,eax
  1869.     jnc    @@UseProposed
  1870.     jmp    @@ScanLoop
  1871.     ;
  1872. @@UseProposed:    mov    ecx,ProposedPage
  1873.     ;
  1874. @@GotPage:    mov    PageingPointer,ecx
  1875.     ;
  1876.     mov    eax,ecx
  1877.     shr    eax,12        ;get page number again.
  1878.     shl    eax,2
  1879.     add    edi,eax
  1880.     ;
  1881.     ;Check if it needs to go to the swap file.
  1882.     ;
  1883.     test    fs:d[edi],1 shl 6    ;is it dirty?
  1884.     jz    @@5        ;no need to write it if not.
  1885.     ;
  1886.     ;Flush this page to disk.
  1887.     ;
  1888.     push    edi
  1889.     mov    esi,BreakAddress
  1890.     mov    al,fs:[esi]
  1891.     mov    fs:b[esi],0
  1892.     push    eax
  1893.     ;
  1894.     sub    edi,1024*4096*1023    ;get page table entry number.
  1895.     shr    edi,2        ;page number.
  1896.     shl    edi,12        ;get linear address.
  1897.     push    edi
  1898.     mov    esi,edi
  1899.     pushm    ds,es
  1900.     mov    edi,PageBufferLinear    ;copy it to somewhere we can deal with it.
  1901.     mov    ax,KernalZero
  1902.     mov    ds,ax
  1903.     mov    es,ax
  1904.     mov    ecx,4096/4
  1905.     rep    movsd
  1906.     popm    es,ds
  1907.     pop    edi
  1908.     ;
  1909.     sub    edi,LinearBase
  1910.     mov    ebp,edi
  1911.     mov    dx,di
  1912.     shr    edi,16
  1913.     mov    cx,di
  1914.     mov    ax,4200h
  1915.     mov    bx,VMMHandle
  1916.     mov    edi,offset PageInt
  1917.     mov    Real_EBX[edi],ebx
  1918.     mov    Real_EAX[edi],eax
  1919.     mov    Real_EDX[edi],edx
  1920.     mov    Real_ECX[edi],ecx
  1921.     mov    Real_SS[edi],0
  1922.     mov    Real_SP[edi],0
  1923.     mov    bl,21h
  1924.     push    ds
  1925.     pop    es
  1926.     call    EMURawSimulateInt    ;move to right place.
  1927.     ;
  1928.     test    Real_Flags[edi],1
  1929.     stc
  1930.     jnz    @@error_anyway
  1931.     mov    edx,Real_EDX[edi]
  1932.     mov    eax,Real_EAX[edi]
  1933.     shl    edx,16
  1934.     mov    dx,ax
  1935.     cmp    edx,ebp
  1936.     jnz    @@force_error
  1937.     ;
  1938.     mov    edi,offset PageInt
  1939.     mov    ax,VMMHandle
  1940.     mov    Real_EBX[edi],eax
  1941.     mov    ax,PageBufferReal
  1942.     mov    Real_DS[edi],ax
  1943.     mov    Real_EAX[edi],4000h
  1944.     mov    Real_EDX[edi],0
  1945.     mov    Real_ECX[edi],4096
  1946.     mov    Real_SS[edi],0
  1947.     mov    Real_SP[edi],0
  1948.     mov    bl,21h
  1949.     call    EMURawSimulateInt    ;write it to disk.
  1950.     test    Real_Flags[edi],1
  1951.     stc
  1952.     jnz    @@error_anyway
  1953.     mov    eax,Real_EAX[edi]
  1954.     cmp    ax,4096
  1955.     jz    @@error_anyway
  1956. @@force_error:    stc
  1957. @@error_anyway: ;
  1958.     mov    esi,BreakAddress
  1959.     pop    eax
  1960.     mov    fs:[esi],al
  1961.     ;
  1962.     pop    edi
  1963.     jc    @@8
  1964.     or    fs:d[edi],1 shl 11    ;signal it living on disk.
  1965.     ;
  1966. @@5:    ;Now remove it from the page table and exit.
  1967.     ;
  1968.     and    fs:d[edi],0FFFFFFFFh-1    ;mark as not present.
  1969.     mov    edx,fs:[edi]        ;get page entry.
  1970.     mov    ecx,edx
  1971.     and    edx,0FFFFFFFFh-4095    ;lose flag bits.
  1972.     shr    ecx,10
  1973.     and    ecx,1        ;preserve user flags.
  1974.     call    EMUCR3Flush
  1975.     ;
  1976.     ;Update number of un-locked physical pages present.
  1977.     ;
  1978.     dec    NoneLockedPages
  1979.     ;
  1980.     clc
  1981.     jmp    @@9
  1982.     ;
  1983. @@8:    stc            ;failed to find free page.
  1984.     ;
  1985. @@9:    popm    eax,ebx,esi,edi,ebp,ds,es,fs
  1986.     ret
  1987.     assume ds:_cwDPMIEMU
  1988. UnMapPhysical    endp
  1989.  
  1990.  
  1991. ;-------------------------------------------------------------------------------
  1992. ;
  1993. ;Lock page indicated.
  1994. ;
  1995. ;On Entry:-
  1996. ;
  1997. ;EAX    - Linear address to lock.
  1998. ;
  1999. RawLockPage    proc    near
  2000.     pushm    eax,ebx,esi,es
  2001.     shr    eax,12        ;get page number.
  2002.     mov    bx,KernalZero
  2003.     mov    es,bx
  2004.     mov    esi,1024*4096*1022    ;base of page DET's.
  2005.     mov    ebx,es:[esi+eax*4]
  2006.     shr    ebx,MEM_LOCK_SHIFT
  2007.     and    ebx,MEM_LOCK_MASK
  2008.     jnz    @@WasLocked
  2009.     ;
  2010.     ;Update number of un-locked physical pages present.
  2011.     ;
  2012.     pushm    ax,ds
  2013.     mov    ax,KernalDS
  2014.     mov    ds,ax
  2015.     assume ds:_cwRaw
  2016.     dec    NoneLockedPages
  2017.     assume ds:_cwDPMIEMU
  2018.     popm    ax,ds
  2019.     ;
  2020. @@WasLocked:    cmp    ebx,MEM_LOCK_MASK
  2021.     jz    @@0
  2022.     add    es:d[esi+eax*4],1 shl MEM_LOCK_SHIFT    ;lock it.
  2023. @@0:    popm    eax,ebx,esi,es
  2024.     ret
  2025. RawLockPage    endp
  2026.  
  2027.  
  2028. ;-------------------------------------------------------------------------------
  2029. RawClearPageLock proc near
  2030.     pushm    eax,ebx,ecx,esi,es
  2031.     mov    bx,KernalZero
  2032.     mov    es,bx
  2033.     shr    eax,12
  2034.     mov    esi,1024*4096*1022    ;base of page alias's.
  2035.     mov    ebx,MEM_LOCK_MASK shl MEM_LOCK_SHIFT
  2036.     xor    ebx,-1
  2037.     and    es:d[esi+eax*4],ebx    ;un-lock it.
  2038.     popm    eax,ebx,ecx,esi,es
  2039.     ret
  2040. RawClearPageLock endp
  2041.  
  2042.  
  2043. ;-------------------------------------------------------------------------------
  2044. ;
  2045. ;Un-lock a linear page.
  2046. ;
  2047. ;On Entry:-
  2048. ;
  2049. ;EAX    - Linear address of page to unlock.
  2050. ;
  2051. RawUnLockPage    proc    near
  2052.     call    RawPageLocked
  2053.     jz    @@9
  2054.     pushm    eax,ebx,esi,es
  2055.     mov    bx,KernalZero
  2056.     mov    es,bx
  2057.     shr    eax,12
  2058.     mov    esi,1024*4096*1022    ;base of page alias's.
  2059.     sub    es:d[esi+eax*4],1 shl MEM_LOCK_SHIFT    ;un-lock it.
  2060.     mov    eax,es:d[esi+eax*4]
  2061.     shr    eax,MEM_LOCK_SHIFT
  2062.     and    eax,MEM_LOCK_MASK
  2063.     jnz    @@NotUnLocked
  2064.     ;
  2065.     ;Update number of un-locked physical pages present.
  2066.     ;
  2067.     push    ds
  2068.     mov    ax,KernalDS
  2069.     mov    ds,ax
  2070.     assume ds:_cwRaw
  2071.     inc    NoneLockedPages
  2072.     assume ds:_cwDPMIEMU
  2073.     pop    ds
  2074.     ;
  2075. @@NotUnLocked:    popm    eax,ebx,esi,es
  2076. @@9:    ret
  2077. RawUnLockPage    endp
  2078.  
  2079.  
  2080. ;-------------------------------------------------------------------------------
  2081. ;
  2082. ;Check if page lock count is zero.
  2083. ;
  2084. ;On Entry:-
  2085. ;
  2086. ;EAX    - Linear page address.
  2087. ;
  2088. ;On Exit:-
  2089. ;
  2090. ;Zero set if page count=0.
  2091. ;
  2092. RawPageLocked    proc    near
  2093.     pushm    eax,ebx,esi,es
  2094.     mov    bx,KernalZero
  2095.     mov    es,bx
  2096.     shr    eax,12        ;get page number.
  2097.     mov    esi,1024*4096*1022    ;base of page alias's.
  2098.     mov    ebx,es:d[esi+eax*4]
  2099.     shr    ebx,MEM_LOCK_SHIFT
  2100.     and    ebx,MEM_LOCK_MASK
  2101.     popm    eax,ebx,esi,es
  2102.     ret
  2103. RawPageLocked    endp
  2104.  
  2105.  
  2106. ;-------------------------------------------------------------------------------
  2107. ;
  2108. ;Return page table entry for a particular linear address.
  2109. ;
  2110. ;On Entry:-
  2111. ;
  2112. ;EAX    - linear address.
  2113. ;
  2114. ;On Exit:-
  2115. ;
  2116. ;Carry set if page table not present else,
  2117. ;
  2118. ;EDX    - Page table entry.
  2119. ;
  2120. GetPageStatus    proc    near
  2121.     pushm    eax,ebx,esi,ds,es
  2122.     push    ax
  2123.     mov    ax,KernalDS
  2124.     mov    ds,ax
  2125.     pop    ax
  2126.     assume ds:_cwRaw
  2127.     mov    bx,KernalZero
  2128.     mov    es,bx
  2129.     push    eax
  2130.     mov    esi,PageDirLinear
  2131.     shr    eax,12        ;get page number.
  2132.     shr    eax,10        ;get dir entry number.
  2133.     test    es:d[esi+eax*4],1    ;page table present?
  2134.     pop    eax
  2135.     jz    @@8
  2136.     mov    esi,4096*1024*1023    ;base of page alias memory.
  2137.     shr    eax,12        ;get page number.
  2138.     mov    edx,es:[esi+eax*4]    ;get page details.
  2139.     clc
  2140.     jmp    @@9
  2141.     ;
  2142. @@8:    xor    edx,edx
  2143.     stc
  2144. @@9:    popm    eax,ebx,esi,ds,es
  2145.     ret
  2146.     assume ds:_cwDPMIEMU
  2147. GetPageStatus    endp
  2148.  
  2149.  
  2150. ;-------------------------------------------------------------------------------
  2151. ;
  2152. ;The Exception 14 handler. This gets a shout whenever a not present page table is encountered by
  2153. ;the processor. We check if the faulting address is within our range, passing to old handler if
  2154. ;its not, re-aranging memory if it is.
  2155. ;
  2156. VirtualFault    proc    far
  2157.     pushm    eax,ecx,edx,ds
  2158.     mov    ax,DpmiEmuDS
  2159.     mov    ds,ax
  2160.     mov    eax,ExceptionCR2
  2161.     mov    cx,KernalDS
  2162.     mov    ds,cx
  2163.     assume ds:_cwRaw
  2164.     cmp    eax,LinearBase    ;address below our memory space?
  2165.     jc    @@OldExit
  2166.     cmp    eax,LinearLimit    ;address above our memory space?
  2167.     jnc    @@OldExit
  2168.     ;
  2169.     push    eax        ;save the linear address.
  2170.     call    UnMapPhysical    ;retrieve a physical page to use.
  2171.     pop    eax
  2172.     jc    @@Disk_Error        ;This should only happen on disk errors.
  2173.     shr    eax,12
  2174.     push    LinearEntry
  2175.     mov    LinearEntry,eax    ;setup linear address we want to map.
  2176.     call    MapPhysical        ;map new page into faulting linear address space.
  2177.     pop    LinearEntry
  2178.     jc    @@Disk_Error        ;This should only happen on disk errors.
  2179.     ;
  2180.     popm    eax,ecx,edx,ds
  2181.     assume ds:nothing
  2182.     test    cs:DpmiEmuSystemFlags,1    ;check exit size.
  2183.     assume ds:_cwRaw
  2184.     jz    @@Use32Bit3
  2185.     db 66h
  2186.     retf            ;16 bit exit.
  2187. @@Use32Bit3:    ;
  2188.     retf
  2189.     ;
  2190. @@disk_error:    jmp    @@OldExit
  2191.     ;
  2192.     assume ds:nothing
  2193. @@OldExit:    popm    eax,ecx,edx,ds
  2194.     jmp    cs:f[OldExcep14]    ;32 bit chaining.
  2195. OldExcep14    df ?
  2196.     assume ds:_cwDPMIEMU
  2197. VirtualFault    endp
  2198.  
  2199.  
  2200. ;-------------------------------------------------------------------------------
  2201. ;
  2202. ;Allocate a block of DOS memory & provide a selector to access it with.
  2203. ;
  2204. RawGetDOSMemory proc near
  2205.     pushm    ecx,esi,edi,ebp,ds,es
  2206.     mov    ax,KernalDS
  2207.     mov    ds,ax
  2208.     assume ds:_cwRaw
  2209.     ;
  2210.     cmp    bx,-1        ;maximum?
  2211.     jz    @@0
  2212.     inc    ebx        ;para extra for us.
  2213. @@0:    ;
  2214.     push    ebx
  2215.     mov    edi,offset MemIntBuffer
  2216.     push    ds
  2217.     pop    es
  2218.     mov    Real_EAX[edi],4800h    ;get memory.
  2219.     mov    Real_EBX[edi],ebx    ;memory size.
  2220.     mov    Real_SS[edi],0
  2221.     mov    Real_SP[edi],0
  2222.     mov    bl,21h
  2223.     call    EMURawSimulateINT    ;allocate it.
  2224.     pop    ecx
  2225.     mov    eax,Real_EAX[edi]    ;get result.
  2226.     mov    ebx,Real_EBX[edi]
  2227.     test    Real_Flags[edi],1
  2228.     jz    @@1
  2229.     or    bx,bx        ;nothing available?
  2230.     jz    @@9
  2231.     dec    ebx        ;leave space for us!
  2232.     jmp    @@9
  2233.     ;
  2234. @@1:    ;Now try and allocate enough selectors.
  2235.     ;
  2236.     pushm    eax,ecx
  2237.     dec    cx        ;lose our para.
  2238.     shr    cx,12        ;get number of 64k chunks.
  2239.     inc    cx        ;+1 for base.
  2240.     call    RawGetDescriptors
  2241.     popm    ebx,ecx
  2242.     jc    @@8
  2243.     ;
  2244.     ;Store block size.
  2245.     ;
  2246.     push    ecx
  2247.     mov    dx,KernalZero
  2248.     mov    es,dx
  2249.     movzx    esi,bx        ;get segment address.
  2250.     shl    esi,4        ;get linear address.
  2251.     mov    es:w[esi],cx        ;store block size.
  2252.     dec    es:w[esi]        ;lose our para.
  2253.     pop    ecx
  2254.     ;
  2255.     ;Setup selectors.
  2256.     ;
  2257.     dec    cx        ;lose our para.
  2258.     inc    bx        ;/
  2259.     push    ds
  2260.     pop    es
  2261.     push    eax
  2262.     push    ebx
  2263.     ;
  2264. @@2:    pushm    eax,ebx,ecx,eax
  2265.     mov    edi,offset RawSelBuffer
  2266.     add    edi,7
  2267.     and    edi,not 7
  2268.     movzx    esi,bx
  2269.     shl    esi,4
  2270.     movzx    ecx,cx
  2271.     shl    ecx,4
  2272.     dec    ecx
  2273.     mov    al,0
  2274.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2275.     call    EMUMakeDesc
  2276.     pop    ebx
  2277.     call    RawBPutDescriptor
  2278.     popm    eax,ebx,ecx
  2279.     add    eax,8        ;next selector.
  2280.     add    ebx,1000h        ;update segment base.
  2281.     movzx    ecx,cx
  2282.     sub    ecx,1000h        ;reduce segment size.
  2283.     jns    @@2        ;keep going till all done.
  2284.     ;
  2285.     pop    eax        ;Get base segment again.
  2286.     pop    edx        ;Get base selector again.
  2287.     clc
  2288.     jmp    @@10
  2289.     ;
  2290. @@8:    ;Release memory we managed to allocate.
  2291.     ;
  2292.     mov    edi,offset MemIntBuffer
  2293.     mov    ax,KernalDS
  2294.     mov    es,ax
  2295.     mov    es:Real_EAX[edi],4900h    ;release memory.
  2296.     mov    es:Real_ES[edi],bx    ;segment.
  2297.     mov    es:Real_SS[edi],0
  2298.     mov    es:Real_SP[edi],0
  2299.     mov    bl,21h
  2300.     call    EMURawSimulateINT    ;release it.
  2301.     ;
  2302. @@9:    stc
  2303. @@10:    popm    ecx,esi,edi,ebp,ds,es
  2304.     ret
  2305.     assume ds:_cwDPMIEMU
  2306. RawGetDOSMemory endp
  2307.  
  2308.  
  2309. ;-------------------------------------------------------------------------------
  2310. ;
  2311. ;Re-size a block of DOS memory.
  2312. ;
  2313. RawResDOSMemory proc near
  2314.     pushm    ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2315.     mov    ax,KernalDS
  2316.     mov    ds,ax
  2317.     assume ds:_cwRaw
  2318.     ;
  2319.     pushm    bx,dx
  2320.     mov    bx,dx
  2321.     call    RawGetSelBase
  2322.     shl    ecx,16
  2323.     mov    cx,dx
  2324.     mov    esi,ecx
  2325.     sub    esi,16        ;back to our stuff.
  2326.     popm    bx,dx
  2327.     mov    ax,KernalZero
  2328.     mov    es,ax
  2329.     cmp    bx,es:w[esi]        ;shrinking or expanding?
  2330.     jz    @@8
  2331.     jnc    @@Expand
  2332.     ;
  2333. @@Shrink:    ;Attempt to shrink the memory block.
  2334.     ;
  2335.     pushm    ebx,edx
  2336.     inc    ebx        ;include our para.
  2337.     push    ds
  2338.     pop    es
  2339.     mov    edi,offset MemIntBuffer
  2340.     mov    eax,esi
  2341.     shr    eax,4        ;get real mode segment.
  2342.     mov    Real_EAX[edi],4a00h
  2343.     mov    Real_EBX[edi],ebx
  2344.     mov    Real_ES[edi],ax
  2345.     mov    Real_SS[edi],0
  2346.     mov    Real_SP[edi],0
  2347.     mov    bl,21h
  2348.     call    EMURawSimulateINT
  2349.     mov    eax,Real_EAX[edi]
  2350.     mov    ebx,Real_EBX[edi]
  2351.     test    Real_Flags[edi],1
  2352.     popm    ecx,edx
  2353.     jnz    @@9        ;DOS failed it!
  2354.     ;
  2355.     ;Lose any selectors that are no longer needed.
  2356.     ;
  2357.     pushm    ecx,edx
  2358.     mov    ebx,edx
  2359.     call    RawGetSelBase
  2360.     shl    ecx,16
  2361.     mov    cx,dx
  2362.     mov    esi,ecx
  2363.     sub    esi,16        ;back to our stuff.
  2364.     popm    ecx,edx
  2365.     pushm    ecx,edx
  2366.     mov    ax,KernalZero
  2367.     mov    es,ax
  2368.     mov    ax,es:w[esi]        ;get old size.
  2369.     mov    es:w[esi],cx        ;store new size.
  2370.     shr    ax,12
  2371.     inc    eax
  2372.     mov    ebx,eax        ;need existing number.
  2373.     shr    cx,12        ;get 64k chunks.
  2374.     inc    ecx        ;+ base.
  2375.     sub    ax,cx        ;get number of selectors to lose.
  2376.     jz    @@0
  2377.     popm    ecx,edx        ;need base selector again.
  2378.     pushm    ecx,edx
  2379.     shl    bx,3
  2380.     add    dx,bx        ;move to end of descriptors.
  2381.     movzx    ecx,ax
  2382.     shl    ax,3
  2383.     sub    edx,eax        ;reduce by number to lose.
  2384.     mov    ebx,edx
  2385. @@1:    pushm    ebx,ecx
  2386.     call    RawRelDescriptor    ;release this selector.
  2387.     popm    ebx,ecx
  2388.     add    ebx,8
  2389.     dec    ecx
  2390.     jnz    @@1
  2391. @@0:    popm    ecx,edx
  2392.     ;
  2393.     ;Re-set all selector base & limits to affect new last selector.
  2394.     ;
  2395.     pushm    ecx,edx
  2396.     mov    ebx,edx
  2397.     call    RawGetSelBase
  2398.     shl    ecx,16
  2399.     mov    cx,dx
  2400.     mov    ebx,ecx
  2401.     shr    ebx,4        ;get real mode segment.
  2402.     popm    ecx,edx
  2403.     mov    eax,edx
  2404. ;    shr    ax,3        ;lose TI & RPL
  2405. ;    shr    ax,3        ;get descriptor number.
  2406.     push    ds
  2407.     pop    es
  2408.     ;
  2409. @@2:    pushm    eax,ebx,ecx,eax
  2410.     mov    edi,offset RawSelBuffer
  2411.     add    edi,7
  2412.     and    edi,0fffffff8h
  2413.     movzx    esi,bx
  2414.     shl    esi,4
  2415.     movzx    ecx,cx
  2416.     shl    ecx,4
  2417.     dec    ecx
  2418.     mov    al,0
  2419.     mov    ah,DescPresent+DescPL3+DescMemory+DescRWData
  2420.     call    EMUMakeDesc
  2421.     pop    ebx
  2422.     call    RawBPutDescriptor
  2423.     popm    eax,ebx,ecx
  2424.     add    eax,8        ;next selector.
  2425.     add    ebx,1000h        ;update segment base.
  2426.     movzx    ecx,cx
  2427.     sub    ecx,1000h        ;reduce segment size.
  2428.     jns    @@2        ;keep going till all done.
  2429.     ;
  2430. @@8:    clc
  2431.     jmp    @@10
  2432.     ;
  2433. @@Expand:    ;Attempt to expand the memory block.
  2434.     ;
  2435.     mov    bx,es:w[esi]        ;return current length as maximum.
  2436.     mov    ax,8
  2437. @@9:    stc
  2438. @@10:    popm    ecx,edx,esi,edi,ebp,ds,es,fs,gs
  2439.     ret
  2440.     assume ds:_cwDPMIEMU
  2441. RawResDOSMemory endp
  2442.  
  2443.  
  2444. ;-------------------------------------------------------------------------------
  2445. ;
  2446. ;Release a block of DOS memory.
  2447. ;
  2448. RawRelDOSMemory proc near
  2449.  
  2450.     pushm    eax,ebx,ecx
  2451.     mov    ebx,edx
  2452.     and    ebx,0ffffh-7
  2453.     xor    ecx,ecx
  2454.     xor    eax,eax
  2455.     mov    ax,ds
  2456.     and    eax,not 7
  2457.     cmp    eax,ebx
  2458.     jnz    @@z0
  2459.     mov    ds,cx
  2460. @@z0:    mov    ax,es
  2461.     and    eax,not 7
  2462.     cmp    eax,ebx
  2463.     jnz    @@z1
  2464.     mov    es,cx
  2465. @@z1:    mov    ax,fs
  2466.     and    eax,not 7
  2467.     cmp    eax,ebx
  2468.     jnz    @@z2
  2469.     mov    fs,cx
  2470. @@z2:    mov    ax,gs
  2471.     and    eax,not 7
  2472.     cmp    eax,ebx
  2473.     jnz    @@z3
  2474.     mov    gs,cx
  2475. @@z3:    popm    eax,ebx,ecx
  2476.  
  2477.     pushm    ebx,ecx,edx,esi,edi,ebp
  2478.     pushm    ds,es
  2479.     mov    ax,KernalDS
  2480.     mov    ds,ax
  2481.     assume ds:_cwRaw
  2482.     ;
  2483.     ;Get segment base address.
  2484.     ;
  2485.     push    edx
  2486.     mov    ebx,edx
  2487.     call    RawGetSelBase
  2488.     shl    ecx,16
  2489.     mov    cx,dx
  2490.     mov    esi,ecx
  2491.     pop    ebx
  2492.     sub    esi,16        ;back to our stuff.
  2493.     mov    eax,esi
  2494.     shr    eax,4        ;real mode paragraph address.
  2495.     mov    dx,KernalZero
  2496.     mov    es,dx
  2497.     mov    cx,es:w[esi]        ;get block size.
  2498.     ;
  2499.     ;Release selectors.
  2500.     ;
  2501. @@0:    pushm    eax,ebx,ecx
  2502.     call    RawRelDescriptor
  2503.     popm    eax,ebx,ecx
  2504.     add    ebx,8        ;next descriptor.
  2505.     movzx    ecx,cx
  2506.     sub    ecx,1000h
  2507.     jns    @@0        ;release all selectors.
  2508.     ;
  2509.     ;Release DOS memory block.
  2510.     ;
  2511.     push    ds
  2512.     pop    es
  2513.     mov    edi,offset MemIntBuffer
  2514.     mov    Real_EAX[edi],4900h    ;release block.
  2515.     mov    Real_ES[edi],ax    ;block to release.
  2516.     mov    Real_SS[edi],0
  2517.     mov    Real_SP[edi],0
  2518.     mov    bl,21h
  2519.     call    EMURawSimulateINT    ;release it.
  2520.     mov    eax,Real_EAX[edi]
  2521.     test    Real_Flags[edi],1
  2522.     clc
  2523.     jz    @@noc
  2524.     stc
  2525. @@noc:    ;
  2526.     popm    ds,es
  2527.     popm    ebx,ecx,edx,esi,edi,ebp
  2528.     ret
  2529. RawRelDOSMemory endp
  2530.