[comp.windows.ms] Using DPMI and XMS to get BIG memory blocks

brent@well.sf.ca.us (Brent Southard) (12/22/90)

I've been successful so far in my less adventurous forays into the DPMI forest
(real mode interrupt simulation, real mode far calls, etc.), but now I'm
finding my paths blocked by a wall of confusing, if not missing, documentation.

I'm working on our Windows application, which does a considerable amount of
hardware fiddling, and trying to expand it's memory handling capabilities.  I
need to work with large (1-5 megabyte) blocks of memory containing scanned
image data.  Because of earlier limitations of DOS and Windows, I had limited
our data handling to EMS memory allocations.  With the advent of Windows 3.0,
XMS, and DPMI, I should be able to work with large contiguous memory blocks
now, without the overhead of EMS.

Now, you may be thinking I don't really need truly contiguous memory blocks.
Not so.  You see, I am working with some scanner hardware which wants to
transfer, via DMA, (possibly) megabytes of data to an extended memory address.
The transfer can not be broken up by any time span longer than it takes to
reset the DMA hardware for the next transfer.  Therefore, any memory block I
allocate must meet the following criteria, at least at the time of DMA transfer:

   1.  The actual, physical, real, hardwired address of the memory must be
       beyond the 1 megabyte boundary, at least when locked.
   2.  The memory must be physically contiguous, or DMA will really have fun
       with the system.
   3.  The memory must be page locked (in enhanced mode).

Well, it looked to me like a perfect application for XMS memory.  Well, I put
together a little test winapp to play with XMS EMBs (extended memory blocks).
After determining that XMS is installed, and retrieving the control function's
address (all via DPMI in enhanced mode), I decided to try to allocate the
biggest block available.  Calling the Query Free Extended Memory function (08h)
revealed that I had a total of 4096K (4MB) XMS memory with the largest block
free 2048K (2MB).  This was a little surprising since I have a 4 megabyte (i.e.
3MB extended) system, so I'm guessing that the XMM is including virtual (disk)
memory in its numbers.  Well, I tried to allocate that 2MB block using the
Allocate Extended Memory Block function (09h), and got back an error, BL==A0,
which implies that ALL extended memory is allocated.  Huh?  I tried halving my
request, and it succeeded.  What gives?

Now, let's say I didn't have the afore mentioned allocation problem.  I'm still
a little worried that XMS may allocate virtual memory -- what happens when I
need to page lock?

What are my alternatives?  If I use GlobalAlloc() to allocate a big block of
memory, will it be guaranteed to be contiguous, page lockable, and in the
extended memory address region?  If so, which functions do I use to get the
true physical (hardware) address to pass to the scanner driver (for DMA)?

Now that the questions are dealing more with DPMI than XMS, could someone
clarify the terms 'physical' versus 'linear' as used in the DPMI spec?  How is
each type addressed, i.e. selector:offset or 32-bit address?  My guess is that
the DMA comtroller needs the 'linear' address...

I'd appreciate any experienced answers I can get, since I'm in the middle of
some code changes, and I can't wait for OnLine or the next issue of MSJ,
whichever comes first.  I will consider posting a summary of my knowledge if
enough is gained.


Thanks,

Brent Southard

ImageTech Corp.
(313) 353-7900
-- 
brent southard  (313) 656-8349   |   usenet:  ...!well!brent
ImageTech Corp  (313) 362-3141   |   

"When frog licking is outlawed, only outlaws will lick frogs."

mojo@netcom.UUCP (Morris Jones) (12/22/90)

brent@well.sf.ca.us (Brent Southard) writes:
>                        Well, I tried to allocate that 2MB block using the
>Allocate Extended Memory Block function (09h), and got back an error, BL==A0,
>which implies that ALL extended memory is allocated.  Huh?  I tried halving my
>request, and it succeeded.  What gives?

Brent, it's possible that Windows won't allocate more than a meg of 16-bit
memory because of limits involving 16-bit pointer arithmetic and selectors.
So here's an alternative:

Look at Appendix E of the SDK.  Use the 32-bit memory allocation functions.
I have succesfully allocated much larger chunks of memory using the
Global32Alloc() function.  You can refer to the memory with 16-bit pointers
if you need to by getting a 16-bit alias with Global16PointerAlloc().

As far as insuring that the memory is contiguous and page locked ...

... I'm afraid you're on your own.  But if you find a way to do it, I'd
certainly like to hear about it.

Mojo
Caere Corp.
netcom!mojo@apple.com
-- 
mojo@netcom.UUCP          Site Coordinating Instructor, San Jose South
Morris "Mojo" Jones       Skilled Motorcycling And Rider Training (S.M.A.R.T.)
Campbell, CA              800-675-5559 ... 800-CC-RIDER ...  408-423-2212
AA4KB @ N6LDL.#NOCAL.CA.USA.NA / aa4kb.ampr.org / netcom!mojo@apple.com