Main Page   Class Hierarchy   Alphabetical List   Data Structures   File List   Data Fields   Globals  

_physmem.c File Reference

#include "rcs_defs.hh"
#include "_physmem.h"
#include <string.h>

Include dependency graph for _physmem.c:

Include dependency graph

Go to the source code of this file.

Functions

int read_physmem (unsigned long source, void *destination, long bytes)
int write_physmem (unsigned long destination, void *source, long bytes)
int move_physmem (unsigned long target, unsigned long source, long bcount)


Function Documentation

int read_physmem unsigned long    source,
void *    destination,
long    bytes
 

Definition at line 44 of file _physmem.c.

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);                  /* No Applicable PLATFORM  */
00133 }

int write_physmem unsigned long    destination,
void *    source,
long    bytes
 

Definition at line 136 of file _physmem.c.

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);                  /* No Applicable PLATFORM  */
00226 }

int move_physmem unsigned long    target,
unsigned long    source,
long    bcount
 

Definition at line 439 of file _physmem.c.

Referenced by read_physmem(), and write_physmem().

00440 {
00441   static initialized = 0;       /* Has the CPU been checked. */
00442   static unsigned char addrln = 0;      /* Number of addr. lines CPU drives   */
00443   unsigned char gdt[48];        /* Global Descriptor Table,see below  */
00444   unsigned char far *g_p = gdt; /* Pointer to GDT loaded into SI & ES */
00445 
00446 #ifdef __BORLANDC__
00447   union REGS r;                 /* Structure of INTEL registers       */
00448   struct SREGS s;               /* Structure of INTEL segment reg's   */
00449 #endif
00450 #ifdef _MSC_VER
00451   union _REGS r;                /* Structure of INTEL registers       */
00452   struct _SREGS s;              /* Structure of INTEL segment reg's   */
00453 #endif
00454 
00455   /* Movphy can not transfer more than (32K - 1) words */
00456   if (bcount >= 0x7ffffL)
00457     {
00458       fprintf (stderr, "\nTransfer length too large.\n");
00459       return (-1);
00460     }
00461 
00462   /*****************************************************************************
00463    **
00464    **      Identify system processor type and its addressing capability.
00465    **
00466    *****************************************************************************/
00467 
00468   if (!initialized)
00469     {
00470       /*lint -e122 */
00471 #ifdef __BORLANDC__
00472       asm
00473       {
00474 #else
00475       __asm
00476       {
00477 #endif
00478         /* 8086 CPU check */
00479         /* Bits 12-15 are always set on the 8086 processor. */
00480         pushf;                  /* Save EFLAGS.                      */
00481         pop bx;                 /* Store EFLAGS in BX                */
00482         mov ax, 0f ffh;         /*   clear bits 12-15                */
00483         and ax, bx;             /*     in EFLAGS                     */
00484         push ax;                /* Store new EFLAGS value on stack.  */
00485         popf;                   /* Replace current EFLAGS value.     */
00486         pushf;                  /* Set new EFLAGS.                   */
00487         pop ax;                 /* Store new EFLAGS in AX.           */
00488         and ax, 0f 000 h;       /* If bits 12-15 are set, then the   */
00489         cmp ax, 0f 000 h;       /*   CPU is an 8086/8088.            */
00490         mov addrln, 20;         /* Set the number of address lines   */
00491         /*   for a 8086/8088.                */
00492         je nodescriptors;
00493 
00494 
00495         /* 80286 CPU check */
00496         /* Bits 12-15 are always clear on the 80286 processor. */
00497 
00498         or bx, 0f 000 h;        /* Try to set bits 12-15             */
00499         push bx;                /*  */
00500         popf;                   /*  */
00501         pushf;                  /*  */
00502         pop ax;                 /*  */
00503         and ax, 0f 000 h;       /* If bits 12-15 are cleared, then   */
00504         /*   the CPU is an 80286             */
00505         mov addrln, 24;         /* Set the number of address lines   */
00506         /*   for a 80286.                    */
00507         jz descriptors;         /*  */
00508 
00509 
00510         /* Otherwise it is an i386 or later CPU with 32 bit addressing. */
00511         mov addrln, 32;         /* Set the number of address lines   */
00512         /* for either a i386 or later CPU's. */
00513       }
00514       /*lint +e122 */
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       /* For i286 check against A24 address limit. */
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    **      Format of descriptors
00538    **
00539    **    Offset    Size                Description
00540    **
00541    **     00h        2 Bytes        Bits 0-15 of the segment limit.
00542    **
00543    **     02h        3 Bytes        Bits 0-23 of physical address.
00544    **
00545    **     05h        1 Byte         i386 & i486 Access flags:
00546    **                               9Ah = Code segment.
00547    **                               92h = Writable data segment.
00548    **                               90h = Read only data segment.
00549    **
00550    **                               80286 Access flags:
00551    **                               9Bh = Code segment.
00552    **                               93h = Writable data segment.
00553    **                               91h = Read only data segment.
00554    **
00555    **     06h        2 Bytes        Reserved on an 80286, must be zero.
00556    **
00557    **                               A32 Processors Only.
00558    **     06h        1 Byte         Bits 0-3 are the upper 4 bits of the
00559    **                               segment limit.  Bits 4-7 are set to zero.
00560    **                               Please note that this byte is not supported
00561    **                               by Interrupt 0x15 Function 0x87.
00562    **
00563    **                               A32 Processors Only.
00564    **     07h        1 Byte         Bits 24-32 of physical address.
00565    **
00566    *****************************************************************************/
00567 
00568   memset (gdt, '\0', sizeof (gdt));     /* Zero out global descripter table  */
00569 
00570   /* Descripter 2: Source */
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;           /* A24 Access flag */
00580     }
00581   else
00582     {
00583       gdt[21] = 0x92;           /* A32 Access flag */
00584       gdt[23] = (unsigned char) (source >> 24);
00585     }
00586 
00587   /* Descripter 3: Target */
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;           /* A24 Access flag */
00597     }
00598   else
00599     {
00600       gdt[29] = 0x92;           /* A32 Access flag */
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           /* RAM parity error occurred */
00623           fprintf (stderr,
00624                    "\nData transfer failed.  A RAM parity error occurred.\n");
00625           break;
00626 
00627         case 2:
00628           /* Exception interrupt error occurred */
00629           fprintf (stderr,
00630                    "\nData transfer failed.  Exception interrupt error occurred.\n");
00631           break;
00632 
00633         case 3:
00634           /* Gating address line 20 failed during switch to protected mode */
00635           fprintf (stderr,
00636                    "\nData transfer failed.  Gate address line 20 failed.\n");
00637           break;
00638 
00639         default:
00640           /* Unknown reason-word count > 32767 */
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 }


Generated on Sun Dec 2 15:56:54 2001 for rcslib by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001