00001
00002 #include "rcs_defs.hh"
00003 #include "_physmem.h"
00004
00005 #ifndef WIN32
00006 #ifdef __MSDOS__
00007 #ifdef _WINDOWS
00008 #include <windows.h>
00009
00010 #ifndef __BORLANDC__
00011 #ifdef __cplusplus
00012 extern "C" WORD _0000h;
00013 extern "C" WORD _0040h;
00014 extern "C" WORD _A000h;
00015 extern "C" WORD _B000h;
00016 extern "C" WORD _B800h;
00017 extern "C" WORD _C000h;
00018 extern "C" WORD _D000h;
00019 extern "C" WORD _E000h;
00020 extern "C" WORD _F000h;
00021 #else
00022 extern WORD _0000h;
00023 extern WORD _0040h;
00024 extern WORD _A000h;
00025 extern WORD _B000h;
00026 extern WORD _B800h;
00027 extern WORD _C000h;
00028 extern WORD _D000h;
00029 extern WORD _E000h;
00030 extern WORD _F000h;
00031 #endif
00032 #endif
00033
00034 #else
00035 #include <stdio.h>
00036 #include <dos.h>
00037 #endif
00038 #endif
00039 #endif
00040
00041 #include <string.h>
00042
00043 int
00044 read_physmem (unsigned long source, void *destination, long bytes)
00045 {
00046
00047 #ifndef WIN32
00048 #ifdef _WINDOWS
00049
00050 LPBYTE lpDestination;
00051 LPBYTE lpSource;
00052 WORD wSelector;
00053 int i;
00054
00055 lpDestination = (LPBYTE) destination;
00056 lpSource = create_ptr_to_physmem (source, bytes, &wSelector);
00057
00058 if (NULL == lpSource || NULL == lpDestination)
00059 {
00060 return (-1);
00061 }
00062
00063
00064 for (i = 0; i < bytes; i++)
00065 {
00066 lpDestination[i] = lpSource[i];
00067 }
00068 if (wSelector)
00069 {
00070 FreeSelector (wSelector);
00071 }
00072 return (i);
00073 #else
00074 char far *ptr_to_destination;
00075 char far *ptr_to_source;
00076 unsigned long physical_source_address;
00077 unsigned long physical_destination_address;
00078 unsigned long temp_segment, temp_offset;
00079 static char two_bytes[2];
00080 char far *ptr_to_two_bytes;
00081 int i;
00082
00083 if (((unsigned long) destination) < 0x100000UL)
00084 {
00085 ptr_to_source = (char far *)
00086 ((source & 0xf) + ((source & 0xffff0L) << 16));
00087 ptr_to_destination = (char far *) destination;
00088 for (i = 0; i < bytes; i++)
00089 {
00090 ptr_to_destination[i] = ptr_to_source[i];
00091 }
00092 return (i);
00093 }
00094 else
00095 {
00096 physical_source_address = source;
00097 temp_segment = (((unsigned long) destination) & 0xffff0000L) >> 16;
00098 temp_offset = ((unsigned long) destination) & 0x0000ffffL;
00099 physical_destination_address = (temp_segment << 4) + temp_offset;
00100 if (0 == (bytes % 2))
00101 {
00102 return (move_physmem (physical_destination_address,
00103 physical_source_address, bytes));
00104 }
00105 else
00106 {
00107 if (bytes > 1)
00108 {
00109 if (-1 == move_physmem (physical_destination_address,
00110 physical_source_address, bytes))
00111 {
00112 return -1;
00113 }
00114 }
00115 ptr_to_two_bytes = (char far *) two_bytes;
00116 temp_segment =
00117 (((unsigned long) ptr_to_two_bytes) & 0xffff0000L) >> 16;
00118 temp_offset = ((unsigned long) ptr_to_two_bytes) & 0x0000ffffL;
00119 physical_source_address = source + bytes - 1;
00120 physical_destination_address = (temp_segment << 4) + temp_offset;
00121 if (-1 == move_physmem (physical_destination_address,
00122 physical_source_address, 2))
00123 {
00124 return -1;
00125 }
00126 ((char *) destination)[bytes - 1] = (char) two_bytes[0];
00127 return (0);
00128 }
00129 }
00130 #endif
00131 #endif
00132 return (-1);
00133 }
00134
00135 int
00136 write_physmem (unsigned long destination, void *source, long bytes)
00137 {
00138 #ifndef WIN32
00139 #ifdef _WINDOWS
00140
00141 LPBYTE lpDestination;
00142 LPBYTE lpSource;
00143 WORD wSelector;
00144 DWORD max_size;
00145 int i;
00146
00147 lpDestination = create_ptr_to_physmem (destination, bytes, &wSelector);
00148 lpSource = (LPBYTE) source;
00149
00150 if (NULL == lpSource || NULL == lpDestination)
00151 {
00152 return (-1);
00153 }
00154
00155
00156 for (i = 0; i < bytes; i++)
00157 {
00158 lpDestination[i] = lpSource[i];
00159 }
00160
00161 if (wSelector)
00162 {
00163 FreeSelector (wSelector);
00164 }
00165 return (i);
00166 #else
00167 char far *ptr_to_destination;
00168 char far *ptr_to_source;
00169 unsigned long physical_source_address;
00170 unsigned long physical_destination_address;
00171 unsigned long temp_segment, temp_offset;
00172 int i;
00173 static char two_bytes[2];
00174 char far *ptr_to_two_bytes;
00175
00176 if (destination < 0x100000UL)
00177 {
00178 ptr_to_source = (char far *) source;
00179 ptr_to_destination = (char far *)
00180 ((destination & 0xf) + ((destination & 0xffff0L) << 16));
00181 for (i = 0; i < bytes; i++)
00182 {
00183 ptr_to_destination[i] = ptr_to_source[i];
00184 }
00185 return (i);
00186 }
00187 else
00188 {
00189 temp_segment = (((unsigned long) source) & 0xffff0000L) >> 16;
00190 temp_offset = ((unsigned long) source) & 0x0000ffffL;
00191 physical_source_address = (temp_segment << 4) + temp_offset;
00192 physical_destination_address = destination;
00193 if (0 == (bytes % 2))
00194 {
00195 return (move_physmem (physical_destination_address,
00196 physical_source_address, bytes));
00197 }
00198 else
00199 {
00200 if (bytes > 1)
00201 {
00202 if (-1 == move_physmem (physical_destination_address,
00203 physical_source_address, bytes))
00204 {
00205 return -1;
00206 }
00207 }
00208 two_bytes[0] = ((char *) source)[bytes - 1];
00209 ptr_to_two_bytes = (char far *) two_bytes;
00210 temp_segment =
00211 (((unsigned long) ptr_to_two_bytes) & 0xffff0000L) >> 16;
00212 temp_offset = ((unsigned long) ptr_to_two_bytes) & 0x0000ffffL;
00213 physical_destination_address = destination + bytes - 1;
00214 physical_source_address = (temp_segment << 4) + temp_offset;
00215 if (-1 == move_physmem (physical_destination_address,
00216 physical_source_address, 2))
00217 {
00218 return -1;
00219 }
00220 return (0);
00221 }
00222 }
00223 #endif
00224 #endif
00225 return (-1);
00226 }
00227
00228 #ifdef WIN16
00229
00230 LPBYTE
00231 create_ptr_to_physmem (unsigned long phys_addr, int bytes,
00232 WORD FAR * ptr_to_selector)
00233 {
00234 LPBYTE lpPhysAddr;
00235 DWORD dwPhysAddrLinear;
00236 DWORD dwPhysAddrSegment;
00237 DWORD dwPhysAddrOffset;
00238 WORD wPhysAddrSelector;
00239 BOOL boolSynthesizeSelector;
00240 int max_size;
00241
00242 if (NULL != ptr_to_selector)
00243 {
00244 *ptr_to_selector = 0;
00245 }
00246
00247 #ifndef __BORLANDC__
00248 if (phys_addr < 0x100000UL)
00249 {
00250 dwPhysAddrSegment = ((phys_addr & 0xf0000UL) >> 4);
00251 dwPhysAddrOffset = (phys_addr & 0xffff);
00252 boolSynthesizeSelector = FALSE;
00253 max_size = 0x10000UL - dwPhysAddrOffset;
00254 switch (dwPhysAddrSegment)
00255 {
00256 case 0:
00257 if (dwPhysAddrOffset < 0x400)
00258 {
00259 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_0000h);
00260 }
00261 else
00262 {
00263 dwPhysAddrOffset -= 0x400;
00264 max_size += 0x400;
00265 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_0040h);
00266 }
00267 break;
00268
00269 case 0xA000:
00270 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_A000h);
00271 break;
00272 case 0xB000:
00273 if (dwPhysAddrOffset < 0x8000)
00274 {
00275 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_B000h);
00276 }
00277 else
00278 {
00279 dwPhysAddrOffset -= 0x8000;
00280 max_size += 0x8000;
00281 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_B800h);
00282 }
00283 break;
00284 case 0xC000:
00285 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_C000h);
00286 break;
00287 case 0xD000:
00288 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_D000h);
00289 break;
00290 case 0xE000:
00291 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_E000h);
00292 break;
00293 case 0xF000:
00294 lpPhysAddr = (LPBYTE) MAKELONG (dwPhysAddrOffset, &_F000h);
00295 break;
00296 default:
00297 boolSynthesizeSelector = TRUE;
00298 dwPhysAddrLinear =
00299 ((DWORD) dwPhysAddrSegment << 4L) + dwPhysAddrOffset;
00300 break;
00301 }
00302 }
00303 else
00304 #endif
00305 {
00306 if (0x100000 < bytes)
00307 {
00308 return (NULL);
00309 }
00310 max_size = bytes;
00311 dwPhysAddrLinear = MapPhysicalToLinear (phys_addr, bytes);
00312 boolSynthesizeSelector = TRUE;
00313 }
00314
00315 if (max_size < bytes)
00316 {
00317 return (NULL);
00318 }
00319
00320 if (boolSynthesizeSelector)
00321 {
00322 wPhysAddrSelector = SynthSelector (dwPhysAddrLinear, max_size);
00323 if (NULL != ptr_to_selector)
00324 {
00325 *ptr_to_selector = wPhysAddrSelector;
00326 }
00327 lpPhysAddr = GetSelectorPointer (wPhysAddrSelector);
00328 }
00329 return (lpPhysAddr);
00330 }
00331
00332
00333
00334
00335
00336
00337 DWORD
00338 MapPhysicalToLinear (DWORD dwPhysical, DWORD dwLength)
00339 {
00340 DWORD dwLinear = 0L;
00341
00342
00343 if (dwPhysical >= 0x100000L)
00344 {
00345 _asm
00346 {
00347 push di push si mov bx, WORD PTR[dwPhysical + 2]
00348 mov cx, WORD PTR[dwPhysical]
00349 mov si, WORD PTR[dwLength + 2]
00350 mov di, WORD PTR[dwLength] mov ax, 800 h int 31 h
00351 jc short error_return mov dx, bx mov ax, cx jmp short fine_return}
00352 error_return:_asm
00353 {
00354 xor ax, ax mov dx, ax}
00355 fine_return:_asm
00356 {
00357 mov WORD PTR[dwLinear + 2], dx
00358 mov WORD PTR[dwLinear], ax pop si pop di}
00359 }
00360 return dwLinear;
00361 }
00362
00363
00364
00365
00366 WORD
00367 SynthSelector (DWORD dwLinearAddress, DWORD dwLength)
00368 {
00369 WORD tempSelector, selector = NULL;
00370 WORD data_segment;
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383 #ifdef __BORLANDC__
00384 _asm
00385 {
00386 push ds pop ax mov data_segment, ax}
00387 tempSelector = AllocSelector (data_segment);
00388 #else
00389 _asm
00390 {
00391 push ds call AllocSelector mov tempSelector, ax}
00392 #endif
00393 if (tempSelector)
00394 {
00395 SetSelectorBase (tempSelector, dwLinearAddress);
00396 SetSelectorLimit (tempSelector, dwLength);
00397
00398 selector = AllocSelector (tempSelector);
00399
00400 SetSelectorLimit (tempSelector, 100L);
00401 FreeSelector (tempSelector);
00402 }
00403 return selector;
00404 }
00405
00406
00407
00408
00409
00410 LPSTR
00411 GetSelectorPointer (WORD selector)
00412 {
00413 return (LPSTR) MAKELONG (0, selector);
00414 }
00415
00416 #else
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 int
00439 move_physmem (unsigned long target, unsigned long source, long bcount)
00440 {
00441 static initialized = 0;
00442 static unsigned char addrln = 0;
00443 unsigned char gdt[48];
00444 unsigned char far *g_p = gdt;
00445
00446 #ifdef __BORLANDC__
00447 union REGS r;
00448 struct SREGS s;
00449 #endif
00450 #ifdef _MSC_VER
00451 union _REGS r;
00452 struct _SREGS s;
00453 #endif
00454
00455
00456 if (bcount >= 0x7ffffL)
00457 {
00458 fprintf (stderr, "\nTransfer length too large.\n");
00459 return (-1);
00460 }
00461
00462
00463
00464
00465
00466
00467
00468 if (!initialized)
00469 {
00470
00471 #ifdef __BORLANDC__
00472 asm
00473 {
00474 #else
00475 __asm
00476 {
00477 #endif
00478
00479
00480 pushf;
00481 pop bx;
00482 mov ax, 0f ffh;
00483 and ax, bx;
00484 push ax;
00485 popf;
00486 pushf;
00487 pop ax;
00488 and ax, 0f 000 h;
00489 cmp ax, 0f 000 h;
00490 mov addrln, 20;
00491
00492 je nodescriptors;
00493
00494
00495
00496
00497
00498 or bx, 0f 000 h;
00499 push bx;
00500 popf;
00501 pushf;
00502 pop ax;
00503 and ax, 0f 000 h;
00504
00505 mov addrln, 24;
00506
00507 jz descriptors;
00508
00509
00510
00511 mov addrln, 32;
00512
00513 }
00514
00515
00516
00517 nodescriptors:
00518 if (addrln < 24)
00519 {
00520 fprintf (stderr,
00521 "\nThis system does not support protected mode.\n");
00522 return (-1);
00523 }
00524
00525
00526 descriptors:
00527 if ((addrln < 32) && (source >= (1UL << 24) || target >= (1UL << 24)))
00528 {
00529 fprintf (stderr, "\nA24 Address out of bounds.\n");
00530 return (-1);
00531 }
00532 initialized = 1;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 memset (gdt, '\0', sizeof (gdt));
00569
00570
00571 gdt[16] = (unsigned char) bcount;
00572 gdt[17] = (unsigned char) (bcount >> 8);
00573 gdt[18] = (unsigned char) source;
00574 gdt[19] = (unsigned char) (source >> 8);
00575 gdt[20] = (unsigned char) (source >> 16);
00576
00577 if (addrln < 32)
00578 {
00579 gdt[21] = 0x93;
00580 }
00581 else
00582 {
00583 gdt[21] = 0x92;
00584 gdt[23] = (unsigned char) (source >> 24);
00585 }
00586
00587
00588 gdt[24] = (unsigned char) bcount;
00589 gdt[25] = (unsigned char) (bcount >> 8);
00590 gdt[26] = (unsigned char) target;
00591 gdt[27] = (unsigned char) (target >> 8);
00592 gdt[28] = (unsigned char) (target >> 16);
00593
00594 if (addrln < 32)
00595 {
00596 gdt[29] = 0x93;
00597 }
00598 else
00599 {
00600 gdt[29] = 0x92;
00601 gdt[31] = (unsigned char) (target >> 24);
00602 }
00603
00604 r.h.ah = 0x87;
00605 r.x.cx = (int) (bcount / 2);
00606 s.es = (((unsigned long) g_p) & 0xffff0000L) >> 16;
00607 r.x.si = ((unsigned long) g_p) & 0x0000ffffL;
00608
00609 #ifdef __BORLANDC__
00610 int86x (0x15, &r, &r, &s);
00611 #endif
00612
00613 #ifdef _MSC_VER
00614 (void) _int86x (0x15, &r, &r, &s);
00615 #endif
00616
00617 if (r.h.ah)
00618 {
00619 switch (r.h.ah)
00620 {
00621 case 1:
00622
00623 fprintf (stderr,
00624 "\nData transfer failed. A RAM parity error occurred.\n");
00625 break;
00626
00627 case 2:
00628
00629 fprintf (stderr,
00630 "\nData transfer failed. Exception interrupt error occurred.\n");
00631 break;
00632
00633 case 3:
00634
00635 fprintf (stderr,
00636 "\nData transfer failed. Gate address line 20 failed.\n");
00637 break;
00638
00639 default:
00640
00641 fprintf (stderr,
00642 "\nData transfer failed. Reason unknown, possibly word count > 32767.\n");
00643 break;
00644 }
00645 return (-1);
00646 }
00647
00648
00649 return (bcount);
00650 }
00651
00652 #endif
00653
00654
00655
00656
00657
00658
00659 #if 0
00660
00661 From rippey @ cme.nist.gov Wed Jun 5 09:46:29 1996
00662 Date:5 Jun 1996 09:43:35 U
00663 From:"Bill Rippey" < rippey @ cme.nist.gov >
00664 Subject:Net info on physical memory
00665 To:"Will Shackleford" < shackle @ isdmail >
00666 Content - Length:14745
00667 Subject:Time:9:43 AM
00668 OFFICE MEMO Net info on physical memory Date:6 / 5 / 96
00669 Here is the bulletin I grabbed off the network.
00670 -- ---ftp.microsoft.com / developr / win_dk / ddk / 105 / 6 / 43
00671 DOCUMENT:Q105643 05 - JAN - 1995[win16sdk]
00672 TITLE:Accessing Physical Memory in Windows 3.0 and 3.1
00673 PRODUCT:Microsoft Windows Software Development Kit
00674 PROD / VER:3.00 3.10
00675 OPER / SYS:WINDOWS
00676 KEYWORDS:kbprg-- --
00677 ------------------------------------------------------------------The
00678 information in this article applies to:-Microsoft Windows Software
00679 Development
00680 Kit (SDK) for Windows,
00681 versions 3.0 and 3.1-- --
00682 ------------------------------------------------------------------SUMMARY ==
00683 == == =
00684 Some applications need to access memory at a particular physical address
00685 fixed in the address space of the microprocessor.
00686 Such applications typically interact directly with memory -
00687 mapped hardware device interface cards,
00688 or may need to read the computer CMOS settings.
00689
00690 This article outlines two methods to access physical memory in Windows
00691 protected mode (standard mode or 386 enhanced mode)
00692 .MORE INFORMATION == == == == == == == ==
00693 Method 1:Exported Selectors (Preferred)-- --
00694 ------------------------------------The Windows 3.0 and 3.1 Kernels export
00695 several selectors that should be used by applications that require access
00696 to physical memory located below the 1 megabyte (MB) boundary.
00697 The exported selectors are:__0000h, __0040h, __A000h, __B000h, __B800h,
00698 __C000h, __D000h, __E000h, and __F000h To use one of these selectors,
00699 place it onto a segment register and access the memory or create a long
00700 pointer.Here are examples using the Microsoft Macro Assembler (MASM)
00701 and Microsoft C:In ASM:extern __0040h ... mov ax, __0040h mov es,
00702 ax In C:extern WORD _0040h;
00703 LPSTR lpBIOSDataArea;
00704 ...
00705
00706 lpBIOSDataArea = (LPSTR) MAKELONG (0, &_0040h);
00707
00708 In
00709 C++:extern
00710 "C" WORD _0040h;
00711 LPSTR
00712 lpBIOSDataArea;
00713 ...
00714
00715 lpBIOSDataArea = (LPSTR) MAKELONG (0, &_0040h);
00716
00717 Each of these data selectors is limited to
00718 accessing 64 kilobytes (K).An attempt to read or write to data beyond the
00719 limit causes a general protection (GP) fault (evidenced by an unrecoverable
00720 application error-- UAE)
00721 in protected
00722 mode.Performing segment arithmetic with
00723 these selectors also causes a GP fault.Finally,
00724 do
00725 not free these
00726 selectors once they are no longer needed.Method 1 is always
00727 recommended and should be used unless the exported selectors
00728 do
00729 not provide access to the necessary area of physical memory.Method
00730 2:Selector Synthesis-- --
00731 ------------------------Selector synthesis should be used when an
00732 application needs to access physical memory that is not addressable
00733 with the selectors exported from the Windows Kernel.
00734 This method involves allocating a new selector and initializing the
00735 associated descriptor with the appropriate values.The functions to
00736 do
00737 this are provided through the Windows Kernel and the MS -
00738 DOS Protected Mode Interface (DPMI) server (which is a part of
00739 Windows).
00740 The required functions include the following:Function
00741 Description-- --
00742 ---------------Map Physical To Linear (DPMI:Interrupt 31 h, AX =
00743 0800 h) Maps a 32 -
00744 bit physical address to a 32 -
00745 bit linear address.In 386 enhanced mode this function is required
00746 because because linear addresses are different from physical
00747 addresses and the selector functions can work only with linear
00748 addresses.In standard mode,
00749 this function is not required because linear addresses are the
00750 same as physical addresses.AllocSelector (WORD
00751 wSelector) (Kernel) Allocates a new selector
00752 or array of tiled selectors and copies the attributes of wSelector to
00753 the new selector (s).
00754 If the limit of wSelector is less than or equal to 64 K,
00755 then only one selector is allocated.
00756 If the limit of wSelector is larger than 64 K,
00757 an array of tiled selectors is allocated such that each selector points
00758 to one 64 K portion of the limit of wSelector.FreeSelector (WORD
00759 wSelector)
00760 (Kernel) Frees either a single
00761 selector or an array of tiled selectors depending on the limit of
00762 wSelector.
00763 Frees one selector for each 64 K portion of the limit of wSelector.
00764 The selector,
00765 or array of tiled selectors being freed must have been allocated
00766 previously by AllocSelector.Furthermore,
00767 the limit of wSelector must be the same as the selector used as a
00768 parameter to the call to AllocSelector.SetSelectorBase (WORD wSelector,
00769 DWORD dwBase)
00770 (Kernel) Stores the starting
00771 linear
00772 address of the desired region in the
00773 descriptor of wSelector.SetSelectorLimit (WORD wSelector,
00774 DWORD dwLimit) (Kernel) Stores the length of the
00775 desired region in the descriptor of wSelector.GetSelectorLimit (WORD
00776 wSelector)
00777 (Kernel) Retrieves the length of
00778 the region pointed to by wSelector.
00779 This length comes from wSelector descriptor.Caveats:1. These routines
00780 do
00781 not inform the Windows memory manager that a particular block of memory
00782 is in use.
00783
00784 It is the responsibility of the caller to ensure that the area of
00785 memory will not be accessed or freed by some other process in the
00786 system.2. Synthesized selectors that alias a memory object allocated
00787 by Windows will not be updated if the memory object is moved.
00788 To make sure that the memory object will not be moved,
00789 call GlobalFix () on it before synthesizing a selector that aliases
00790 it.Note that if the synthesized selector points to memory provided by a
00791 physical device, there is no need to call GlobalFix ()
00792 because the device memory was not allocated by Windows.3. Allocating
00793 large numbers of selectors is discouraged because selectors are a
00794 limited resource.4. Allocating a selector does not actually allocate
00795 any memory:it merely creates a pointer that can be used to access
00796 existing memory (that was previously allocated or is provided by a
00797 memory -
00798 mapped hardware device).
00799 Do not confuse allocating a selector with allocating memory.The
00800 following code fragment has been written using the inline assembly
00801 feature of the Microsoft C and C++ compilers.
00802 This code illustrates the technique of selector synthesis.Sample
00803 Code-- -- -------DWORD MapPhysicalToLinear (DWORD, DWORD);
00804 WORD
00805 SynthSelector (DWORD, DWORD);
00806 LPSTR
00807 GetSelectorPointer (WORD);
00808
00809
00810
00811
00812
00813 int FAR PASCAL
00814 SetSelectorBase (WORD, DWORD);
00815 int FAR PASCAL
00816 SetSelectorLimit (WORD, DWORD);
00817 DWORD FAR PASCAL
00818 GetSelectorLimit (WORD);
00819
00820 LPSTR
00821 lpPhys;
00822 DWORD
00823 dwPhysical, dwLinear, dwLength;
00824 WORD
00825 wSelector;
00826 WORD
00827 segment, offset;
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844 dwLinear = ((DWORD) segment << 4L) + offset;
00845
00846
00847
00848
00849
00850
00851
00852 dwPhysical = 0xC00000;
00853
00854
00855 dwLinear = MapPhysicalToLinear (dwPhysical, dwLength);
00856 if (!dwLinear)
00857 {
00858
00859 }
00860
00861
00862
00863
00864
00865
00866 wSelector = SynthSelector (dwLinear, dwLength);
00867 lpPhys = GetSelectorPointer (wSelector);
00868
00869
00870
00871
00872
00873
00874
00875
00876 FreeSelector (wSelector);
00877
00878
00879
00880
00881
00882
00883
00884
00885 DWORD MapPhysicalToLinear (DWORD dwPhysical, DWORD dwLength)
00886 {
00887 DWORD dwLinear = 0L;
00888
00889
00890 if (dwPhysical >= 0x100000L)
00891 {
00892 _asm
00893 {
00894 push di push si mov bx, WORD PTR[dwPhysical + 2];
00895 Load arguments.mov cx, WORD PTR[dwPhysical]
00896 mov si, WORD PTR[dwLength + 2]
00897 mov di, WORD PTR[dwLength] mov ax, 800 h int 31 h;
00898 Issue DPMI call.jc short error_return
00899 mov dx, bx
00900 mov ax, cx
00901 jmp short fine_return
00902 error_return:xor ax, ax
00903 mov dx, ax fine_return:mov WORD PTR[dwLinear + 2], dx;
00904 Return value.mov WORD PTR[dwLinear], ax pop si pop di}
00905 }
00906 return dwLinear;
00907 }
00908
00909
00910
00911
00912 WORD SynthSelector (DWORD dwLinearAddress, DWORD dwLength)
00913 {
00914 WORD tempSelector, selector = NULL;
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 _asm
00928 {
00929 push ds call AllocSelector mov tempSelector, ax}
00930
00931 if (tempSelector)
00932 {
00933 SetSelectorBase (tempSelector, dwLinearAddress);
00934 SetSelectorLimit (tempSelector, dwLength);
00935
00936 selector = AllocSelector (tempSelector);
00937
00938 SetSelectorLimit (tempSelector, 100L);
00939 FreeSelector (tempSelector);
00940 }
00941 return selector;
00942 }
00943
00944
00945
00946
00947
00948 LPSTR GetSelectorPointer (WORD selector)
00949 {
00950 return (LPSTR) MAKELONG (0, selector);
00951 }
00952
00953 Additional reference words:3.00 3.10 Q80591
00954 KBCategory:kbprg
00955 KBSubcategory:KrMm
00956 == == == == == == == == == == == == == == == == == == == == == == == ==
00957 == == == == == == == == == == == == == == =
00958 THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED
00959 "AS IS" WITHOUT WARRANTY OF ANY KIND.
00960 MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED,
00961 INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00962 PARTICULAR PURPOSE.
00963 IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
00964 ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
00965 CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES,
00966 EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
00967 POSSIBILITY OF SUCH DAMAGES.
00968
00969 SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR
00970 CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT
00971 APPLY.Copyright Microsoft Corporation 1995.
00972 #endif