Mail Archives: djgpp/2006/04/19/21:17:02
"Eric" <NoOne AT invalid DOT com> wrote in message
news:A8adnbpWz9FuPdjZnZ2dnUVZ_sednZ2d AT comcast DOT com...
> Can anyone point me to some sample code that shows how to allocate a dos
> buffer (below 1 meg). I want to understand how to do things this way and
> not rely on tb.
> For instance:
> allocate buffer below 1 meg - size -32k
> fill buffer with data and read it back
> store actual buffer address in say regs.r.ax and regs.r.bx
> free buffer
>
> I looked at __dpmi_allocate_dos_memory but it gets you a selector and I
dont
> know what to do to convert that to a pointer
>
Now, the memory below 1Mb is physically mapped per the DPMI specification,
but a buffer in that region still needs to be allocated. Unfortunately, DOS
memory must be allocated through the DPMI host and not directly through DOS
itself. It handles some other issues and allocates from DOS. Therefore, to
allocate DOS memory, you must use either one of these:
1) __dpmi_allocate_dos_memory
2) _go32_dpmi_allocate_dos_memory
Now, _go32_dpmi_allocate_dos_memory() uses segments and offsets through a
structure, like you want. However, I'm not fond of the _go32_xxx functions
because the set of functions is incomplete. So, you end up spending all
your time reformating segments, offsets, etc. to switch between the _go32
functions and _dpmi functions...
Anyway, I've written two examples. They both compile cleanly, but haven't
been thoroughly tested (i.e., possible bugs...). If there are any bugs,
you'll need to sort them out yourself.
Method 1)
----
#include <dpmi.h>
#include <go32.h>
#include <sys/farptr.h>
#define BUFF 32768
int main(void)
{
unsigned long base;
/* unsigned short segment,offset; */
int selector;
char buf[BUFF];
/* base is the physical address of the low mem buffer */
/* selector is used for virtual addressing, i.e., within application space
*/
__dpmi_allocate_dos_memory((BUFF+15)>>4,&selector);
__dpmi_get_segment_base_address(selector,&base);
#if 0
/* this is how to calculate segment & offset, if needed */
segment=(unsigned long)base>>4;
offset=(unsigned long)base&0x0F;
#endif
dosmemput(buf, BUFF, base); /* copy to low mem */
/* something done to low mem buffer: DOS call, farpoke */
_farpokeb(selector,12,0x20); /* set low mem buf[12] to 0x20 */
dosmemget(base, BUFF, buf); /* copy from low mem */
__dpmi_free_dos_memory(selector);
return(0);
}
Method 2)
----
#include <string.h>
#include <dpmi.h>
#include <go32.h>
#include <sys/farptr.h>
#include <sys/nearptr.h>
#define BUFF 32768
int main(void)
{
unsigned long base,CS_base;
/* unsigned short segment,offset; */
int selector;
unsigned char buf[BUFF];
unsigned char *bufl;
/* base is the physical address of the low mem buffer */
/* selector is used for virtual addressing, i.e., within application space
*/
__dpmi_allocate_dos_memory((BUFF+15)>>4,&selector);
__dpmi_get_segment_base_address(selector,&base);
/* get the physical starting address of the code segment */
/* and enable full address range */
__dpmi_get_segment_base_address(_my_cs(),&CS_base);
__djgpp_nearptr_enable();
#if 0
for physical-to-virtual addressing use: (e.g., screen=0xB8000)
#ifdef __DJGPP__
"variable" -=CS_base;
#endif
for virtual-to-physical addressing use: (e.g., lgdt,lidt,etc.)
#ifdef __DJGPP__
"variable" +=CS_base;
#endif
#endif
bufl=(unsigned char *)base; /* create a pointer to low mem */
bufl+=CS_base; /* convert virtual to physical address */
#if 0
/* this is how to calculate segment & offset, if needed */
segment=(unsigned long)bufl>>4;
offset=(unsigned long)bufl&0x0F;
#endif
memcpy(bufl,buf,BUFF); /* copy to low mem */
/* something done to low mem buffer: DOS call, farpoke */
_farpokeb(selector,12,0x20); /* set low mem buf[12] to 0x20 */
memcpy(buf,bufl,BUFF); /* copy from low mem */
__dpmi_free_dos_memory(selector);
return(0);
}
HTH,
Rod Pemberton
- Raw text -