www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1996/05/03/12:37:09

Xref: news2.mv.net comp.os.msdos.djgpp:3389
Newsgroups: comp.os.msdos.djgpp
From: sam AT cs DOT vu DOT nl (Megens SA)
Subject: Re: Pointers -> memory how ?
Nntp-Posting-Host: punter.cs.vu.nl
References: <Dqr73L DOT Hz1 AT nyongwa DOT montreal DOT qc DOT ca> <9605020928 DOT AA24093 AT axp03> <Pine DOT LNX DOT 3 DOT 91 DOT 960502130058 DOT 11114A-100000 AT noether DOT nyongwa DOT montreal DOT qc DOT ca>
Sender: news AT cs DOT vu DOT nl
Organization: Fac. Wiskunde & Informatica, VU, Amsterdam
Date: Fri, 3 May 1996 08:44:56 GMT
Message-ID: <DqtMyx.Cop.0.-s@cs.vu.nl>
Lines: 198
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp

dunder (dunder AT nyongwa DOT montreal DOT qc DOT ca) wrote:


: > Although this could be done, if you *absolutely* want it (look up the
: > 'nearptr' method in libc.inf and the FAQ list), it will cost you too
: > much to be really useful.  The reason is that by doing this, you won't
: > necessarily drop out of protected mode (which you generally *can't* in
: > DJGPP), but you loose almost all the *protection* that way.  

: I know, that's why I wanted another method ...

Another method is to use dpmi to map physical memory into your own
address-space. This is something I recently figured out and it's great. BUT...
it only works if cwsdpmi is providing the dpmi-services, it won't work with
Windows 95, it won't work with OS/2 (I haven't tested it with other dpmi
hosts).

The following example will try to map the video memory at a0000 in it's own
address-space, and fill a mode13 screen with all colors.

The map_physical_memory is copied from the library-sources, because I
couldn't get __dpmi_map_physical_memory to work (it wouldn't link, got 
undefined symbol; if someone knows how to fix this, please tell me).

By the way, this is an edited non-tested version of the test-program I used,
so I wouldn't be surpised if it now contained some small typo's (I'm sorry for
that, but I don't have access to DJGPP right now).

#include <dos.h>
#include <go32.h>
#include <dpmi.h>
#include <errno.h>
#include <string.h>

/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <crt0.h>
#include <stddef.h>


/* Maps the specified number of bytes at a given address into our
 * address space.  All arguments must be page-aligned.  Returns 0 on
 * success, -1 on failure.  This routine isn't as fast as it could be,
 * but it shouldn't get called all that often.
 */
int map_physical_memory (void *_our_addr, unsigned long _num_bytes,
                         unsigned long _phys_addr)
{
  unsigned long p, end;

  /* Make sure all arguments are page aligned. */
  if (((unsigned long) _our_addr & 0xfff )
      || (_phys_addr & 0xfff)
      || (_num_bytes & 0xfff))
    {
      errno = EINVAL;
      printf("pages not aligned\n");
      return -1;
    }

  /* Loop through the memory range, identify individual handles
   * that intersect the range, and map the appropriate memory
   * within each handle.
   */
  for (p = (unsigned long) _our_addr, end = p + _num_bytes; p < end; )
    {
      const __djgpp_sbrk_handle *d;
      unsigned long handle_end_addr;
      __dpmi_meminfo meminfo;

      /* Find the memory handle corresponding to the first byte. */
      d = __djgpp_memory_handle (p);
      if (d == NULL)
      {
        printf("d = __djgpp_memory_handler = NULL\n");
        goto fail;
      }

      /* Find the last byte in the range that's also in the same
       * memory handle as our current starting byte.  We start with
       * the farthest away address because it will usually be in the
       * same memory handle, and we don't need to check any
       * intermediate addresses once we know the far away address is
       * in the same handle.
       */
      for (handle_end_addr = end - 0x1000;
	   handle_end_addr > p;
	   handle_end_addr -= 0x1000)
	{
	  const __djgpp_sbrk_handle *d2;

	  /* Find the memory handle corresponding to this test byte. */
	  d2 = __djgpp_memory_handle (handle_end_addr);
	  if (d2 == NULL)
      {
        printf("d2 = __djgpp_memory_handler = NULL\n");
	    goto fail;
      }

	  /* Is this test byte in the same handle as the first byte? */
	  if (d2->handle == d->handle)
	    break;
	}
      handle_end_addr += 0x1000;

      /* Map the appropriate physical addresses into this handle. */
      meminfo.handle  = d->handle;
      meminfo.size    = (handle_end_addr - p) / 0x1000;  /* # pages */
      meminfo.address = p - d->address;

      if (__dpmi_map_device_in_memory_block (&meminfo,
					     (_phys_addr
					      + (p - (unsigned) _our_addr))))
      {
        printf("__dpmi_map_device_in_memory_block failed\n");
        goto fail;
      }

      /* Move on to the next memory handle. */
      p = handle_end_addr;
    }

  /* success! */
  printf("succes!\n");
  return 0;

 fail:
  errno = EACCES;
  return -1;
}

void mode13_enter()
{
/* set VGA-mode 13 */
    union REGS in, out;

    in.x.ax = 0x0013;
    int86(0x10, &in, &out);
}

void mode13_leave()
{
/* set text-mode */
    union REGS in, out;

    in.x.ax = 0x0003;
    int86(0x10, &in, &out);
}

char* ptr;

int main()
{
    __dpmi_version_ret dvr;
    int i;
    int mapped = 0;

    __dpmi_get_version(&dvr);
    printf("major = %x, minor = %x\n", (int)dvr.major, (int)dvr.minor);

/* allocate a dummy-page, so we've got a pointer to somewhere in our
   address-space */
    ptr = malloc(65536);
    if (map_physical_memory(ptr, 65536, 0xa0000) == -1)
        printf("couldn't map physical memory (%s)\n", strerror(errno));
    else
    {
        printf("physical memory mapped\n");
        mapped = 1;
    }

    getchar();

    if (mapped)
    {
        mode13_enter();
        for (i = 0; i < 320*200; i++)
        {
            ptr[i] = i & 0xff;
        }
        getchar();
        mode13_leave();
    }

/* I guess it would be nicer to unmap the physical memory and to release
   the dummy-page :) */
    return 0;
}

Of course, this should also work with text-memory, just be sure to change the
'0xa0000' to '0xb8000' and always map a multiple of a complete page (4K, if
I'm not mistaking).

I hope this is of some use to people, please let me know if you got it to
work, I'm very interested to know. :)

DGreetings,

SAM

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019