sane-project-backends/backend/plustek-pp_misc.c

939 wiersze
22 KiB
C
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*.............................................................................
* Project : linux driver for Plustek parallel-port scanners
*.............................................................................
* File: plustek-pp_misc.c - here we have some helpful functions
*.............................................................................
*
* based on sources acquired from Plustek Inc.
* Copyright (C) 1998 Plustek Inc.
* Copyright (C) 2000-2003 Gerhard Jaeger <gerhard@gjaeger.de>
* also based on the work done by Rick Bronson
*.............................................................................
* History:
* 0.30 - initial version
* 0.31 - no changes
* 0.32 - moved the parport functions inside this module
* now using the information, the parport-driver provides
* for selecting the port-mode this driver uses
* 0.33 - added code to use faster portmodes
* 0.34 - added sample code for changing from ECP to PS/2 bidi mode
* 0.35 - added Kevins´ changes (new function miscSetFastMode())
* moved function initPageSettings() to module models.c
* 0.36 - added random generator
* added additional debug messages
* changed prototype of MiscInitPorts()
* added miscPreemptionCallback()
* 0.37 - changed inb_p/outb_p to macro calls (kernel-mode)
* added MiscGetModelName()
* added miscShowPortModes()
* 0.38 - fixed a small bug in MiscGetModelName()
* 0.39 - added forceMode support
* 0.40 - no changes
* 0.41 - merged Kevins' patch to make EPP(ECP) work
* 0.42 - changed get_fast_time to _GET_TIME
* changed include names
*
*.............................................................................
*
* 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.
*/
#include "plustek-pp_scan.h"
/*************************** some definitions ********************************/
#ifndef __KERNEL__
#define PPA_PROBE_SPP 0x0001
#define PPA_PROBE_PS2 0x0002
#define PPA_PROBE_ECR 0x0010
#define PPA_PROBE_EPP17 0x0100
#define PPA_PROBE_EPP19 0x0200
#else
/*
* the parport driver in Kernel 2.4 has changed. It does report the
* possible modes in a different, more general way. As long, as
* we do not use the parport-module change mode facility, I assume
* the following correlations
*/
#if defined LINUX_24 || defined LINUX_26
# define PARPORT_MODE_PCPS2 PARPORT_MODE_TRISTATE
# define PARPORT_MODE_PCEPP PARPORT_MODE_EPP
# define PARPORT_MODE_PCECPPS2 PARPORT_MODE_TRISTATE
# define PARPORT_MODE_PCECPEPP PARPORT_MODE_EPP
# define PARPORT_MODE_PCECR PARPORT_MODE_ECP
#endif
#endif
#define _A 16807 /* multiplier */
#define _M 2147483647L /* 2**31 - 1 */
#define _Q 127773L /* m div a */
#define _R 2836 /* m mod a */
/*************************** some local vars *********************************/
static int port_feature;
static long randomnum = 1;
static int portIsClaimed[_MAX_PTDEVS] = { [0 ... (_MAX_PTDEVS-1)] = 0 };
#ifdef __KERNEL__
MODELSTR; /* is a static char array (see plustek-share.h) */
#endif
/*************************** local functions *********************************/
/** display the avaialable port-modes
*/
#ifdef DEBUG
static void miscShowPortModes( int modes )
{
DBG( DBG_LOW, "parport-modi:" );
#ifdef __KERNEL__
if( modes & PARPORT_MODE_PCSPP )
DBG( DBG_LOW, " SPP" );
if( modes & PARPORT_MODE_PCPS2 )
DBG( DBG_LOW, " PS/2" );
if( modes & PARPORT_MODE_PCEPP )
DBG( DBG_LOW, " EPP" );
if( modes & PARPORT_MODE_PCECR )
DBG( DBG_LOW, " ECP" );
if( modes & PARPORT_MODE_PCECPEPP )
DBG( DBG_LOW, " EPP(ECP)" );
if( modes & PARPORT_MODE_PCECPPS2 )
DBG( DBG_LOW, " PS/2(ECP)" );
#else
if( modes & PPA_PROBE_SPP )
DBG( DBG_LOW, " SPP" );
if( modes & PPA_PROBE_PS2 )
DBG( DBG_LOW, " PS/2" );
if( modes & PPA_PROBE_EPP17 )
DBG( DBG_LOW, " EPP17" );
if( modes & PPA_PROBE_EPP19 )
DBG( DBG_LOW, " EPP19" );
if( modes & PPA_PROBE_ECR )
DBG( DBG_LOW, " ECP" );
#endif
DBG( DBG_LOW, "\n" );
}
#endif
/** probe the parallel port
*/
static int initPortProbe( pScanData ps )
{
int retv = 0;
#ifndef __KERNEL__
UShort port;
UChar a, b, c;
UInt i, j;
#endif
/*
* clear the controls
*/
ps->IO.lastPortMode = 0xFFFF;
#ifdef __KERNEL__
if( NULL != ps->pardev )
retv = ps->pardev->port->modes;
#else
port = ps->IO.portBase;
DBG(DBG_SCAN, "Probing port 0x%04x\n", port);
/* ##### ###### ######
* # # # # # #
* # # # # #
* ##### ###### ######
* # # #
* # # # #
* ##### # #
*/
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
outb(0x55, port);
a = inb(port);
if (a != 0x55)
return retv;
DBG(DBG_SCAN, " SPP port present\n");
retv += PPA_PROBE_SPP;
/* ####### ##### ######
* # # # # #
* # # # #
* ##### # ######
* # # #
* # # # #
* ####### ##### #
*/
for (i = 1024; i > 0; i--) { /* clear at most 1k of data from FIFO */
a = inb(port + 0x402);
if ((a & 0x03) == 0x03)
goto no_ecp;
if (a & 0x01)
break;
inb(port + 0x400); /* Remove byte from FIFO */
}
if (i <= 0)
goto no_ecp;
b = a ^ 3;
outb(b, port + 0x402);
c = inb(port + 0x402);
if (a == c) {
outb(0xc0, port + 0x402); /* FIFO test */
j = 0;
while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
inb(port + 0x400);
j++;
}
if (j >= 1024)
goto no_ecp;
i = 0;
j = 0;
while (!(inb(port + 0x402) & 0x02) && (j < 1024)) {
outb(0x00, port + 0x400);
i++;
j++;
}
if (j >= 1024)
goto no_ecp;
j = 0;
while (!(inb(port + 0x402) & 0x01) && (j < 1024)) {
inb(port + 0x400);
j++;
}
if (j >= 1024)
goto no_ecp;
DBG(DBG_SCAN, " ECP with a %i byte FIFO present\n", i);
retv += PPA_PROBE_ECR;
}
/* ###### ##### #####
* # # # # # #
* # # # #
* ###### ##### #####
* # # #
* # # # #
* # ##### #######
*/
no_ecp:
if (retv & PPA_PROBE_ECR)
outb(0x20, port + 0x402);
outb(0x55, port);
outb(0x0c, port + 2);
a = inb(port);
outb(0x55, port);
outb(0x2c, port + 2);
b = inb(port);
if (a != b) {
DBG(DBG_SCAN, " PS/2 bidirectional port present\n");
retv += PPA_PROBE_PS2;
}
/* ####### ###### ######
* # # # # #
* # # # # #
* ##### ###### ######
* # # #
* # # #
* ####### # #
*/
if (port & 0x007) {
DBG(DBG_SCAN, " EPP not supported at this address\n");
return retv;
}
if (retv & PPA_PROBE_ECR) {
for (i = 0x00; i < 0x80; i += 0x20) {
outb(i, port + 0x402);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
a = inb(port + 1);
if (!(a & 0x01)) {
DBG(DBG_SCAN, " Failed Intel bug check. (Phony EPP in ECP)\n");
return retv;
}
}
DBG(DBG_SCAN, " Passed Intel bug check.\n");
outb(0x80, port + 0x402);
}
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
a = inb(port + 1);
if (a & 0x01) {
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
return retv;
}
outb(0x04, port + 2);
inb(port + 4);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
if (a & 0x01) {
DBG(DBG_SCAN, " EPP 1.9 with hardware direction protocol\n");
retv += PPA_PROBE_EPP19;
} else {
/* The EPP timeout bit was not set, this could either be:
* EPP 1.7
* EPP 1.9 with software direction
*/
outb(0x24, port + 2);
inb(port + 4);
a = inb(port + 1);
outb(a, port + 1);
outb(a & 0xfe, port + 1);
if (a & 0x01) {
DBG(DBG_SCAN, " EPP 1.9 with software direction protocol\n");
retv += PPA_PROBE_EPP19;
} else {
DBG(DBG_SCAN, " EPP 1.7\n");
retv += PPA_PROBE_EPP17;
}
}
outb(0x0c, port + 0x402);
outb(0x0c, port + 0x002);
#endif
return retv;
}
#ifdef __KERNEL__
/** will be called by the parport module when we already have access, but
* another module wants access to the port...
*/
static int miscPreemptionCallback( pVoid data )
{
pScanData ps = (pScanData)data;
if( NULL != ps ) {
/* never release during scanning */
if( ps->DataInf.dwScanFlag & _SCANNER_SCANNING ) {
DBG( DBG_LOW, "no way!!!\n" );
return 1;
}
}
/* let the port go...*/
return 0;
}
/** depending on the reported possible port modes, we try to set a faster mode
* than SPP
*/
static int miscSetFastMode( pScanData ps )
{
UChar a, b;
/*
* when previously found the EPP mode, break right here
*/
if (( _PORT_EPP == ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR)))
return _OK;
/* CHECK REMOVE: from here we should have SPP (Paranoia Code !) */
if (( _PORT_SPP != ps->IO.portMode ) && (!(port_feature & PARPORT_MODE_PCECR)))
return _OK;
DBG(DBG_LOW, "Trying faster mode...\n" );
/*
* ECP mode usually has sub-modes of EPP and/or PS2.
* First we try to set EPP
*/
if((port_feature & PARPORT_MODE_PCECR) &&
(port_feature & PARPORT_MODE_PCECPEPP)){
DBG(DBG_LOW, "Attempting to set EPP from ECP mode.\n" );
a = _INB_ECTL(ps); /* get current ECR */
ps->IO.lastPortMode = a; /* save it for restoring later */
a = (a & 0x1F) | 0x80; /* set to EPP */
_OUTB_ECTL(ps, a); /* write it back */
_DO_UDELAY(1);
/*
* It is probably unnecessary to
* do this check but it makes me feel better
*/
b = _INB_ECTL(ps); /* check to see if port set */
if( a == b ) {
DBG( DBG_LOW, "Port is set to (ECP) EPP mode.\n" );
ps->IO.portMode = _PORT_EPP;
return _OK;
} else {
DBG( DBG_LOW, "Port could not be set to (ECP) EPP mode. "
"Using SPP mode.\n" );
_OUTB_ECTL(ps,(Byte)ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
/* go ahead and try with other settings...*/
}
}
/* If port cannot be set to EPP, try PS2 */
if((port_feature & PARPORT_MODE_PCECR) &&
(port_feature & PARPORT_MODE_PCECPPS2)) {
DBG(DBG_LOW, "Attempting to set PS2 from ECPPS2 mode.\n" );
a = _INB_ECTL(ps); /* get current ECR */
ps->IO.lastPortMode = a; /* save it for restoring later */
/* set to Fast Centronics/bi-directional/PS2 */
a = (a & 0x1F) | 0x20;
_OUTB_ECTL(ps,a); /* write it back */
_DO_UDELAY(1);
/*
* It is probably unnecessary to do this check
* but it makes me feel better
*/
b = _INB_ECTL(ps); /* check to see if port set */
if (a == b) {
DBG(DBG_LOW, "Port is set to (ECP) PS2 bidirectional mode.\n");
ps->IO.portMode = _PORT_BIDI;
return _OK;
} else {
DBG(DBG_LOW, "Port could not be set to (ECP) PS2 mode. "
"Using SPP mode.\n");
_OUTB_ECTL(ps,ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
/* next mode, last attempt... */
}
}
/*
* Some BIOS/cards have only a Bi-directional/PS2 mode (no EPP).
* Make one last attemp to set to PS2 mode.
*/
if ( port_feature & PARPORT_MODE_PCPS2 ){
DBG(DBG_LOW, "Attempting to set PS2 mode.\n" );
a = _INB_CTRL(ps); /* get current setting of control register*/
ps->IO.lastPortMode = a; /* save it for restoring later */
a = a | 0x20; /* set bit 5 of control reg */
_OUTB_CTRL(ps,a); /* set to Fast Centronics/bi-directional/PS2 */
_DO_UDELAY(1);
a = 0;
_OUTB_DATA(ps,0x55);
_DO_UDELAY(1);
if ((inb(ps->IO.portBase)) != 0x55) /* read data */
a++;
_OUTB_DATA(ps,0xAA);
_DO_UDELAY(1);
if (_INB_DATA(ps) != 0xAA) /* read data */
a++;
if (2 == a) {
DBG(DBG_LOW, "Port is set to PS2 bidirectional mode.\n");
ps->IO.portMode = _PORT_BIDI;
return _OK;
}
else {
DBG(DBG_LOW, "Port could not be set to PS2 mode. "
"Using SPP mode.\n");
_OUTB_CTRL(ps,(Byte)ps->IO.lastPortMode); /* restore */
_DO_UDELAY(1);
ps->IO.portMode = _PORT_SPP;
}
}
/*
* reaching this point, we´re back in SPP mode and there´s no need
* to restore at shutdown...
*/
ps->IO.lastPortMode = 0xFFFF;
return _OK;
}
#endif
/** check the state of the par-port and switch to EPP-mode if possible
*/
static int miscSetPortMode( pScanData ps )
{
#ifndef __KERNEL__
if (iopl(3)) {
DBG( DBG_HIGH, "Could not unlock IO ports. Are you superuser?\n" );
return _E_LOCK;
}
#endif
/*
* try to detect the port settings, SPP seems to work in any case !
*/
port_feature = initPortProbe( ps );
#ifdef DEBUG
miscShowPortModes( port_feature );
#endif
switch( ps->IO.forceMode ) {
case 1:
DBG( DBG_LOW, "Use of SPP-mode enforced\n" );
ps->IO.portMode = _PORT_SPP;
return _OK;
break;
case 2:
DBG( DBG_LOW, "Use of EPP-mode enforced\n" );
ps->IO.portMode = _PORT_EPP;
return _OK;
break;
default:
break;
}
#ifdef __KERNEL__
if( !(port_feature & PARPORT_MODE_PCEPP)) {
if( !(port_feature & PARPORT_MODE_PCSPP )) {
_PRINT("\nThis Port supports not the SPP- or EPP-Mode\n" );
_PRINT("Please activate SPP-Mode, EPP-Mode or\nEPP + ECP-Mode!\n");
return _E_NOSUPP;
} else {
DBG(DBG_LOW, "Using SPP-mode\n" );
ps->IO.portMode = _PORT_SPP;
}
#else
if (!(port_feature & (PPA_PROBE_EPP17 | PPA_PROBE_EPP19))){
if( !(port_feature & PPA_PROBE_SPP )) {
DBG(DBG_HIGH,"\nThis Port supports not the SPP- or EPP-Mode\n");
DBG(DBG_HIGH,"Please activate SPP-Mode, EPP-Mode or\n"
"EPP + ECP-Mode!\n");
return _E_NOSUPP;
} else {
DBG(DBG_LOW, "Using SPP-mode\n" );
ps->IO.portMode = _PORT_SPP;
}
#endif
} else {
DBG(DBG_LOW, "Using EPP-mode\n" );
ps->IO.portMode = _PORT_EPP;
}
#ifdef __KERNEL__
/* else try to set to a faster mode than SPP */
return miscSetFastMode( ps );
#else
return _OK;
#endif
}
/** miscNextLongRand() -- generate 2**31-2 random numbers
**
** public domain by Ray Gardner
**
** based on "Random Number Generators: Good Ones Are Hard to Find",
** S.K. Park and K.W. Miller, Communications of the ACM 31:10 (Oct 1988),
** and "Two Fast Implementations of the 'Minimal Standard' Random
** Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), p. 87-88
**
** linear congruential generator f(z) = 16807 z mod (2 ** 31 - 1)
**
** uses L. Schrage's method to avoid overflow problems
*/
static Long miscNextLongRand( Long seed )
{
ULong lo, hi;
lo = _A * (Long)(seed & 0xFFFF);
hi = _A * (Long)((ULong)seed >> 16);
lo += (hi & 0x7FFF) << 16;
if (lo > _M) {
lo &= _M;
++lo;
}
lo += hi >> 15;
if (lo > _M) {
lo &= _M;
++lo;
}
return (Long)lo;
}
/** initialize the random number generator
*/
static void miscSeedLongRand( ULong seed )
{
randomnum = seed ? (seed & _M) : 1; /* nonzero seed */
}
/************************ exported functions *********************************/
/** allocate and initialize some memory for the scanner structure
*/
pScanData MiscAllocAndInitStruct( void )
{
pScanData ps;
ps = (pScanData)_KALLOC(sizeof(ScanData), GFP_KERNEL);
if( NULL != ps ) {
MiscReinitStruct( ps );
}
DBG( DBG_HIGH, "ScanData = 0x%08lx\n", (ULong)ps );
return ps;
}
/** re-initialize the memory for the scanner structure
*/
int MiscReinitStruct( pScanData ps )
{
if( NULL == ps )
return _E_NULLPTR;
memset( ps, 0, sizeof(ScanData));
/*
* first init all constant stuff in ScanData
*/
ps->sCaps.Version = ((_PTDRV_V1 << 8) | _PTDRV_V0);
ps->bCurrentSpeed = 1;
ps->sCaps.wLens = 1; /* set wNumberOfLens */
ps->pbMapRed = ps->a_bMapTable;
ps->pbMapGreen = &ps->a_bMapTable[256];
ps->pbMapBlue = &ps->a_bMapTable[512];
ps->sCaps.wIOBase = _NO_BASE;
/* use memory address to seed the generator */
miscSeedLongRand((Long)ps);
DBG( DBG_HIGH, "Init settings done\n" );
return _OK;
}
/** in USER-Mode: probe the specified port and try to get the port-mode
* in KERNEL-Mode: only use the modes, the driver returns
*/
int MiscInitPorts( pScanData ps, int port )
{
int status;
if( NULL == ps )
return _E_NULLPTR;
/*
* Get access to the ports
*/
ps->IO.portBase = (UShort)port;
status = miscSetPortMode(ps);
if( _OK != status ) {
ps->sCaps.wIOBase = _NO_BASE;
ps->IO.portBase = _NO_BASE;
return status;
}
/*
* the port settings
*/
ps->IO.pbSppDataPort = (UShort)port;
ps->IO.pbStatusPort = (UShort)port+1;
ps->IO.pbControlPort = (UShort)port+2;
ps->IO.pbEppDataPort = (UShort)port+_EPPDATA_PORT;
return _OK;
}
/** here we restore the port
*/
void MiscRestorePort( pScanData ps )
{
if( 0 == ps->IO.pbSppDataPort )
return;
DBG(DBG_LOW,"MiscRestorePort()\n");
/* don´t restore if not necessary */
if( 0xFFFF == ps->IO.lastPortMode ) {
DBG(DBG_LOW,"- no need to restore portmode !\n");
return;
}
/*Restore Port-Mode*/
#ifdef __KERNEL__
if (port_feature & PARPORT_MODE_PCECR ){
_OUTB_ECTL( ps, (Byte)ps->IO.lastPortMode );
_DO_UDELAY(1);
} else {
_OUTB_CTRL( ps, (Byte)ps->IO.lastPortMode );
_DO_UDELAY(1);
}
#else
if (port_feature & PPA_PROBE_ECR ){
outb( ps->IO.lastPortMode, ps->IO.pbSppDataPort + 0x402);
}
#endif
}
/** starts a timer
*/
inline void MiscStartTimer( pTimerDef timer , unsigned long us)
{
struct timeval start_time;
#ifdef __KERNEL__
_GET_TIME( &start_time );
#else
gettimeofday(&start_time, NULL);
#endif
*timer = start_time.tv_sec * 1e6 + start_time.tv_usec + us;
}
/** checks for timeout
*/
inline int MiscCheckTimer( pTimerDef timer )
{
struct timeval current_time;
#ifdef __KERNEL__
_GET_TIME( &current_time );
#else
gettimeofday(&current_time, NULL);
#endif
if (current_time.tv_sec * 1e6 + current_time.tv_usec > *timer) {
return _E_TIMEOUT;
} else {
#ifdef __KERNEL__
schedule();
#else
sched_yield();
#endif
return _OK;
}
}
/** checks the function pointers
*/
#ifdef DEBUG
Bool MiscAllPointersSet( pScanData ps )
{
ULong i;
pULong ptr;
for( ptr = (pULong)&ps->OpenScanPath, i = 1;
ptr <= (pULong)&ps->ReadOneImageLine; ptr++, i++ ) {
if( NULL == (pVoid)*ptr ) {
DBG( DBG_HIGH, "Function pointer not set (pos = %lu) !\n", i );
return _FALSE;
}
}
return _TRUE;
}
#endif
/** registers this driver to use port "portAddr" (KERNEL-Mode only)
*/
int MiscRegisterPort( pScanData ps, int portAddr )
{
#ifndef __KERNEL__
int i;
Bool found;
ULong pref[] = { 0x378, 0x278, 0x3bc, 0xFFFFFFFF };
DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr );
_VAR_NOT_USED( ps );
/*
* check the port address !!!!
*/
found = _FALSE;
for( i = 0; 0xFFFFFFFF != pref[i]; i++ ) {
if(((ULong)portAddr != 0xFFFFFFFF) && (pref[i] == (ULong)portAddr)) {
found = _TRUE;
break;
}
}
if( !found )
return _E_INVALID;
#else
struct parport *pp;
DBG( DBG_LOW, "Requested port at 0x%02x\n", portAddr );
pp = parport_enumerate();
ps->pardev = NULL;
if( NULL == pp ) {
return _E_PORTSEARCH;
}
/*
* go through the list
*/
for( ps->pp = NULL; NULL != pp; ) {
if( pp->base == portAddr ) {
DBG( DBG_LOW, "Requested port (0x%02x) found\n", portAddr );
DBG( DBG_LOW, "Port mode reported: (0x%04x)\n", pp->modes );
ps->pp = pp;
break;
}
pp = pp->next;
}
if( NULL == ps->pp ) {
return _E_NO_PORT;
}
/*
* register this device
*/
ps->pardev = parport_register_device( ps->pp, "Plustek Driver",
miscPreemptionCallback, NULL, NULL, 0, (pVoid)ps );
if( NULL == ps->pardev ) {
return _E_REGISTER;
}
DBG( DBG_LOW, "Port for device %lu registered\n", ps->devno );
#endif
portIsClaimed[ps->devno] = 0;
return _OK;
}
/** unregisters the port from driver (KERNEL-Mode only)
*/
void MiscUnregisterPort( pScanData ps )
{
#ifdef __KERNEL__
if( NULL != ps->pardev ) {
DBG( DBG_LOW, "Port unregistered\n" );
parport_unregister_device( ps->pardev );
}
#else
_VAR_NOT_USED( ps );
#endif
}
/*.............................................................................
* try to claim the port (KERNEL-Mode only)
*/
int MiscClaimPort( pScanData ps )
{
#ifdef __KERNEL__
if( 0 == portIsClaimed[ps->devno] ) {
DBG( DBG_HIGH, "Try to claim the parport\n" );
if( 0 != parport_claim( ps->pardev ))
return _E_BUSY;
}
#endif
portIsClaimed[ps->devno]++;
return _OK;
}
/*.............................................................................
* release previously claimed port (KERNEL-Mode only)
*/
void MiscReleasePort( pScanData ps )
{
if( portIsClaimed[ps->devno] > 0 ) {
portIsClaimed[ps->devno]--;
#ifdef __KERNEL__
if( 0 == portIsClaimed[ps->devno] ) {
DBG( DBG_HIGH, "Releasing parport\n" );
parport_release( ps->pardev );
}
#endif
}
}
/*.............................................................................
* get random number
*/
Long MiscLongRand( void )
{
randomnum = miscNextLongRand( randomnum );
return randomnum;
}
/*.............................................................................
* according to the id, the function returns a pointer to the model name
*/
const char *MiscGetModelName( UShort id )
{
DBG( DBG_HIGH, "MiscGetModelName - id = %i\n", id );
if( MODEL_OP_PT12 < id )
return ModelStr[0];
return ModelStr[id];
}
/* END PLUSTEK-PP_MISC.C ....................................................*/