home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / labhelp.zip / labhelp / test.c < prev    next >
C/C++ Source or Header  |  1992-12-09  |  12KB  |  329 lines

  1. /* ---------------------------------------------------------------------------
  2. -- LabHelp subroutines to provide useful access to physical functions
  3. -- of the OS/2 operating system and hardward.  These functions are normally
  4. -- not allowed, but in lab situations, such access if often desirable.
  5. --------------------------------------------------------------------------- */
  6.  
  7. /* --------------------------------------------------------------------------
  8. -- void *LHGetPhysMem(unsigned long ulAddr, size_t cbSize);
  9. --    Obtains pointer to specified physical memory locations
  10. -- int LHGetTime(unsigned long *ulMs, unsigned long *ulNs);
  11. --    Obtains timestamp to the nearest millisecond, ns since boot
  12. --
  13. -- Notes:
  14. --
  15. -- * Code tested with IBM CSET/2 compiler at CSD CS0022, and Microsoft C6.0A
  16. --   compiler.  Default is the IBM CSET/2 compiler.
  17. --
  18. -- * #define NO_DEVELOPMENT_KIT if you don't have the OS/2 developers kit.
  19. --
  20. -- * #define MSC60 to use Microsoft C compiler instead of IBM CSET/2 compiler
  21. --
  22. -- * #include files are for POSIX standard implementation.  If not using
  23. --   POSIX, replace <unistd.h> with <io.h>.
  24. --
  25. -- * Code depends on CSET/2 providing pointer conversion from _SEG16 to flat.
  26. --   I hope IBM continues to make this work with future CSET/2 releases.
  27. --
  28. -- * Under Microsoft C, large model must be used if you do not have the OS/2
  29. --   developer's kit (DosDevIOCtl call must be properly prototyped).
  30. ---------------------------------------------------------------------------- */
  31.  
  32. /* -------------------
  33. -- Feature test macros
  34. ---------------------- */
  35. #define _POSIX_SOURCE                    /* Must always be defined for POSIX   */
  36. /* #define MSC60 */                        /* Uncomment if using Microsoft C 6.0 */
  37. /* #define NO_DEVELOPERS_KIT */        /* Uncomment if no OS/2 develope kit  */
  38. /* #define DEBUG */                          /* Uncomment to get debug message      */
  39. #define TEST                                /* Uncomment to enable test routines  */
  40.  
  41. /* ----------------------
  42. -- Standard include files
  43. ------------------------- */
  44. #ifndef NO_DEVELOPMENT_KIT                /* Include if it exists */
  45.     #define INCL_DOSDEVICES
  46.     #include <os2.h>
  47. #elif defined MSC60                        /* Otherwise, fake definitions */
  48.     unsigned short _pascal _far
  49.         DosDevIOCtl(void *,void *,unsigned short,unsigned short,unsigned short);
  50. #else
  51.     unsigned long _System
  52.         DosDevIOCtl(unsigned long, unsigned long, unsigned long, void *,
  53.         unsigned long, unsigned long *, void *, unsigned long, unsigned long *);
  54. #endif
  55.  
  56. #include <stdio.h>
  57. #include <unistd.h>                        /* Replace with <io.h> if no POSIX */
  58. #include <fcntl.h>
  59.  
  60. /* ----------------------------
  61. -- Local macros and definitions
  62. ------------------------------- */
  63. #ifdef MSC60                                /* Create standard way to access IOCTL */
  64.     #define IOCTL(h,ct,fc,pm,ln)    DosDevIOCtl(NULL,pm, fc,ct, h)
  65. #else
  66.     #define IOCTL(h,ct,fc,pm,ln)    DosDevIOCtl(h, ct,fc, pm,ln,&ln, NULL,0,NULL)
  67. #endif
  68.  
  69. #define    LHCATEGORY    0x81            /* Category for Labhelp IOCtl calls */
  70. #define    LHGETMEM        0x41            /* Function to allocate physical mem */
  71. #define    LHGETTIME    0x42            /* Function to return time in ns */
  72.  
  73. /* -------------------
  74. -- Function prototypes
  75. ---------------------- */
  76. void *LHGetPhysMem(unsigned long ulAddr, size_t cbSize);
  77.  
  78.  
  79. /* ===========================================================================
  80. -- Description: Obtain (void *) pointer to physical memory address block.
  81. --
  82. -- Usage:   void *LHGetPhysMem(unsigned long ulAddr, size_t cbSize);
  83. --
  84. -- Inputs:    ulAddr - long (32 bit) physical address of desired block
  85. --                cbSize - block length in bytes.  (see note below).
  86. --
  87. -- Outputs:    <none>
  88. --
  89. -- Returns: (void *) pointer to memory if successful.  NULL on failure.
  90. --
  91. -- Errors:  Returns NULL.  Possible reasons are driver not installed (message
  92. --          printed) or some invalid call (ie. don't know).
  93. --
  94. -- Note:  * Physical memory is only accessible at Ring 0 from the device
  95. --          driver LABHELP.SYS, which must be loaded in CONFIG.SYS.
  96. --        * Memory under OS/2 2.0 is committed only in pages of 4096 bytes.
  97. --          Requests for less will be satisfied with one full page.
  98. --             * Because of implementation, block size must be < 65535 bytes
  99. --        * Implemented as IOCtl call to device LABHELP$ via category 0x81
  100. --          and function 0x41.  LABHELP$ returns _SEG16 pointer to memory.
  101. --        * Attempting to "free" pointer will likely result in a trap
  102. --
  103. -- WARNING: This routine blatantly bypasses OS/2's memory protection.  It goes
  104. --          against everything OS/2 stands for, but that's why I run a single
  105. --          user system.  This call gives access to any memory, and you can
  106. --          trash it as you see fit.  This is now your problem, not mine.
  107. =========================================================================== */
  108. void *LHGetPhysMem(unsigned long ulAddr, size_t cbSize) {
  109.  
  110.     struct {
  111.         unsigned long    PhysicalAddress;        /* 32 bit physical address        */
  112.         unsigned long    AccessLength;            /* Length access required        */
  113. #if defined MSC60
  114.         void  *SegPtr;                                /* Returned pointer                */
  115. #else
  116.         void    * _Seg16 SegPtr;                    /* Returned pointer                */
  117. #endif
  118.     } Parms;
  119.  
  120.     int fh;                                            /* File handle                        */
  121.     int rc;                                            /* Return code                        */
  122.     unsigned long len=sizeof(Parms);            /* Random length variable        */
  123.     void    *pvPtr=NULL;                            /* Normal (! _Seg16) pointer    */
  124.  
  125.     Parms.PhysicalAddress = ulAddr;            /* Copy user values to structure */
  126.     Parms.AccessLength    = cbSize;
  127.  
  128.     if ( (fh = open("LABHELP$", O_RDONLY)) < 0) {
  129.         perror("LABHELP$ not found - is LABHELP.SYS installed?");
  130.         return(NULL);
  131.     } else {
  132.         rc = IOCTL(fh, LHCATEGORY, LHGETMEM, &Parms, len);
  133.         if (rc == 0) pvPtr = Parms.SegPtr;    /* Compiler handles conversion */
  134.         close(fh);
  135. #ifdef DEBUG
  136.         printf("GETMEM: %i  (_Seg16 *): %p  (*): %p\n", rc, Parms.SegPtr, pvPtr);
  137. #endif
  138.     }
  139.     return(pvPtr);
  140. }
  141.  
  142. /* ===========================================================================
  143. -- Description: Obtain timestamp in nanoseconds and milliseconds
  144. --
  145. -- Usage:   int LHGetTime(unsigned long *ulMs, unsigned long *ulNs);
  146. --
  147. -- Inputs:    <none>
  148. --
  149. -- Outputs:    *ulMs - If not NULL, get time in milliseconds since start of system
  150. --          *ulNs - If not NULL, get time in nanoseconds portion of time
  151. --                  0 < ulNs < 999999 since 1 mS is largest fraction
  152. --
  153. -- Returns:  0 - successful
  154. --          !0 - unsuccessful
  155. --
  156. -- Errors:  No driver returns -1.  Otherwise, return code from DosDevIOCtl
  157. --          returned.  Error printed if no driver found.
  158. --
  159. -- Note:  * Timer accessed from device driver LABHELP.SYS.
  160. --        * Implemented as IOCtl call to device LABHELP$ via category 0x81
  161. --          and function 0x42.  LABHELP$ returns private structure.
  162. =========================================================================== */
  163. int LHGetTime(unsigned long *ulMs, unsigned long *ulNs) {
  164.  
  165.     struct {
  166.         unsigned long ns_per_tick;                /* ns / tick (normally 840)    */
  167.         unsigned long tick[2];                    /* 64 bit tick count                */
  168.     } Parms;
  169.     unsigned long ns, ms;
  170.     unsigned long tick[4], remain;            /* 16 bit represent of 32 bit # */
  171.     int i;
  172.  
  173.     int fh;                                            /* File handle                        */
  174.     int rc;                                            /* Return code                        */
  175.     unsigned long len=sizeof(Parms);            /* Random length variable        */
  176.  
  177.     if ( (fh = open("LABHELP$", O_RDONLY)) < 0) {
  178.         perror("LABHELP$ not found - is LABHELP.SYS installed?");
  179.         return(-1);
  180.     } else {
  181.         rc = IOCTL(fh, LHCATEGORY, LHGETTIME, &Parms, len);
  182.         close(fh);
  183. #ifdef DEBUG
  184.         printf("GETTIME: %i  Ticks: %lx%8.8lx\n", rc, Parms.tick[1], Parms.tick[0]);
  185. #endif
  186.         if (rc != 0) return(-1);
  187.     }
  188. /* -- Synthetic math - break into 4 16 bit quantities to give 65536 range */
  189.     tick[0] = Parms.tick[0] & 0xFFFF;
  190.     tick[1] = Parms.tick[0] >> 16;
  191.     tick[2] = Parms.tick[1] & 0xFFFF;
  192.     tick[3] = Parms.tick[1] >> 16;
  193.  
  194. /* -- Multiply by ns per tick to get total # of ns */
  195.     for (i=0; i<4; i++) tick[i] *= Parms.ns_per_tick;
  196.     for (i=0; i<3; i++) {                            /* Handle carry */
  197.         tick[i+1] += tick[i] >> 16;
  198.         tick[i]   &= 0xFFFF;
  199.     }
  200.  
  201. /* -- Divide limited to 2**16 = 65536, so do by 1000 twice */
  202.     remain = 0;
  203.     for (i=3; i>=0; i--) {                                /* Divide by 1000 */
  204.         tick[i] += remain << 16;                        /* Add remainder */
  205.         remain   = tick[i] % 1000u;                    /* Next stage remainder */
  206.         tick[i] /= 1000u;                                    /* And do division */
  207.     }
  208.     ns = remain;
  209.     remain = 0;
  210.     for (i=2; i>=0; i--) {
  211.         tick[i] += (remain << 16);                        /* Add remainder */
  212.         remain   = (tick[i] % 1000u);                    /* Next stage remainder */
  213.         tick[i] /= 1000u;                                    /* And do division */
  214.     }
  215.     ns += 1000*remain;                                    /* uS left overs */
  216.  
  217.     ms = tick[0] + (tick[1] << 16);                    /* Restore the 32 bit value */
  218.  
  219.     if (ulMs != NULL) *ulMs = (rc==0) ? ms : 0;
  220.     if (ulNs != NULL) *ulNs = (rc==0) ? ns : 0;
  221.     return(rc);
  222. }
  223.  
  224.  
  225. /* ******************************************************************
  226. ** TEST SECTION - ONLY NECESSARY IF YOU WANT TO TEST ALL FUNCTIONS **
  227. ****************************************************************** */
  228.  
  229. #ifdef TEST
  230.  
  231. /* --------------------------------------------
  232. -- Additional includes/prototypes (CSET/2 only)
  233. ----------------------------------------------- */
  234. APIRET APIENTRY DosSleep(ULONG msec);
  235. #include <stdlib.h>
  236. #include <string.h>
  237.  
  238. /* ===========================================================================
  239. -- Usage: int TestGetMem(void);
  240. --        int TestGetTime(void);
  241. --
  242. -- Description: Gets pointer to memory at 0xB8000, length 0x2000, video memory
  243. --              in CGA full screen mode.  Write's 0's over screen for 1 sec.
  244. --              Time test sleeps for 1 second and prints time of sleep.
  245. --
  246. -- Inputs:    <none>
  247. --
  248. -- Outputs: <none>
  249. --
  250. -- Returns: 0 (successful) or 1 (failed)
  251. --
  252. -- Notes:   Imagine the damage you can do with LHGetPhysMem!
  253. =========================================================================== */
  254. int TestGetMem(void) {
  255.  
  256.     int i;
  257.     short *Video, *VideoHold;        
  258.     
  259.     if ( (Video = LHGetPhysMem(0xB8000, 0x1000)) == NULL) {
  260.         printf("ERROR: Unable to obtain pointer to physical memory\n");
  261.         return(1);
  262.     }
  263.  
  264.     VideoHold = malloc(25*80*sizeof(*VideoHold));
  265.     memcpy(VideoHold, Video, 25*80*sizeof(*VideoHold));
  266.     for (i=0; i<25*80; i++) Video[i] = 0x0730;        /* Fill with 0's */
  267.     DosSleep(1000L);                                            /* Sleep one second */
  268.     memcpy(Video, VideoHold, 25*80*sizeof(*VideoHold));
  269.  
  270.     free(VideoHold);                                            /* Free memory blocks */
  271.     return(0);
  272. }
  273.  
  274. #define    NUMFAST    25
  275. #define    NUMSLEEP    10
  276.  
  277. int TestGetTime(void) {
  278.  
  279.     unsigned long ms_start, ns_start, ms, ns;
  280.     int i;
  281.     unsigned long fast[NUMFAST];
  282.  
  283.     if (LHGetTime(&ms_start, &ns_start) != 0) return(1);
  284.  
  285.     for (i=0; i<NUMSLEEP; i++) {
  286.         DosSleep(1000);
  287.         if (LHGetTime(&ms, &ns) != 0) return(1);
  288.         ms = ms - ms_start;                                    /* Delta ms */
  289.         ns = (ns >= ns_start) ? ns-ns_start : (1000000+ns)-ns_start, ms--;
  290.         printf("Total time: %lu.%6.6lu milliseconds\n", ms, ns);
  291.     }
  292.  
  293.     for (i=0; i<NUMFAST; i++) {
  294.         LHGetTime(&ms_start, &ns_start);
  295.         LHGetTime(&ms, &ns);
  296.         ms = ms - ms_start;                                    /* Delta ms */
  297.         ns = (ns >= ns_start) ? ns-ns_start : (1000000+ns)-ns_start, ms--;
  298.         fast[i] = ms*1000000+ns;
  299.     }
  300.     for (i=0; i<NUMFAST; i++) printf("fast: %lu\n", fast[i]);
  301.     return(0);
  302. }
  303.  
  304. /* ===========================================================================
  305. -- Usage: main routine to run through LabHelp calls
  306. --
  307. -- Description: Runs test of each LabHelp routine
  308. --
  309. -- Returns: 0 (successful) or # of failures
  310. =========================================================================== */
  311. int main(int argc, char *argv[]) {
  312.  
  313.     int rc=0;
  314.  
  315.     if (TestGetMem() != 0) {
  316.         rc++;
  317.         printf("Memory access function test failed\n");
  318.     }
  319.  
  320.     if (TestGetTime() != 0) {
  321.         rc++;
  322.         printf("Timer access function test failed\n");
  323.     }
  324.  
  325.     return(rc);
  326. }
  327.  
  328. #endif     /* TEST */
  329.