home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / rng-810.zip / randdrv.cpp < prev    next >
C/C++ Source or Header  |  1994-01-24  |  14KB  |  437 lines

  1. /*
  2. *
  3. * Copyright (c) Sirius Software 1992.
  4. * All rights reserved.
  5. * But the README.DOC from Sirius Software file says:
  6. * This software is hereby placed in the public domain.
  7. *
  8. */
  9. /*
  10.  RANDDRV.SYS random number driver for RNG-810 random # or similar.
  11.  Copyright (C) 1994 Paul Elliot
  12.  
  13.  This program is free software; you can redistribute it and/or
  14.  modify it under the terms of the GNU General Public License
  15.  as published by the Free Software Foundation; either version 2
  16.  of the License, or (at your option) any later version.
  17.  
  18.  This program is distributed in the hope that it will be useful,
  19.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.  GNU General Public License for more details.
  22.  
  23.  You should have received a copy of the GNU General Public License
  24.  along with this program; if not, write to the Free Software
  25.  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27. Paul.Elliott@Hrnowl.LoneStar.Org
  28.  
  29. Paul Elliott
  30.  
  31. 3986 South Gessner #224 Houston TX 77063
  32.  
  33. */
  34.  
  35. /*
  36. *  file_name = randdrv.cpp
  37. *
  38. *   Notes :
  39. *        - created June 1, 1993 Greg Smith
  40. *        - sample OS/2 device driver. This is very brain dead and it just
  41. *        installs itself and any other call returns errors. Generic IOCTL 
  42. *        is supported and is used to get the device driver version string.
  43. */
  44.  
  45. //#include <stdio.h>
  46. //#include <stdarg.h>
  47. //#include <string.h>
  48. #include <mem.h>
  49. #include <dos.h>
  50. #include "randdrv.h"
  51. #include "rand.h"
  52.  
  53. #define majorVersion     1
  54. #define minorVersion    00
  55. #define revision        'a'
  56.  
  57. // 
  58. // This MUST be the first data declaration that allocates space in the
  59. // data segment
  60. //
  61. #if 0
  62. // There is nothing in the c or c++ language, that requires
  63. // that the first data item in the source file
  64. // will be the first element in memory!
  65. // This happens (by chance ) to work, but
  66. // may not in future versions of the compiler/
  67. // Therefore I am commenting this declaration out
  68. // and declaring header in assembly lauague. PE
  69. DeviceDriverHeader Header = {
  70.     (struct DeviceDriverHeaderStruct far *)-1L,
  71.     DAW_OPN | DAW_CHR | DAW_LEVEL1 |DAW_GIO | DAW_SHR,
  72.     //0x80c0,    // character device driver, function level 001, Generic IOCTL supported
  73.     // sharable as well
  74.     Entry1,            // entry point to call driver, defined in c0.asm
  75.     0,
  76.     // name of device
  77.     { 'R', 'A', 'N', 'D', '0', '0', '0', '1' }
  78. };
  79. #else
  80. extern DeviceDriverHeader Header;
  81. #endif
  82.  
  83. // request handler routines.
  84. extern word near Init( RequestPacket far *requestPacket );
  85. //word near GenericIOCTL( RequestPacket far *requestPacket );
  86. word near Error( RequestPacket far *requestPacket );
  87. word near Done( RequestPacket far *requestPacket );
  88. word near Open( RequestPacket far *requestPacket );
  89. word near Close( RequestPacket far *requestPacket );
  90. word near Deinstall( RequestPacket far *requestPacket );
  91. word near Read( RequestPacket far *requestPacket );
  92. word near ReadNoWait( RequestPacket far *requestPacket );
  93. word near InputStatus( RequestPacket far *requestPacket );
  94.  
  95.  
  96. DispatchFunctionType dispatchTable[] = {
  97.     Init,                     // 0 = Initialise
  98.     Error,                    // 1 = Media Check
  99.     Error,                    // 2 = Build Bios Parameter Block
  100.     Error,                    // 3 = reserved
  101.     Read,                    // 4 = Read
  102.     ReadNoWait,                    // 5 = Non Destructive Read
  103.     InputStatus,                    // 6 = Input Status
  104.     Error,                    // 7 = Input Flush
  105.     Error,                    // 8 = Write
  106.     Error,                    // 9 = Write with verify
  107.     Error,                    // 10 = output status
  108.     Error,                    // 11 = output flush
  109.     Error,                    // 12 = reserved
  110.     Open,                    // 13 = open
  111.     Close,                    // 14 = close
  112.     Error,                    // 15 = Removable Media
  113. //    GenericIOCTL,            // 16 = Generic IOCTL
  114.     Error,            // 16 = Generic IOCTL
  115.     Error,                    // 17 = Reset Media
  116.     Error,                    // 18 = Get Logical Drive
  117.     Error,                    // 19 = Set Logical Drive
  118.     Deinstall,                // 20 = Deinstall
  119.     Error,                    // 21 = reserved
  120.     Error,                    // 22 = Partitionable Fixed Disk
  121.     Error,                    // 23= Get Fixed Disk Unit Map
  122.     Error,                    // 24 = reserved
  123.     Error,                    // 25 = reserved
  124.     Error                    // 26 = reserved
  125. };
  126.  
  127. // address indicates call back address used to call back device
  128. // helper routines.
  129. dword near _devHlp;
  130.  
  131. // status to return.
  132. const word done = 0x0100;                        //
  133. const word error = 0x8000;                        // status return bit masks
  134. const word generalDeviceError =        0x0c;        //
  135. const word unknownCommand =         0x03;        // status error codes
  136.  
  137. // port to access to read random data.
  138. unsigned int near port;
  139.  
  140. // size of random number buffers
  141. #define BUF_SIZE 512
  142. // buferr to hold random numbers comming form timer routine
  143. char near buf[BUF_SIZE];
  144. // start of above buffer
  145. char near * near  buf_start=buf;
  146. // one byte past above buffer
  147. char near * near buf_end=buf+BUF_SIZE;
  148. // address of next character to read into the buffer
  149. char near * near current_input=buf;
  150. // addres of next character in buffer to give to application.
  151. char near * near current_output=buf;
  152.  
  153. // This is the number of bytes of the buffer that we are currently
  154. // moveing to various applications.
  155. volatile word near pending=0;
  156. // This is the number of bytes in buffer that
  157. // do not contain unused saved random numbers that have not been given
  158. // to a app yet
  159. volatile word near unused_in_buffer=BUF_SIZE;
  160. // number of bytes this request is waiting for..
  161. // when this goes to zero, wake blocked thread.
  162. volatile signed int near waiting_for = 0;
  163.  
  164.  
  165. // number of open files.
  166. unsigned short near open_count=0;
  167. /***************************************************************************/
  168.  
  169.  
  170. /***************************************************************************/
  171.  
  172. // main request dispatcher.
  173. void near Strategy1( RequestPacket far *requestPacket ){
  174.     // All OS/2 device I/O passes through here
  175.     if    ( requestPacket->commandCode < dim( dispatchTable ) ){
  176.         // call the appropriate packet handler
  177.         requestPacket->status = dispatchTable[ requestPacket->commandCode ]( requestPacket );
  178.     } else {
  179.         // a strange packet was received, handle the error
  180.         requestPacket->status = error | done | unknownCommand;
  181.     }
  182. }
  183.  
  184. /***************************************************************************/
  185.  
  186. // open one file, inc open file counter.
  187. word Open( RequestPacket far *requestPacket ){
  188.     if ( ++open_count == 1 ) TimerOn();
  189.     return(done);
  190. }
  191. // remove driver, turn off its timer.
  192. word Deinstall( RequestPacket far *requestPacket ){
  193.     TimerOff();
  194.     return(done);
  195. }
  196. // close file, dec open file counter.
  197. word Close( RequestPacket far *requestPacket ){
  198.     if (--open_count == 0) TimerOff();
  199.     return(done);
  200. }
  201.  
  202. // read one byte with now wait.
  203. word ReadNoWait( RequestPacket far *requestPacket ){
  204.     // assume buffer not empty
  205.     word busy=0;
  206.  
  207.     // if no saved random bytes
  208.     if (unused_in_buffer == BUF_SIZE)
  209.     {
  210.         // declare device busy.
  211.         busy= RPBUSY;
  212.     }
  213.     else
  214.     {
  215.         // return frist char in buffer
  216.         requestPacket->nonDestructiveReadChar = *current_output;
  217.     }
  218.     // return ok
  219.     return (RPDONE |busy);
  220. }
  221.  
  222. // if buffer has characters, OK, else return bussy
  223. word InputStatus( RequestPacket far *requestPacket ){
  224.  
  225.     return(done  | ( (unused_in_buffer == BUF_SIZE)? RPBUSY : 0 ) );
  226. }
  227.  
  228. // read request to read the buffer
  229. word Read( RequestPacket far *requestPacket ){
  230.  
  231.     // virtual address to map
  232.     auto char far* virtaddr;
  233.     // number of bytes remaining to be transfered to application.
  234.     auto word remain = requestPacket->transfer.bytesToTransfer;
  235.  
  236.     // bytes used.
  237.     auto word used;
  238.  
  239.     // true if the virtual address is mapped
  240.     // blocking allways undoes mapping.
  241.     auto word mapped = 0;
  242.  
  243.     // while there are bytes to return...
  244.     while ( remain > 0)
  245.     {
  246.         
  247.  
  248.       // disable interupts, get free bytes = bytes in buffer - #of
  249.       // bytes waiting to be transfer.
  250.       // keep blocking untill we get some bytes.
  251.       while ( disable(),(used = (BUF_SIZE -unused_in_buffer) - pending),
  252.         (used  == 0))
  253.       {
  254.           word count = buf_end - current_output;
  255.           if ( count > remain) count = remain;
  256.           if ( waiting_for <= 0 ) waiting_for = count;
  257.           
  258.           // we are doing a block, which unmapps buffer,
  259.         // if it had been mapped.
  260.           mapped = 0;
  261.           // save current status of buffer to check for change.
  262.           word orig_unused = unused_in_buffer;
  263.           int err;
  264.  
  265.           err = block(41000L,0) & 0xff;
  266.  
  267.           //enable interupts, check for error.
  268.         enable();
  269.           mapped = 0;
  270.  
  271.           // return errors if found
  272.           if ( ( orig_unused != unused_in_buffer) &&(err != 2) )
  273.           err=0;
  274.  
  275.           if (err > 0) requestPacket->transfer.bytesToTransfer = 0;
  276.           if (err == 2)
  277.           {
  278.              return RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED;
  279.           }
  280.           if ( err == 1)
  281.           {
  282.              return RPDONE|RPERR|ERROR_NOT_READY;
  283.           }
  284.       }
  285.       // we fall from above loop with interrupts disabled.
  286.  
  287.  
  288.       // get bytes to transfer, min of
  289.       // a) space from here to end of buffer
  290.       // b) bytes remaining to transfer of those originally requested
  291.       //    by user.
  292.       // c) number of bytes in buffer - # that other requests my
  293.       //     be transfering.
  294.       word count = buf_end - current_output;
  295.       if ( count > remain) count = remain;
  296.       if ( count > used) count = used;
  297.  
  298.       // allocate space in buffer for transfer
  299.       auto char near * pending_buffer = current_output;
  300.       // update the place in buffer to use for next requests
  301.       current_output += count;
  302.       // but wrapp around to beginning if we are at end.
  303.       if (current_output == buf_end) current_output = buf_start;
  304.  
  305.       // we are now tring to tranfer count bytes, so increment
  306.       // pending by count.
  307.       pending += count;
  308.  
  309.       // enable the interrups that have been disabled
  310.       enable();
  311.  
  312.       // get offset within user buffer to transfer to
  313.       auto word offset =
  314.         (requestPacket->transfer.bytesToTransfer - remain);
  315.  
  316.       // if there are bytes to transfer
  317.       if (count > 0) {
  318.          // if the physical address has not been mapped to
  319.          // a virtual address, or if that address has been
  320.          // invalidated by a block request, the convert the
  321.          // physical address to a virtual address
  322.          if (!mapped)
  323.          {
  324.         PhysToVirt(requestPacket->transfer.transferAddress,
  325.             requestPacket->transfer.bytesToTransfer, &virtaddr );
  326.              mapped = 1;        // vir address has now bee maped.
  327.          }
  328.          // move the data to users buffer!
  329.          memmove(virtaddr+offset,(char far *)pending_buffer,count);
  330.       }
  331.  
  332.       // decrement amount of bytes to transfer to user
  333.       remain -= count;
  334.  
  335.       // disable interrups
  336.       disable();
  337.       // reclassify bytes that were pending as unused bytes
  338.  
  339.       // decrement pending
  340.       pending -= count;
  341.       // increment unused bytes
  342.       unused_in_buffer += count;
  343.       // enable interrupts again
  344.       enable();
  345.       
  346.     }        // loop till no more devices to transfer.
  347.     return done;
  348. };
  349.  
  350. // error request.
  351. word Error( RequestPacket far *requestPacket ){
  352.     // a request packet that we don't know how to handle has been
  353.     // received, return an error to the kernel
  354.     (void)requestPacket;    // keep the warnings from the compiler down
  355.     return error | done | unknownCommand;
  356. }
  357. // request successfully.
  358. word Done( RequestPacket far *requestPacket ){
  359.     // a request packet that we don't know how to handle has been
  360.     // received, return an error to the kernel
  361.     (void)requestPacket;    // keep the warnings from the compiler down
  362.     return done ;
  363. }
  364. #if 0
  365. /***************************************************************************/
  366. //
  367. // function: VerifyAccess
  368. // input   : pointer to data, length of data, access type required
  369. // return  :  TRUE if access is allowed, False otherwise
  370. // Note    :
  371. //    - this is an example of DevHlp code using BC++ inline assembly to access
  372. //    devHlp functions. 
  373. //
  374. /***************************************************************************/
  375.  
  376. Boolean VerifyAccess( void far *data, word length, word accessType ){
  377.     // accessType = 0 for read only access
  378.     // accessType = 1 for read/write access
  379.     // returns TRUE if access is allowed, FALSE otherwise
  380.     //
  381.     asm    mov        ax,word ptr data + 2
  382.     asm mov        di,word ptr data
  383.     asm    mov        cx,length
  384.     asm    mov        dh,byte ptr accessType
  385.     asm    mov        dl,0x27                    // function code for VerifyAccess
  386.     asm    call    _devHlp
  387.     asm    jc        returnFalse
  388.     return TRUE;
  389. returnFalse:
  390.     return FALSE;
  391. }
  392. /***************************************************************************/
  393.  
  394. word GenericIOCTL( RequestPacket far *requestPacket ){
  395.     // This is the Generic IOCTL code. Currently only one category and
  396.     // one function type is supported but the structure is done in a
  397.     // way that allows easy modification to handle more categories of
  398.     // functions. 
  399.     word *wp;
  400.     byte *bp;
  401.     switch    ( requestPacket->ioctl.categoryCode ) {
  402.         case 0x80 :
  403.             // device specific IOCTL category
  404.             switch ( requestPacket->ioctl.functionCode ){
  405.                 case 0x01 :        // version name function
  406.                     // read the device driver version, it is returned to
  407.                     // the caller as a string.
  408.                     char buf[ 80 ];
  409.                     sprintf( buf, "%d.%02d%c", majorVersion, minorVersion, revision );
  410.                     if    ( VerifyAccess( requestPacket->ioctl.dataBuffer, strlen( buf ) + 1, 1 ) ){
  411.                         // we have read/write access to the callers memory where
  412.                         // the string will be copied ( 1 extra char for the NULL terminator )
  413.                         strcpy( (char *)requestPacket->ioctl.dataBuffer, buf );
  414.                         return done;
  415.                     } else {
  416.                         // the memory is not accessible, return an error
  417.                         return error | done | generalDeviceError;
  418.                     };
  419.                 case 0x02 :        // version name function
  420.                     // return the number of open files.
  421.                     if    ( VerifyAccess( requestPacket->ioctl.dataBuffer, sizeof(open_count), 1 ) ){
  422.                         // we have read/write access to the callers memory where
  423.                         // the string will be copied ( 1 extra char for the NULL terminator )
  424.                         memcpy( requestPacket->ioctl.dataBuffer, (char *)&open_count ,
  425.                             sizeof(open_count) );
  426.                         return done;
  427.                     } else {
  428.                         // the memory is not accessible, return an error
  429.                         return error | done | generalDeviceError;
  430.                     };
  431.             }    // end switch( requestPacket->ioctl.functionCode )
  432.     } // end switch    ( requestPacket->ioctl.categoryCode )
  433.     return error | done | unknownCommand;
  434. }
  435. #endif
  436. // end of file
  437.