Subversion Repositories f9daq

Rev

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);
}