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

physmem.cc

Go to the documentation of this file.
00001 /***********************************************************************
00002 * File: physmem.cc
00003 * Purpose: Provides the member functions for the PHYSMEM_HANDLE class. This is
00004 * a C++ interface for portable access to physical memory.
00005 * NOTES:
00006 *  On some platforms accessing a block of physical memory is a simple as
00007 * intitializing a pointer and then dereferencing it, but accessing specific
00008 * sections of extended memory under DOS or Windows requires changing the
00009 * descriptor tables and therefore circumventing protected mode security.
00010 * Other platforms require the use of mmap() on memory device files to choose
00011 * a section of memory mapped IO.
00012 ***********************************************************************/
00013 
00014 #include "rcs_defs.hh"          /* __MSDOS__, RCS_FAR, EXTERN_C_STD_HEADERS  */
00015 #include "dbg_mem.h"            // DEBUG_MALLOC, DEBUG_FREE
00016 
00017 #ifdef EXTERN_C_STD_HEADERS
00018 extern "C"
00019 {
00020 #endif
00021 
00022 
00023 #ifdef UNDER_CE
00024 #include <winbase.h>
00025 #endif
00026 
00027 #include <string.h>             /* memcpy(), memset() */
00028 #ifndef NO_STDIO
00029 #include <stdio.h>              // sprintf()
00030 #endif
00031 #include <stdlib.h>             /* malloc() */
00032 
00033 #ifdef  lynxosPC
00034 
00035 #include <smem.h>
00036 #include <errno.h>
00037 
00038 #endif
00039 
00040 #ifdef LINUX_VME
00041 #include <sys/types.h>
00042 #include <fcntl.h>
00043 #include <unistd.h>
00044 #include <sys/mman.h>
00045 #endif
00046 
00047 
00048 #ifdef VXWORKS
00049 #include "vxWorks.h"
00050 #include "sysLib.h"             /* sysBusToLocalAdrs() */
00051 #include "vme.h"                /* VME_AM_STD_USR_DATA */
00052 #endif
00053 
00054 #ifdef EXTERN_C_STD_HEADERS
00055 }
00056 #endif
00057 
00058 #include "physmem.hh"           /* class PHYSMEM_HANDLE */
00059 
00060 #if  defined(__MSDOS__) && !defined(__WIN32__)
00061 #include "_physmem.h"           /* read_physmem(), write_physmem(), */
00062                                 /* create_ptr_to_physmem() */
00063 #endif
00064 
00065 
00066 #include "rcs_prnt.hh"
00067 
00068 /* Constructor. */
00069 PHYSMEM_HANDLE::PHYSMEM_HANDLE ()
00070 {
00071   size = 0;
00072   offset = 0;
00073   temp_buf = NULL;
00074   local_address = (LOCAL_ADDRESS_TYPE) NULL;
00075   physical_address = 0;
00076   using_bit3 = 0;
00077   isvalid = 1;
00078 #if defined(USE_BIT3) && defined(WIN32)
00079   swap_mode = 0;
00080   bt_lock_timeout = BT_FOREVER;
00081   bt_use_lock = 0;
00082 #endif
00083   total_bytes_moved = 0;
00084   enable_byte_counting = 0;
00085 
00086 }
00087 
00088 #if defined(USE_BIT3) && defined(WIN32)
00089 
00090 PHYSMEM_HANDLE::PHYSMEM_HANDLE (bt_desc_t _btd, unsigned long _btd_offset,
00091                                 long _size, int _swap_mode)
00092 {
00093   size = _size;
00094   temp_buf = NULL;
00095   offset = 0;
00096   btd = _btd;
00097   btd_offset = _btd_offset;
00098   swap_mode = _swap_mode;
00099   using_bit3 = 1;
00100   local_address = (LOCAL_ADDRESS_TYPE) NULL;
00101   physical_address = 0;
00102   bt_lock_timeout = BT_FOREVER;
00103   bt_use_lock = 0;
00104 };
00105 
00106 #endif
00107 
00108 PHYSMEM_HANDLE::PHYSMEM_HANDLE (unsigned long _physical_address,
00109                                 long _address_code, long _size)
00110 {
00111   temp_buf = NULL;
00112   physical_address = _physical_address;
00113   size = _size;
00114   address_code = _address_code;
00115   local_address = (LOCAL_ADDRESS_TYPE) NULL;
00116   isvalid = 1;
00117   offset = 0;
00118   using_bit3 = 0;
00119 #if defined(USE_BIT3) && defined(WIN32)
00120   swap_mode = 0;
00121   bt_lock_timeout = BT_FOREVER;
00122   bt_use_lock = 0;
00123 #endif
00124 
00125   if (0 == physical_address)
00126     {
00127       local_address = (LOCAL_ADDRESS_TYPE) NULL;
00128       return;
00129     }
00130 #ifdef VXWORKS
00131   /* Normally the address should be in "standard" space and address_code */
00132   /* should equal VME_AM_STD_USR_DATA. */
00133   /* and the sysBusToLocal will be used to get the address as seen */
00134   /* from this board. If the conversion doesn't work the user could replace */
00135   /* address_code with another code from "vme.h". or determine the correct */
00136   /* address for this particular board to use and bypass the */
00137   /* sysBusToLocalAdrs() call by setting address_code to zero. */
00138   /* If this is done though globmem it can be done by adding the line */
00139   /* vme_code=??? to the buffer line of the config file. */
00140   /* local address and put the VME address in a different config file. */
00141   bus_address = (char *) physical_address;
00142   if (address_code != 0)
00143     {
00144       if (OK != sysBusToLocalAdrs (address_code,
00145                                    (char *) bus_address,
00146                                    (char **) &local_address))
00147         {
00148           rcs_print_error ("sysBusToLocalAdrs returned ERROR. %d %s\n",
00149                            errno, strerror (errno));
00150           rcs_print_error ("Try changing vme_code=???");
00151         }
00152     }
00153   else
00154     {
00155       local_address = (char *) physical_address;
00156     }
00157   return;
00158 #endif
00159 
00160 
00161 #if defined(__MSDOS__) && !defined(__WIN32__)
00162 #if defined(_Windows)
00163   selector = 0;
00164   local_address =
00165     (LOCAL_ADDRESS_TYPE) create_ptr_to_physmem (physical_address, size,
00166                                                 &selector);
00167   return;
00168 #else
00169   if (physical_address < 0x100000L)
00170     {
00171       local_address = (char RCS_FAR *) physical_address;
00172     }
00173   else
00174     {
00175       local_address = NULL;
00176     }
00177   return;
00178 #endif
00179 #endif
00180 
00181 #if defined(WIN32) && !defined(gnuwin32) && !defined(UNDER_CE)
00182   if (using_bit3)
00183     {
00184       local_address = (char *) _physical_address;
00185       return;
00186     }
00187   DWORD cbReturned;
00188   ioport = 0;
00189   hMapMemDriver = NULL;
00190   hGenPortDriver = NULL;
00191   switch (address_code)
00192     {
00193     case NT_ISA_MEM_ADDRESS:
00194       pmi.InterfaceType = (INTERFACE_TYPE) Isa; // ISA interface type
00195       pmi.AddressSpace = (LONG) 0;      // 0 = map memory, 1 = map I/O
00196       pmi.BusNumber = (ULONG) 0;        // Standard x86 bus
00197       pmi.BusAddress.HighPart = (LONG) 0x00000000;      // High 32 bits of 64 bit address
00198       pmi.BusAddress.LowPart = (LONG) physical_address; // address to map
00199       pmi.Length = (LONG) size;
00200 
00201       /*
00202        *  Try to open the device
00203        */
00204       hMapMemDriver = CreateFile (TEXT ("\\\\.\\MAPMEM"),
00205                                   GENERIC_READ | GENERIC_WRITE,
00206                                   0,
00207                                   NULL,
00208                                   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
00209 
00210       if (!hMapMemDriver)
00211         {
00212           rcs_print_error
00213             ("Can not open MAPMEM driver device. (Error = %d)\n",
00214              GetLastError ());
00215           local_address = NULL;
00216           isvalid = 0;
00217           return;
00218         }
00219 
00220 
00221       if (!DeviceIoControl (hMapMemDriver,
00222                             (DWORD) IOCTL_MAPMEM_MAP_USER_PHYSICAL_MEMORY,
00223                             &pmi,
00224                             sizeof (PHYSICAL_MEMORY_INFO),
00225                             &local_address, sizeof (PVOID), &cbReturned, 0))
00226         {
00227           rcs_print_error
00228             ("DeviceIoControl error accessing MAPMEM driver. (Error = %d)\n",
00229              GetLastError ());
00230           rcs_print_error
00231             ("PHYSMEM_HANDLE: Can not create handle to physical memory at 0x%X(%d) of 0x%X(%d) bytes.(address_code = %d)\n",
00232              physical_address, physical_address, size, size, address_code);
00233           local_address = NULL;
00234           isvalid = 0;
00235           return;
00236         }
00237       break;
00238 
00239     case NT_ISA_IO_ADDRESS:
00240       hGenPortDriver = CreateFile ("\\\\.\\GpdDev",     // Open the Device "file"
00241                                    GENERIC_READ | GENERIC_WRITE,
00242                                    0, NULL, OPEN_EXISTING, 0, NULL);
00243 
00244       if (hGenPortDriver == INVALID_HANDLE_VALUE)       // Was the device opened?
00245         {
00246           rcs_print_error ("Unable to open the device.\n");
00247           local_address = NULL;
00248           ioport = 0;
00249           isvalid = 0;
00250         }
00251       ioport = (WORD) physical_address;
00252       break;
00253 
00254     default:
00255       rcs_print_error ("PHYSMEM_HANDLE: Invalid address_code (%d)\n",
00256                        address_code);
00257       isvalid = 0;
00258       return;
00259     }
00260 
00261 
00262 
00263   return;
00264 
00265 #endif
00266 
00267 #ifdef lynxosPC
00268   sprintf (smem_name, "rcs_physmem%X", physical_address);
00269 
00270   // Remove any use of this name.
00271   smem_remove (smem_name);
00272 
00273   if ((local_address = (void *)
00274        smem_create (smem_name, (char *) physical_address, size,
00275                     SM_READ | SM_WRITE)) == NULL)
00276     {
00277       rcs_print_error ("can't get physical memory %X", physical_address);
00278     }
00279   return;
00280 #endif
00281 
00282 #ifdef LINUX_VME
00283   {
00284     int fd = open ("/dev/mem", O_RDWR);
00285     if (fd < 0)
00286       {
00287         perror ("open /dev/mem");
00288         return;
00289       }
00290 
00291     /* map it */
00292     local_address = (LOCAL_ADDRESS_TYPE) mmap (0, size,
00293                                                PROT_READ | PROT_WRITE,
00294                                                MAP_FILE | MAP_SHARED,
00295                                                fd, physical_address);
00296 
00297     /* close the fd since it's no longer used */
00298     close (fd);
00299   }
00300 #endif
00301 
00302 
00303 
00304 #if !defined(__MSDOS__) && !defined(_Windows) && !defined(lynxosPC)
00305   local_address = (LOCAL_ADDRESS_TYPE) physical_address;
00306 #endif
00307 
00308 
00309 }
00310 
00311 /* Destructor. */
00312 PHYSMEM_HANDLE::~PHYSMEM_HANDLE ()
00313 {
00314 #ifdef WIN32
00315 #ifdef USING_BIT3
00316   if (using_bit3)
00317     {
00318       return;
00319     }
00320 #endif
00321 #if !defined(gnuwin32) && !defined(UNDER_CE)
00322   DWORD cbReturned;
00323   if (NULL != hMapMemDriver)
00324     {
00325       DeviceIoControl (hMapMemDriver,
00326                        (DWORD) IOCTL_MAPMEM_UNMAP_USER_PHYSICAL_MEMORY,
00327                        &pmi,
00328                        sizeof (PHYSICAL_MEMORY_INFO),
00329                        &local_address, sizeof (PVOID), &cbReturned, 0);
00330       CloseHandle (hMapMemDriver);
00331       hMapMemDriver = NULL;
00332     }
00333   if (NULL != hGenPortDriver)
00334     {
00335       CloseHandle (hGenPortDriver);
00336       hGenPortDriver = NULL;
00337     }
00338 #endif
00339 #endif
00340 
00341 #ifdef WIN16
00342   if (selector)
00343     {
00344       FreeSelector (selector);
00345       selector = 0;
00346     }
00347 #endif
00348 
00349 #ifdef lynxosPC
00350   smem_create ("", (char *) physical_address, (long int) 0, SM_DETACH);
00351   smem_remove (smem_name);
00352 
00353 #endif
00354 
00355 #ifdef LINUX_VME
00356   if (local_address != 0 && physical_address != 0)
00357     {
00358       munmap (local_address, size);
00359     }
00360 #endif
00361 
00362 }
00363 
00364 
00365 /* Use an ordinary pointer to access memory. */
00366 void
00367 PHYSMEM_HANDLE::set_to_ptr (void *_ptr, long _size)
00368 {
00369   local_address = (LOCAL_ADDRESS_TYPE) _ptr;
00370   size = _size;
00371   offset = 0;
00372 }
00373 
00374 static int physmem_read_local_address_is_null_error_print_count = 0;
00375 
00376 /***********************************************************
00377 * Read _read_size bytes from physical memory to store at _to.
00378 * Returns: 0 for success or -1 for failure.
00379 **********************************************************/
00380 int
00381 PHYSMEM_HANDLE::read (void *_to, long _read_size)
00382 {
00383   if (NULL == _to)
00384     {
00385       rcs_print_error ("PHYSMEM_HANDLE::read _to = NULL.\n");
00386       return (-1);
00387     }
00388   /* Check sizes. */
00389   if (_read_size + offset > size)
00390     {
00391       rcs_print_error
00392         ("PHYSMEM_HANDLE: Can't read %ld bytes at offset %ld from buffer of size %ld.\n",
00393          _read_size, offset, size);
00394       return (-1);
00395     }
00396 
00397   if (enable_byte_counting)
00398     {
00399       total_bytes_moved += _read_size;
00400     }
00401 
00402 #ifdef USE_BIT3
00403   if (using_bit3)
00404     {
00405       if (swap_mode)
00406         {
00407           /* Lock the adaptor */
00408           if (bt_use_lock)
00409             {
00410               bt_status = bt_lock (btd, bt_lock_timeout);
00411               if (BT_SUCCESS != bt_status)
00412                 {
00413                   bt_perror (btd, bt_status,
00414                              "Could not lock the Bit3 device. ");
00415                   return (-1);
00416                 }
00417             }
00418 
00419           // Must use character by character copy to ensure bit3 doesn't do stupid
00420           // redundant swapping.
00421           volatile char *fp = ((char *) local_address) + offset;
00422           volatile char *tp = (char *) _to;
00423           for (int i = 0; i < _read_size; i++)
00424             {
00425               *tp = *fp;
00426               tp++;
00427               fp++;
00428             }
00429 
00430           /* Unlock the adaptor  */
00431           if (bt_use_lock)
00432             {
00433               bt_status = bt_unlock (btd);
00434               if (BT_SUCCESS != bt_status)
00435                 {
00436                   bt_perror (btd, bt_status,
00437                              "Could not unlock the Bit3 device. ");
00438                   return (-1);
00439                 }
00440             }
00441 
00442           return 0;
00443         }
00444       unsigned int bt_bytes_read;
00445       bt_devaddr_t transfer_addr = btd_offset + offset;
00446       bt_status =
00447         bt_read (btd, _to, transfer_addr, _read_size, &bt_bytes_read);
00448       if (BT_SUCCESS != bt_status)
00449         {
00450           bt_perror (btd, bt_status, " bt_read failed ");
00451           return (-1);
00452         }
00453       return (0);
00454     }
00455 #endif
00456 
00457   /* If local_address has been initialized use it as an ordinary pointer. */
00458   if (NULL != local_address)
00459     {
00460       char RCS_FAR *from;
00461       from = ((char *) local_address) + offset;
00462       if (_read_size == 2)
00463         {
00464           short *sfrom = (short *) from;
00465           short sval;
00466           sval = *sfrom;
00467           short *sto = (short *) _to;
00468           *sto = sval;
00469         }
00470       else
00471         {
00472           memcpy (_to, from, _read_size);
00473         }
00474       return (0);
00475     }
00476 
00477   /* include platform specific ways of accessing phsical memory here. */
00478 #if defined(__MSDOS__) && !defined(__WIN32__)
00479   return (read_physmem (physical_address + offset, _to, _read_size));
00480 #endif
00481 #if defined(WIN32) && !defined(gnuwin32) && !defined(UNDER_CE)
00482   if (address_code == NT_ISA_IO_ADDRESS && ioport != 0)
00483     {
00484       return read_from_genport (_to, _read_size);
00485     }
00486 #endif
00487   if (!(physmem_read_local_address_is_null_error_print_count % 100000))
00488     {
00489       rcs_print_error
00490         ("PHYSMEM_HANDLE: Cannot read from physical memory when local address is NULL.\n");
00491       rcs_print_error ("(This error has occured %d times.)\n",
00492                        physmem_read_local_address_is_null_error_print_count +
00493                        1);
00494     }
00495   physmem_read_local_address_is_null_error_print_count++;
00496   return (-1);
00497 }
00498 
00499 static int physmem_write_local_address_is_null_error_print_count = 0;
00500 
00501 /***********************************************************
00502 * Write _write_size bytes from memory at _from to physical memory.
00503 * Returns: 0 for success or -1 for failure.
00504 **********************************************************/
00505 int
00506 PHYSMEM_HANDLE::write (void *_from, long _write_size)
00507 {
00508   if (NULL == _from)
00509     {
00510       rcs_print_error ("PHYSMEM_HANDLE:write _from = NULL\n");
00511       return -1;
00512     }
00513 
00514   /* Check sizes. */
00515   if (_write_size + offset > size)
00516     {
00517       rcs_print_error
00518         ("PHYSMEM_HANDLE: Can't write %ld bytes at offset %ld from buffer of size %ld.\n",
00519          _write_size, offset, size);
00520       return (-1);
00521     }
00522   if (enable_byte_counting)
00523     {
00524       total_bytes_moved += _write_size;
00525     }
00526 
00527 
00528 #ifdef USE_BIT3
00529   if (using_bit3)
00530     {
00531       if (swap_mode)
00532         {
00533           /* Lock the adaptor */
00534           if (bt_use_lock)
00535             {
00536               bt_status = bt_lock (btd, bt_lock_timeout);
00537               if (BT_SUCCESS != bt_status)
00538                 {
00539                   bt_perror (btd, bt_status,
00540                              "Could not lock the Bit3 device. ");
00541                   return (-1);
00542                 }
00543             }
00544 
00545           // Must use character by character copy to ensure bit3 doesn't do stupid
00546           // redundant swapping.
00547           volatile char *fp = (char *) _from;
00548           volatile char *tp = ((char *) local_address) + offset;
00549           for (int i = 0; i < _write_size; i++)
00550             {
00551               *tp = *fp;
00552               tp++;
00553               fp++;
00554             }
00555 
00556           /* Unlock the adaptor  */
00557           if (bt_use_lock)
00558             {
00559               bt_status = bt_unlock (btd);
00560               if (BT_SUCCESS != bt_status)
00561                 {
00562                   bt_perror (btd, bt_status,
00563                              "Could not unlock the Bit3 device. ");
00564                   return (-1);
00565                 }
00566             }
00567           return 0;
00568         }
00569       unsigned int bt_bytes_read;
00570       bt_devaddr_t transfer_addr = btd_offset + offset;
00571       bt_status =
00572         bt_write (btd, _from, transfer_addr, _write_size, &bt_bytes_read);
00573       if (BT_SUCCESS != bt_status)
00574         {
00575           bt_perror (btd, bt_status, " bt_write failed ");
00576           return (-1);
00577         }
00578       return (0);
00579     }
00580 #endif
00581 
00582   /* If local_address has been initialized use it as an ordinary pointer. */
00583   if (NULL != local_address)
00584     {
00585       char RCS_FAR *to;
00586       to = ((char *) local_address) + offset;
00587       if (_write_size == 2)
00588         {
00589           short *sto = (short *) to;
00590           short sval = *(short *) _from;
00591           *sto = sval;
00592         }
00593       else
00594         {
00595           memcpy (to, _from, _write_size);
00596         }
00597       return (0);
00598     }
00599 
00600   /* include platform specific ways of accessing phsical memory here. */
00601 #if  defined(__MSDOS__) && !defined(__WIN32__)
00602   return (write_physmem (physical_address + offset, _from, _write_size));
00603 #endif
00604 #if defined(WIN32) && !defined(gnuwin32) && !defined(UNDER_CE)
00605   if (address_code == NT_ISA_IO_ADDRESS && ioport != 0)
00606     {
00607       return write_to_genport (_from, _write_size);
00608     }
00609 #endif
00610   if (!(physmem_write_local_address_is_null_error_print_count % 100000))
00611     {
00612       rcs_print_error
00613         ("PHYSMEM_HANDLE: Cannot write to physical memory when local address is NULL.\n");
00614       rcs_print_error ("(This error has occured %d times.)\n",
00615                        physmem_write_local_address_is_null_error_print_count +
00616                        1);
00617     }
00618   physmem_write_local_address_is_null_error_print_count++;
00619   return (-1);
00620 }
00621 
00622 
00623 void
00624 PHYSMEM_HANDLE::memsetf (long _memset_offset, char _byte, long _memset_size)
00625 {
00626   /* Check sizes. */
00627   if (_memset_size + _memset_offset > size)
00628     {
00629       return;
00630     }
00631 
00632   /* If local_address has been initialized use it as an ordinary pointer. */
00633   if (NULL != local_address)
00634     {
00635       char *temp_addr;
00636       temp_addr = ((char *) local_address) + _memset_offset;
00637       memset (temp_addr, _byte, _memset_size);
00638       return;
00639     }
00640   else
00641     {
00642       /* Since local address is not initialized use temp_buf and write to
00643          access the physical memory in an platform specific way. */
00644       if (NULL == temp_buf)
00645         {
00646           temp_buf = (char *) DEBUG_MALLOC (size);
00647         }
00648       if (NULL != temp_buf)
00649         {
00650           if (_memset_size + _memset_offset <= size)
00651             {
00652               memset (temp_buf, _byte, _memset_size);
00653               unsigned long old_offset;
00654               old_offset = offset;
00655               offset = _memset_offset;
00656               write (temp_buf, _memset_size);
00657               offset = old_offset;
00658             }
00659           else
00660             {
00661               memset (temp_buf, _byte, size - _memset_offset);
00662               unsigned long old_offset;
00663               old_offset = offset;
00664               offset = _memset_offset;
00665               write (temp_buf, size - offset);
00666               offset = old_offset;
00667             }
00668         }
00669     }
00670 }
00671 
00672 
00673 
00674 int
00675 PHYSMEM_HANDLE::clear_memory ()
00676 {
00677   /* If local_address has been initialized use it as an ordinary pointer. */
00678   if (NULL != local_address)
00679     {
00680       memset (local_address, 0, size);
00681       return (0);
00682     }
00683   else
00684     {
00685       /* Since local address is not initialized use temp_buf and write to
00686          access the physical memory in an platform specific way. */
00687       if (NULL == temp_buf)
00688         {
00689           temp_buf = (char *) DEBUG_MALLOC (size);
00690         }
00691       if (NULL == temp_buf)
00692         {
00693           return (-1);
00694         }
00695       memset (temp_buf, 0, size);
00696       unsigned long old_offset;
00697       old_offset = offset;
00698       offset = 0;
00699       if (-1 == write (temp_buf, size))
00700         {
00701           offset = old_offset;
00702           return (-1);
00703         }
00704       offset = old_offset;
00705     }
00706   return (0);
00707 }
00708 
00709 int
00710 PHYSMEM_HANDLE::valid ()
00711 {
00712   return isvalid;
00713 }
00714 
00715 #if defined(WIN32) && !defined(gnuwin32) && !defined(UNDER_CE)
00716 int
00717 PHYSMEM_HANDLE::read_from_genport (void *_to, long _read_size)
00718 {
00719   int i;
00720 
00721   if ((_read_size % 4) == 0 && ((ioport + offset) % 4) == 0)
00722     {
00723       for (i = 0; i < _read_size / 4; i++)
00724         {
00725           if (read_dword_from_genport (((DWORD *) _to) + i, offset + i * 4) <
00726               0)
00727             {
00728               return -1;
00729             }
00730         }
00731       return 0;
00732     }
00733   if ((_read_size % 2) == 0 && ((ioport + offset) % 2) == 0)
00734     {
00735       for (i = 0; i < _read_size / 2; i++)
00736         {
00737           if (read_word_from_genport (((WORD *) _to) + i, i * 2) < 0)
00738             {
00739               return -1;
00740             }
00741         }
00742       return 0;
00743     }
00744   for (i = 0; i < _read_size; i++)
00745     {
00746       if (read_byte_from_genport (((BYTE *) _to) + i, offset + i) < 0)
00747         {
00748           return -1;
00749         }
00750     }
00751   return 0;
00752 }
00753 
00754 int
00755 PHYSMEM_HANDLE::read_dword_from_genport (DWORD * DataBuffer, ULONG PortNumber)
00756 {
00757   // The following is returned by IOCTL.  It is true if the read succeeds.
00758   BOOL IoctlResult;
00759 
00760   DWORD ReturnedLength;         // Number of bytes returned
00761 
00762   if (hGenPortDriver == NULL || DataBuffer == NULL)
00763     {
00764       return -1;
00765     }
00766 
00767 
00768   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
00769                                  IOCTL_GPD_READ_PORT_ULONG,     // IO Control code for Read
00770                                  &PortNumber,   // Buffer to driver.
00771                                  sizeof (PortNumber),   // Length of buffer in bytes.
00772                                  DataBuffer,    // Buffer from driver.
00773                                  4,     // Length of buffer in bytes.
00774                                  &ReturnedLength,       // Bytes placed in DataBuffer.
00775                                  NULL   // NULL means wait till op. completes.
00776     );
00777 
00778   if (!IoctlResult)
00779     {
00780       rcs_print_error ("Read  DWORD from IO port 0x%X failed.(Error = %ld)\n",
00781                        PortNumber, GetLastError ());
00782       ioport = 0;
00783       return -1;
00784     }
00785   if (ReturnedLength != 4)
00786     {
00787       rcs_print_error
00788         ("GenPort driver returned %d bytes on port 0x%X when 4 were expected.\n",
00789          ReturnedLength, PortNumber);
00790       return -1;
00791     }
00792   return 0;
00793 }
00794 
00795 int
00796 PHYSMEM_HANDLE::read_word_from_genport (WORD * DataBuffer, ULONG PortNumber)
00797 {
00798   // The following is returned by IOCTL.  It is true if the read succeeds.
00799   BOOL IoctlResult;
00800 
00801   DWORD ReturnedLength;         // Number of bytes returned
00802 
00803   if (hGenPortDriver == NULL || DataBuffer == NULL)
00804     {
00805       return -1;
00806     }
00807 
00808 
00809   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
00810                                  IOCTL_GPD_READ_PORT_USHORT,    // IO Control code for Read
00811                                  &PortNumber,   // Buffer to driver.
00812                                  sizeof (PortNumber),   // Length of buffer in bytes.
00813                                  DataBuffer,    // Buffer from driver.
00814                                  2,     // Length of buffer in bytes.
00815                                  &ReturnedLength,       // Bytes placed in DataBuffer.
00816                                  NULL   // NULL means wait till op. completes.
00817     );
00818 
00819   if (!IoctlResult)
00820     {
00821       rcs_print_error ("Read WORD from IO port 0x%X failed.(Error = %ld)\n",
00822                        PortNumber, GetLastError ());
00823       ioport = 0;
00824       return -1;
00825     }
00826   if (ReturnedLength != 2)
00827     {
00828       rcs_print_error
00829         ("GenPort driver returned %d bytes on port 0x%X when 2 were expected.\n",
00830          ReturnedLength, PortNumber);
00831       return -1;
00832     }
00833   return 0;
00834 }
00835 
00836 int
00837 PHYSMEM_HANDLE::read_byte_from_genport (BYTE * DataBuffer, ULONG PortNumber)
00838 {
00839   // The following is returned by IOCTL.  It is true if the read succeeds.
00840   BOOL IoctlResult;
00841 
00842   DWORD ReturnedLength;         // Number of bytes returned
00843 
00844   if (hGenPortDriver == NULL || DataBuffer == NULL)
00845     {
00846       return -1;
00847     }
00848 
00849 
00850   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
00851                                  IOCTL_GPD_READ_PORT_UCHAR,     // IO Control code for Read
00852                                  &PortNumber,   // Buffer to driver.
00853                                  sizeof (PortNumber),   // Length of buffer in bytes.
00854                                  DataBuffer,    // Buffer from driver.
00855                                  1,     // Length of buffer in bytes.
00856                                  &ReturnedLength,       // Bytes placed in DataBuffer.
00857                                  NULL   // NULL means wait till op. completes.
00858     );
00859 
00860   if (!IoctlResult)
00861     {
00862       rcs_print_error ("Read BYTE from IO port 0x%X failed.(Error = %ld)\n",
00863                        PortNumber, GetLastError ());
00864       ioport = 0;
00865       return -1;
00866     }
00867   if (ReturnedLength != 1)
00868     {
00869       rcs_print_error
00870         ("GenPort driver returned %d bytes on port 0x%X when 2 were expected.\n",
00871          ReturnedLength, PortNumber);
00872       return -1;
00873     }
00874   return 0;
00875 }
00876 
00877 
00878 int
00879 PHYSMEM_HANDLE::write_to_genport (void *_from, long _write_size)
00880 {
00881   int i;
00882 
00883   if ((_write_size % 4) == 0 && ((ioport + offset) % 4) == 0)
00884     {
00885       for (i = 0; i < _write_size / 4; i++)
00886         {
00887           if (write_dword_to_genport (((DWORD *) _from)[i], offset + i * 4) <
00888               0)
00889             {
00890               return -1;
00891             }
00892         }
00893       return 0;
00894     }
00895   if ((_write_size % 2) == 0 && ((ioport + offset) % 2) == 0)
00896     {
00897       for (i = 0; i < _write_size / 2; i++)
00898         {
00899           if (write_word_to_genport (((WORD *) _from)[i], offset + i * 2) < 0)
00900             {
00901               return -1;
00902             }
00903         }
00904       return 0;
00905     }
00906   for (i = 0; i < _write_size; i++)
00907     {
00908       if (write_byte_to_genport (((BYTE *) _from)[i], offset + i) < 0)
00909         {
00910           return -1;
00911         }
00912     }
00913   return 0;
00914 }
00915 
00916 
00917 int
00918 PHYSMEM_HANDLE::write_dword_to_genport (DWORD data, ULONG PortNumber)
00919 {
00920   // The following is returned by IOCTL.  It is true if the read succeeds.
00921   BOOL IoctlResult;
00922 
00923   DWORD ReturnedLength;         // Number of bytes returned
00924 
00925   if (hGenPortDriver == NULL)
00926     {
00927       return -1;
00928     }
00929   gpwi.PortNumber = PortNumber;
00930   gpwi.LongData = data;
00931 
00932   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
00933                                  IOCTL_GPD_WRITE_PORT_ULONG,    // IO Control code for Write
00934                                  &gpwi, // Buffer to driver.  Holds port & data.
00935                                  offsetof (GENPORT_WRITE_INPUT, LongData) +
00936                                  sizeof (gpwi.LongData),        // Length of buffer in bytes.
00937                                  NULL,  // Buffer from driver.   Not used.
00938                                  0,     // Length of buffer in bytes.
00939                                  &ReturnedLength,       // Bytes placed in outbuf.  Should be 0.
00940                                  NULL   // NULL means wait till I/O completes.
00941     );
00942 
00943   if (!IoctlResult)
00944     {
00945       rcs_print_error ("Write DWORD to IO port 0x%X failed.(Error = %d)\n",
00946                        PortNumber, GetLastError ());
00947       ioport = 0;
00948       return -1;
00949     }
00950   return 0;
00951 }
00952 
00953 int
00954 PHYSMEM_HANDLE::write_word_to_genport (WORD data, ULONG PortNumber)
00955 {
00956   // The following is returned by IOCTL.  It is true if the read succeeds.
00957   BOOL IoctlResult;
00958 
00959   DWORD ReturnedLength;         // Number of bytes returned
00960 
00961   if (hGenPortDriver == NULL)
00962     {
00963       return -1;
00964     }
00965   gpwi.PortNumber = PortNumber;
00966   gpwi.ShortData = data;
00967 
00968   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
00969                                  IOCTL_GPD_WRITE_PORT_USHORT,   // IO Control code for Write
00970                                  &gpwi, // Buffer to driver.  Holds port & data.
00971                                  offsetof (GENPORT_WRITE_INPUT, ShortData) +
00972                                  sizeof (gpwi.ShortData),       // Length of buffer in bytes.
00973                                  NULL,  // Buffer from driver.   Not used.
00974                                  0,     // Length of buffer in bytes.
00975                                  &ReturnedLength,       // Bytes placed in outbuf.  Should be 0.
00976                                  NULL   // NULL means wait till I/O completes.
00977     );
00978 
00979   if (!IoctlResult)
00980     {
00981       rcs_print_error ("Write WORD to IO port 0x%X failed. (Error = %d)\n",
00982                        PortNumber, GetLastError ());
00983       ioport = 0;
00984       return -1;
00985     }
00986   return 0;
00987 }
00988 
00989 
00990 int
00991 PHYSMEM_HANDLE::write_byte_to_genport (BYTE data, ULONG PortNumber)
00992 {
00993   // The following is returned by IOCTL.  It is true if the read succeeds.
00994   BOOL IoctlResult;
00995 
00996   DWORD ReturnedLength;         // Number of bytes returned
00997 
00998   if (hGenPortDriver == NULL)
00999     {
01000       return -1;
01001     }
01002   gpwi.PortNumber = PortNumber;
01003   gpwi.CharData = data;
01004 
01005   IoctlResult = DeviceIoControl (hGenPortDriver,        // Handle to device
01006                                  IOCTL_GPD_WRITE_PORT_UCHAR,    // IO Control code for Write
01007                                  &gpwi, // Buffer to driver.  Holds port & data.
01008                                  offsetof (GENPORT_WRITE_INPUT, CharData) +
01009                                  sizeof (gpwi.CharData),        // Length of buffer in bytes.
01010                                  NULL,  // Buffer from driver.   Not used.
01011                                  0,     // Length of buffer in bytes.
01012                                  &ReturnedLength,       // Bytes placed in outbuf.  Should be 0.
01013                                  NULL   // NULL means wait till I/O completes.
01014     );
01015 
01016   if (!IoctlResult)
01017     {
01018       rcs_print_error ("Write BYTE to IO port 0x%X failed. (Error = %d)\n",
01019                        PortNumber, GetLastError ());
01020       ioport = 0;
01021       return -1;
01022     }
01023   return 0;
01024 }
01025 
01026 #endif

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