home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
rng-810.zip
/
randdrv.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-24
|
14KB
|
437 lines
/*
*
* Copyright (c) Sirius Software 1992.
* All rights reserved.
* But the README.DOC from Sirius Software file says:
* This software is hereby placed in the public domain.
*
*/
/*
RANDDRV.SYS random number driver for RNG-810 random # or similar.
Copyright (C) 1994 Paul Elliot
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Paul.Elliott@Hrnowl.LoneStar.Org
Paul Elliott
3986 South Gessner #224 Houston TX 77063
*/
/*
* file_name = randdrv.cpp
*
* Notes :
* - created June 1, 1993 Greg Smith
* - sample OS/2 device driver. This is very brain dead and it just
* installs itself and any other call returns errors. Generic IOCTL
* is supported and is used to get the device driver version string.
*/
//#include <stdio.h>
//#include <stdarg.h>
//#include <string.h>
#include <mem.h>
#include <dos.h>
#include "randdrv.h"
#include "rand.h"
#define majorVersion 1
#define minorVersion 00
#define revision 'a'
//
// This MUST be the first data declaration that allocates space in the
// data segment
//
#if 0
// There is nothing in the c or c++ language, that requires
// that the first data item in the source file
// will be the first element in memory!
// This happens (by chance ) to work, but
// may not in future versions of the compiler/
// Therefore I am commenting this declaration out
// and declaring header in assembly lauague. PE
DeviceDriverHeader Header = {
(struct DeviceDriverHeaderStruct far *)-1L,
DAW_OPN | DAW_CHR | DAW_LEVEL1 |DAW_GIO | DAW_SHR,
//0x80c0, // character device driver, function level 001, Generic IOCTL supported
// sharable as well
Entry1, // entry point to call driver, defined in c0.asm
0,
// name of device
{ 'R', 'A', 'N', 'D', '0', '0', '0', '1' }
};
#else
extern DeviceDriverHeader Header;
#endif
// request handler routines.
extern word near Init( RequestPacket far *requestPacket );
//word near GenericIOCTL( RequestPacket far *requestPacket );
word near Error( RequestPacket far *requestPacket );
word near Done( RequestPacket far *requestPacket );
word near Open( RequestPacket far *requestPacket );
word near Close( RequestPacket far *requestPacket );
word near Deinstall( RequestPacket far *requestPacket );
word near Read( RequestPacket far *requestPacket );
word near ReadNoWait( RequestPacket far *requestPacket );
word near InputStatus( RequestPacket far *requestPacket );
DispatchFunctionType dispatchTable[] = {
Init, // 0 = Initialise
Error, // 1 = Media Check
Error, // 2 = Build Bios Parameter Block
Error, // 3 = reserved
Read, // 4 = Read
ReadNoWait, // 5 = Non Destructive Read
InputStatus, // 6 = Input Status
Error, // 7 = Input Flush
Error, // 8 = Write
Error, // 9 = Write with verify
Error, // 10 = output status
Error, // 11 = output flush
Error, // 12 = reserved
Open, // 13 = open
Close, // 14 = close
Error, // 15 = Removable Media
// GenericIOCTL, // 16 = Generic IOCTL
Error, // 16 = Generic IOCTL
Error, // 17 = Reset Media
Error, // 18 = Get Logical Drive
Error, // 19 = Set Logical Drive
Deinstall, // 20 = Deinstall
Error, // 21 = reserved
Error, // 22 = Partitionable Fixed Disk
Error, // 23= Get Fixed Disk Unit Map
Error, // 24 = reserved
Error, // 25 = reserved
Error // 26 = reserved
};
// address indicates call back address used to call back device
// helper routines.
dword near _devHlp;
// status to return.
const word done = 0x0100; //
const word error = 0x8000; // status return bit masks
const word generalDeviceError = 0x0c; //
const word unknownCommand = 0x03; // status error codes
// port to access to read random data.
unsigned int near port;
// size of random number buffers
#define BUF_SIZE 512
// buferr to hold random numbers comming form timer routine
char near buf[BUF_SIZE];
// start of above buffer
char near * near buf_start=buf;
// one byte past above buffer
char near * near buf_end=buf+BUF_SIZE;
// address of next character to read into the buffer
char near * near current_input=buf;
// addres of next character in buffer to give to application.
char near * near current_output=buf;
// This is the number of bytes of the buffer that we are currently
// moveing to various applications.
volatile word near pending=0;
// This is the number of bytes in buffer that
// do not contain unused saved random numbers that have not been given
// to a app yet
volatile word near unused_in_buffer=BUF_SIZE;
// number of bytes this request is waiting for..
// when this goes to zero, wake blocked thread.
volatile signed int near waiting_for = 0;
// number of open files.
unsigned short near open_count=0;
/***************************************************************************/
/***************************************************************************/
// main request dispatcher.
void near Strategy1( RequestPacket far *requestPacket ){
// All OS/2 device I/O passes through here
if ( requestPacket->commandCode < dim( dispatchTable ) ){
// call the appropriate packet handler
requestPacket->status = dispatchTable[ requestPacket->commandCode ]( requestPacket );
} else {
// a strange packet was received, handle the error
requestPacket->status = error | done | unknownCommand;
}
}
/***************************************************************************/
// open one file, inc open file counter.
word Open( RequestPacket far *requestPacket ){
if ( ++open_count == 1 ) TimerOn();
return(done);
}
// remove driver, turn off its timer.
word Deinstall( RequestPacket far *requestPacket ){
TimerOff();
return(done);
}
// close file, dec open file counter.
word Close( RequestPacket far *requestPacket ){
if (--open_count == 0) TimerOff();
return(done);
}
// read one byte with now wait.
word ReadNoWait( RequestPacket far *requestPacket ){
// assume buffer not empty
word busy=0;
// if no saved random bytes
if (unused_in_buffer == BUF_SIZE)
{
// declare device busy.
busy= RPBUSY;
}
else
{
// return frist char in buffer
requestPacket->nonDestructiveReadChar = *current_output;
}
// return ok
return (RPDONE |busy);
}
// if buffer has characters, OK, else return bussy
word InputStatus( RequestPacket far *requestPacket ){
return(done | ( (unused_in_buffer == BUF_SIZE)? RPBUSY : 0 ) );
}
// read request to read the buffer
word Read( RequestPacket far *requestPacket ){
// virtual address to map
auto char far* virtaddr;
// number of bytes remaining to be transfered to application.
auto word remain = requestPacket->transfer.bytesToTransfer;
// bytes used.
auto word used;
// true if the virtual address is mapped
// blocking allways undoes mapping.
auto word mapped = 0;
// while there are bytes to return...
while ( remain > 0)
{
// disable interupts, get free bytes = bytes in buffer - #of
// bytes waiting to be transfer.
// keep blocking untill we get some bytes.
while ( disable(),(used = (BUF_SIZE -unused_in_buffer) - pending),
(used == 0))
{
word count = buf_end - current_output;
if ( count > remain) count = remain;
if ( waiting_for <= 0 ) waiting_for = count;
// we are doing a block, which unmapps buffer,
// if it had been mapped.
mapped = 0;
// save current status of buffer to check for change.
word orig_unused = unused_in_buffer;
int err;
err = block(41000L,0) & 0xff;
//enable interupts, check for error.
enable();
mapped = 0;
// return errors if found
if ( ( orig_unused != unused_in_buffer) &&(err != 2) )
err=0;
if (err > 0) requestPacket->transfer.bytesToTransfer = 0;
if (err == 2)
{
return RPDONE|RPERR|ERROR_CHAR_CALL_INTERRUPTED;
}
if ( err == 1)
{
return RPDONE|RPERR|ERROR_NOT_READY;
}
}
// we fall from above loop with interrupts disabled.
// get bytes to transfer, min of
// a) space from here to end of buffer
// b) bytes remaining to transfer of those originally requested
// by user.
// c) number of bytes in buffer - # that other requests my
// be transfering.
word count = buf_end - current_output;
if ( count > remain) count = remain;
if ( count > used) count = used;
// allocate space in buffer for transfer
auto char near * pending_buffer = current_output;
// update the place in buffer to use for next requests
current_output += count;
// but wrapp around to beginning if we are at end.
if (current_output == buf_end) current_output = buf_start;
// we are now tring to tranfer count bytes, so increment
// pending by count.
pending += count;
// enable the interrups that have been disabled
enable();
// get offset within user buffer to transfer to
auto word offset =
(requestPacket->transfer.bytesToTransfer - remain);
// if there are bytes to transfer
if (count > 0) {
// if the physical address has not been mapped to
// a virtual address, or if that address has been
// invalidated by a block request, the convert the
// physical address to a virtual address
if (!mapped)
{
PhysToVirt(requestPacket->transfer.transferAddress,
requestPacket->transfer.bytesToTransfer, &virtaddr );
mapped = 1; // vir address has now bee maped.
}
// move the data to users buffer!
memmove(virtaddr+offset,(char far *)pending_buffer,count);
}
// decrement amount of bytes to transfer to user
remain -= count;
// disable interrups
disable();
// reclassify bytes that were pending as unused bytes
// decrement pending
pending -= count;
// increment unused bytes
unused_in_buffer += count;
// enable interrupts again
enable();
} // loop till no more devices to transfer.
return done;
};
// error request.
word Error( RequestPacket far *requestPacket ){
// a request packet that we don't know how to handle has been
// received, return an error to the kernel
(void)requestPacket; // keep the warnings from the compiler down
return error | done | unknownCommand;
}
// request successfully.
word Done( RequestPacket far *requestPacket ){
// a request packet that we don't know how to handle has been
// received, return an error to the kernel
(void)requestPacket; // keep the warnings from the compiler down
return done ;
}
#if 0
/***************************************************************************/
//
// function: VerifyAccess
// input : pointer to data, length of data, access type required
// return : TRUE if access is allowed, False otherwise
// Note :
// - this is an example of DevHlp code using BC++ inline assembly to access
// devHlp functions.
//
/***************************************************************************/
Boolean VerifyAccess( void far *data, word length, word accessType ){
// accessType = 0 for read only access
// accessType = 1 for read/write access
// returns TRUE if access is allowed, FALSE otherwise
//
asm mov ax,word ptr data + 2
asm mov di,word ptr data
asm mov cx,length
asm mov dh,byte ptr accessType
asm mov dl,0x27 // function code for VerifyAccess
asm call _devHlp
asm jc returnFalse
return TRUE;
returnFalse:
return FALSE;
}
/***************************************************************************/
word GenericIOCTL( RequestPacket far *requestPacket ){
// This is the Generic IOCTL code. Currently only one category and
// one function type is supported but the structure is done in a
// way that allows easy modification to handle more categories of
// functions.
word *wp;
byte *bp;
switch ( requestPacket->ioctl.categoryCode ) {
case 0x80 :
// device specific IOCTL category
switch ( requestPacket->ioctl.functionCode ){
case 0x01 : // version name function
// read the device driver version, it is returned to
// the caller as a string.
char buf[ 80 ];
sprintf( buf, "%d.%02d%c", majorVersion, minorVersion, revision );
if ( VerifyAccess( requestPacket->ioctl.dataBuffer, strlen( buf ) + 1, 1 ) ){
// we have read/write access to the callers memory where
// the string will be copied ( 1 extra char for the NULL terminator )
strcpy( (char *)requestPacket->ioctl.dataBuffer, buf );
return done;
} else {
// the memory is not accessible, return an error
return error | done | generalDeviceError;
};
case 0x02 : // version name function
// return the number of open files.
if ( VerifyAccess( requestPacket->ioctl.dataBuffer, sizeof(open_count), 1 ) ){
// we have read/write access to the callers memory where
// the string will be copied ( 1 extra char for the NULL terminator )
memcpy( requestPacket->ioctl.dataBuffer, (char *)&open_count ,
sizeof(open_count) );
return done;
} else {
// the memory is not accessible, return an error
return error | done | generalDeviceError;
};
} // end switch( requestPacket->ioctl.functionCode )
} // end switch ( requestPacket->ioctl.categoryCode )
return error | done | unknownCommand;
}
#endif
// end of file