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: <9605020928 DOT AA24093 AT axp03> 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: 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 #include #include #include #include /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include /* 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