Blame |
Last modification |
View Log
| RSS feed
//****************************************************************************
// Copyright (C) 2000-2004 ARW Elektronik Germany
//
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser 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.
//
// This product is not authorized for use as critical component in
// life support systems without the express written approval of
// ARW Elektronik Germany.
//
// Please announce changes and hints to ARW Elektronik
//
// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)
//
//****************************************************************************
//****************************************************************************
//
// cc32lib.c -- a simple access library for the PCICC32 PCI to CAMAC Interface
//
// $Log: libcc32.c,v $
// Revision 1.9 2004/11/29 20:45:36 klaus
// Bug remove. Still release libcc32.so.2.
//
// Revision 1.8 2004/11/29 20:43:12 klaus
// added _qx functions to get Q and X for every transfer. Release libcc32.so.2.
//
// Revision 1.7 2004/08/13 19:48:25 klaus
// changed license from GPL to LGPL
//
// Revision 1.6 2004/08/12 20:00:41 klaus
// conversion to kernel-version 2.6, released version 6.0
//
// Revision 1.5 2002/05/20 21:24:19 klaus
// Small changes for kernel 2.4.18
//
// Revision 1.4 2002/04/17 19:41:06 klaus
// added support for autoread
//
// Revision 1.3 2002/04/14 18:25:38 klaus
// added interrupt handling, driver 4.4. ...3.5.tar.gz
//
// Revision 1.2 2001/11/20 20:12:50 klaus
// included new header and CVS log
//
//
// first steps AR 25.02.2000
//
//****************************************************************************
/*--- INCLUDES -----------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include "../driver/pcicc32.h" /* PCI common ioctl commands and structures between driver and library */
#include "libcc32.h" /* shared header bewteen application and library */
/*--- DEFINES ------------------------------------------------------------------------------------*/
#define pwCC32_ADR(adr, N, A, F) (__u16 *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr)
#define plCC32_ADR(adr, N, A, F) (__u32 *)((N << 10) + (A << 6) + ((F & 0xF) << 2) + adr)
#define WINDOW_SIZE 32768
/*--- EXTERNALS ----------------------------------------------------------------------------------*/
/*--- TYPEDEFS -----------------------------------------------------------------------------------*/
typedef struct
{
FILE
*f
; /* the handle of this device */
int fileNo
; /* equals fileno(f) */
char *base
; /* base of range, got with mmap */
} CC32_DEVICE
;
/*--- FUNCTIONS ----------------------------------------------------------------------------------*/
static int cc32_interrupt_control
(CC32_HANDLE handle
, int enable
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
PCICC32_IRQ_CONTROL control
;
control.
bEnable = enable
;
return ioctl
(dev
->fileNo
, PCICC32_CONTROL_INTERRUPTS
, &control
);
}
static int cc32_xxxx_event
(CC32_HANDLE handle
, int *nTimeout
, int *nLam
, int nCode
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
PCICC32_STATUS state
;
int error
;
if ((error
= ioctl
(dev
->fileNo
, nCode
, &state
)))
return error
;
*nTimeout
= state.
bFail;
*nLam
= state.
bIrq;
if (state.
bFail) /* clear error */
{
if ((error
= ioctl
(dev
->fileNo
, PCICC32_IOCNTRL
, 0)))
return error
;
}
return 0;
}
static int cc32_autoread_control
(CC32_HANDLE handle
, int nOn
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
PCICC32_AUTOREAD control
;
control.
bOn = nOn
;
return ioctl
(dev
->fileNo
, PCICC32_AUTOREAD_SWITCH
, &control
);
}
static void cc32_get_qx
(CC32_DEVICE
*dev
, int *Q
, int *X
)
{
__u16 wstatus
= *pwCC32_ADR
(dev
->base
, 0, 0, 0);
*Q
= (wstatus
& 8) ? 1 : 0;
*X
= (wstatus
& 4) ? 1 : 0;
}
int cc32_open
(char *cszPath
, CC32_HANDLE
*handle
)
{
CC32_DEVICE
*dev
;
*handle
= (CC32_HANDLE
)0;
dev
= (CC32_DEVICE
*)malloc(sizeof(CC32_DEVICE
));
if (!dev
) return errno
;
dev
->fileNo
= 0;
dev
->base
= (char *)0;
if (!(dev
->f
= fopen(cszPath
,"rw")))
{
int error
= errno
;
free(dev
);
printf("Cannot Open Device %s\n",cszPath
);
return error
;
}
dev
->fileNo
= fileno
(dev
->f
);
dev
->base
= (char *)mmap
(0, WINDOW_SIZE
, PROT_READ
, MAP_FILE
| MAP_PRIVATE
, dev
->fileNo
, 0);
if (dev
->base
== (char *)-1)
{
int error
= errno
;
fclose(dev
->f
);
free(dev
);
printf("Cannot MMap Device %s\n",cszPath
);
return error
;
}
*handle
= (CC32_HANDLE
)dev
;
return 0;
}
int cc32_close
(CC32_HANDLE handle
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
int error
= 0;
if (dev
)
{
munmap
(dev
->base
, WINDOW_SIZE
);
if (dev
->f
)
fclose(dev
->f
);
else
error
= -EINVAL
;
free(dev
);
}
else
error
= -EINVAL
;
return error
;
}
__u16 cc32_read_word
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
return *pwCC32_ADR
(dev
->base
, N
, A
, F
);
}
__u16 cc32_read_word_qx
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, int *Q
, int *X
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
__u32 erg
= *plCC32_ADR
(dev
->base
, N
, A
, F
);
*Q
= (erg
& 0x80000000) ? 1 : 0;
*X
= (erg
& 0x40000000) ? 1 : 0;
return erg
& 0x0000FFFF; // get only the lower 16 bits
}
__u32 cc32_read_long_all
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
return *plCC32_ADR
(dev
->base
, N
, A
, F
);;
}
__u32 cc32_read_long
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
__u32 erg
= *plCC32_ADR
(dev
->base
, N
, A
, F
);
return erg
& 0x00FFFFFF;
}
__u32 cc32_read_long_qx
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, int *Q
, int *X
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
__u32 erg
= *plCC32_ADR
(dev
->base
, N
, A
, F
);
*Q
= (erg
& 0x80000000) ? 1 : 0;
*X
= (erg
& 0x40000000) ? 1 : 0;
return erg
& 0x00FFFFFF;
}
void cc32_write_word
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, __u16 uwData
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
*pwCC32_ADR
(dev
->base
, N
, A
, F
) = uwData
;
}
void cc32_write_word_qx
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, __u16 uwData
, int *Q
, int *X
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
*pwCC32_ADR
(dev
->base
, N
, A
, F
) = uwData
;
cc32_get_qx
(dev
, Q
, X
);
}
void cc32_write_long
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, __u32 ulData
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
*plCC32_ADR
(dev
->base
, N
, A
, F
) = ulData
;
}
void cc32_write_long_qx
(CC32_HANDLE handle
, unsigned int N
, unsigned int A
, unsigned int F
, __u32 ulData
, int *Q
, int *X
)
{
CC32_DEVICE
*dev
= (CC32_DEVICE
*)handle
;
*plCC32_ADR
(dev
->base
, N
, A
, F
) = ulData
;
cc32_get_qx
(dev
, Q
, X
);
}
int cc32_poll_event
(CC32_HANDLE handle
, int *nTimeout
, int *nLam
)
{
return cc32_xxxx_event
(handle
, nTimeout
, nLam
, PCICC32_IOSTATE
);
}
int cc32_wait_event
(CC32_HANDLE handle
, int *nTimeout
, int *nLam
)
{
return cc32_xxxx_event
(handle
, nTimeout
, nLam
, PCICC32_IOSTATE_BLOCKING
);
}
int cc32_interrupt_disable
(CC32_HANDLE handle
)
{
return cc32_interrupt_control
(handle
, 0);
}
int cc32_interrupt_enable
(CC32_HANDLE handle
)
{
return cc32_interrupt_control
(handle
, 1);
}
int cc32_autoread_on
(CC32_HANDLE handle
)
{
return cc32_autoread_control
(handle
, 1);
}
int cc32_autoread_off
(CC32_HANDLE handle
)
{
return cc32_autoread_control
(handle
, 0);
}