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

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

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