summaryrefslogtreecommitdiffstats
path: root/drivers/staging/me4000/me4000.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/me4000/me4000.c')
-rw-r--r--drivers/staging/me4000/me4000.c6109
1 files changed, 0 insertions, 6109 deletions
diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c
deleted file mode 100644
index 01017b731d0b..000000000000
--- a/drivers/staging/me4000/me4000.c
+++ /dev/null
@@ -1,6109 +0,0 @@
-/* Device driver for Meilhaus ME-4000 board family.
- * ================================================
- *
- * Copyright (C) 2003 Meilhaus Electronic GmbH (support@meilhaus.de)
- *
- * This file 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.
- *
- * Author: Guenter Gebhardt <g.gebhardt@meilhaus.de>
- */
-
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/mm.h>
-#include <linux/unistd.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/types.h>
-#include <linux/poll.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <asm/pgtable.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <asm/system.h>
-
-/* Include-File for the Meilhaus ME-4000 I/O board */
-#include "me4000.h"
-#include "me4000_firmware.h"
-#include "me4610_firmware.h"
-
-/* Administrative stuff for modinfo */
-MODULE_AUTHOR("Guenter Gebhardt <g.gebhardt@meilhaus.de>");
-MODULE_DESCRIPTION
- ("Device Driver Module for Meilhaus ME-4000 boards version 1.0.5");
-MODULE_SUPPORTED_DEVICE("Meilhaus ME-4000 Multi I/O boards");
-MODULE_LICENSE("GPL");
-
-/* Board specific data are kept in a global list */
-static LIST_HEAD(me4000_board_info_list);
-
-/* Major Device Numbers. 0 means to get it automatically from the System */
-static int me4000_ao_major_driver_no;
-static int me4000_ai_major_driver_no;
-static int me4000_dio_major_driver_no;
-static int me4000_cnt_major_driver_no;
-static int me4000_ext_int_major_driver_no;
-
-/* Let the user specify a custom major driver number */
-module_param(me4000_ao_major_driver_no, int, 0);
-MODULE_PARM_DESC(me4000_ao_major_driver_no,
- "Major driver number for analog output (default 0)");
-
-module_param(me4000_ai_major_driver_no, int, 0);
-MODULE_PARM_DESC(me4000_ai_major_driver_no,
- "Major driver number for analog input (default 0)");
-
-module_param(me4000_dio_major_driver_no, int, 0);
-MODULE_PARM_DESC(me4000_dio_major_driver_no,
- "Major driver number digital I/O (default 0)");
-
-module_param(me4000_cnt_major_driver_no, int, 0);
-MODULE_PARM_DESC(me4000_cnt_major_driver_no,
- "Major driver number for counter (default 0)");
-
-module_param(me4000_ext_int_major_driver_no, int, 0);
-MODULE_PARM_DESC(me4000_ext_int_major_driver_no,
- "Major driver number for external interrupt (default 0)");
-
-/*-----------------------------------------------------------------------------
- Board detection and initialization
- ---------------------------------------------------------------------------*/
-static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id);
-static int me4000_xilinx_download(struct me4000_info *);
-static int me4000_reset_board(struct me4000_info *);
-
-static void clear_board_info_list(void);
-static void release_ao_contexts(struct me4000_info *board_info);
-/*-----------------------------------------------------------------------------
- Stuff used by all device parts
- ---------------------------------------------------------------------------*/
-static int me4000_open(struct inode *, struct file *);
-static int me4000_release(struct inode *, struct file *);
-
-static int me4000_get_user_info(struct me4000_user_info *,
- struct me4000_info *board_info);
-static int me4000_read_procmem(char *, char **, off_t, int, int *, void *);
-
-/*-----------------------------------------------------------------------------
- Analog output stuff
- ---------------------------------------------------------------------------*/
-static ssize_t me4000_ao_write_sing(struct file *, const char *, size_t,
- loff_t *);
-static ssize_t me4000_ao_write_wrap(struct file *, const char *, size_t,
- loff_t *);
-static ssize_t me4000_ao_write_cont(struct file *, const char *, size_t,
- loff_t *);
-
-static int me4000_ao_ioctl_sing(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int me4000_ao_ioctl_wrap(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int me4000_ao_ioctl_cont(struct inode *, struct file *, unsigned int,
- unsigned long);
-
-static unsigned int me4000_ao_poll_cont(struct file *, poll_table *);
-static int me4000_ao_fsync_cont(struct file *, struct dentry *, int);
-
-static int me4000_ao_start(unsigned long *, struct me4000_ao_context *);
-static int me4000_ao_stop(struct me4000_ao_context *);
-static int me4000_ao_immediate_stop(struct me4000_ao_context *);
-static int me4000_ao_timer_set_divisor(u32 *, struct me4000_ao_context *);
-static int me4000_ao_preload(struct me4000_ao_context *);
-static int me4000_ao_preload_update(struct me4000_ao_context *);
-static int me4000_ao_ex_trig_set_edge(int *, struct me4000_ao_context *);
-static int me4000_ao_ex_trig_enable(struct me4000_ao_context *);
-static int me4000_ao_ex_trig_disable(struct me4000_ao_context *);
-static int me4000_ao_prepare(struct me4000_ao_context *ao_info);
-static int me4000_ao_reset(struct me4000_ao_context *ao_info);
-static int me4000_ao_enable_do(struct me4000_ao_context *);
-static int me4000_ao_disable_do(struct me4000_ao_context *);
-static int me4000_ao_fsm_state(int *, struct me4000_ao_context *);
-
-static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context);
-static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context);
-static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context);
-static int me4000_ao_simultaneous_update(
- struct me4000_ao_channel_list *channels,
- struct me4000_ao_context *ao_context);
-
-static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context);
-static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context);
-static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context);
-
-static int me4000_ao_ex_trig_timeout(unsigned long *arg,
- struct me4000_ao_context *ao_context);
-static int me4000_ao_get_free_buffer(unsigned long *arg,
- struct me4000_ao_context *ao_context);
-
-/*-----------------------------------------------------------------------------
- Analog input stuff
- ---------------------------------------------------------------------------*/
-static int me4000_ai_single(struct me4000_ai_single *,
- struct me4000_ai_context *);
-static int me4000_ai_ioctl_sing(struct inode *, struct file *, unsigned int,
- unsigned long);
-
-static ssize_t me4000_ai_read(struct file *, char *, size_t, loff_t *);
-static int me4000_ai_ioctl_sw(struct inode *, struct file *, unsigned int,
- unsigned long);
-static unsigned int me4000_ai_poll(struct file *, poll_table *);
-static int me4000_ai_fasync(int fd, struct file *file_p, int mode);
-
-static int me4000_ai_ioctl_ext(struct inode *, struct file *, unsigned int,
- unsigned long);
-
-static int me4000_ai_prepare(struct me4000_ai_context *ai_context);
-static int me4000_ai_reset(struct me4000_ai_context *ai_context);
-static int me4000_ai_config(struct me4000_ai_config *,
- struct me4000_ai_context *);
-static int me4000_ai_start(struct me4000_ai_context *);
-static int me4000_ai_start_ex(unsigned long *, struct me4000_ai_context *);
-static int me4000_ai_stop(struct me4000_ai_context *);
-static int me4000_ai_immediate_stop(struct me4000_ai_context *);
-static int me4000_ai_ex_trig_enable(struct me4000_ai_context *);
-static int me4000_ai_ex_trig_disable(struct me4000_ai_context *);
-static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *,
- struct me4000_ai_context *);
-static int me4000_ai_sc_setup(struct me4000_ai_sc *arg,
- struct me4000_ai_context *ai_context);
-static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context);
-static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context);
-static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context);
-static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context);
-static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context);
-static int me4000_ai_get_count_buffer(unsigned long *arg,
- struct me4000_ai_context *ai_context);
-
-/*-----------------------------------------------------------------------------
- EEPROM stuff
- ---------------------------------------------------------------------------*/
-static int me4000_eeprom_read(struct me4000_eeprom *arg,
- struct me4000_ai_context *ai_context);
-static int me4000_eeprom_write(struct me4000_eeprom *arg,
- struct me4000_ai_context *ai_context);
-
-/*-----------------------------------------------------------------------------
- Digital I/O stuff
- ---------------------------------------------------------------------------*/
-static int me4000_dio_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int me4000_dio_config(struct me4000_dio_config *,
- struct me4000_dio_context *);
-static int me4000_dio_get_byte(struct me4000_dio_byte *,
- struct me4000_dio_context *);
-static int me4000_dio_set_byte(struct me4000_dio_byte *,
- struct me4000_dio_context *);
-static int me4000_dio_reset(struct me4000_dio_context *);
-
-/*-----------------------------------------------------------------------------
- Counter stuff
- ---------------------------------------------------------------------------*/
-static int me4000_cnt_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int me4000_cnt_config(struct me4000_cnt_config *,
- struct me4000_cnt_context *);
-static int me4000_cnt_read(struct me4000_cnt *, struct me4000_cnt_context *);
-static int me4000_cnt_write(struct me4000_cnt *, struct me4000_cnt_context *);
-static int me4000_cnt_reset(struct me4000_cnt_context *);
-
-/*-----------------------------------------------------------------------------
- External interrupt routines
- ---------------------------------------------------------------------------*/
-static int me4000_ext_int_ioctl(struct inode *, struct file *, unsigned int,
- unsigned long);
-static int me4000_ext_int_enable(struct me4000_ext_int_context *);
-static int me4000_ext_int_disable(struct me4000_ext_int_context *);
-static int me4000_ext_int_count(unsigned long *arg,
- struct me4000_ext_int_context *ext_int_context);
-static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode);
-
-/*-----------------------------------------------------------------------------
- The interrupt service routines
- ---------------------------------------------------------------------------*/
-static irqreturn_t me4000_ao_isr(int, void *);
-static irqreturn_t me4000_ai_isr(int, void *);
-static irqreturn_t me4000_ext_int_isr(int, void *);
-
-/*-----------------------------------------------------------------------------
- Inline functions
- ---------------------------------------------------------------------------*/
-
-static inline int me4000_buf_count(struct me4000_circ_buf buf, int size)
-{
- return (buf.head - buf.tail) & (size - 1);
-}
-
-static inline int me4000_buf_space(struct me4000_circ_buf buf, int size)
-{
- return (buf.tail - (buf.head + 1)) & (size - 1);
-}
-
-static inline int me4000_values_to_end(struct me4000_circ_buf buf, int size)
-{
- int end;
- int n;
- end = size - buf.tail;
- n = (buf.head + end) & (size - 1);
- return (n < end) ? n : end;
-}
-
-static inline int me4000_space_to_end(struct me4000_circ_buf buf, int size)
-{
- int end;
- int n;
-
- end = size - 1 - buf.head;
- n = (end + buf.tail) & (size - 1);
- return (n <= end) ? n : (end + 1);
-}
-
-static inline void me4000_outb(unsigned char value, unsigned long port)
-{
- PORT_PDEBUG("--> 0x%02X port 0x%04lX\n", value, port);
- outb(value, port);
-}
-
-static inline void me4000_outl(unsigned long value, unsigned long port)
-{
- PORT_PDEBUG("--> 0x%08lX port 0x%04lX\n", value, port);
- outl(value, port);
-}
-
-static inline unsigned long me4000_inl(unsigned long port)
-{
- unsigned long value;
- value = inl(port);
- PORT_PDEBUG("<-- 0x%08lX port 0x%04lX\n", value, port);
- return value;
-}
-
-static inline unsigned char me4000_inb(unsigned long port)
-{
- unsigned char value;
- value = inb(port);
- PORT_PDEBUG("<-- 0x%08X port 0x%04lX\n", value, port);
- return value;
-}
-
-static struct pci_driver me4000_driver = {
- .name = ME4000_NAME,
- .id_table = me4000_pci_table,
- .probe = me4000_probe
-};
-
-static const struct file_operations me4000_ao_fops_sing = {
- .owner = THIS_MODULE,
- .write = me4000_ao_write_sing,
- .ioctl = me4000_ao_ioctl_sing,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ao_fops_wrap = {
- .owner = THIS_MODULE,
- .write = me4000_ao_write_wrap,
- .ioctl = me4000_ao_ioctl_wrap,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ao_fops_cont = {
- .owner = THIS_MODULE,
- .write = me4000_ao_write_cont,
- .poll = me4000_ao_poll_cont,
- .ioctl = me4000_ao_ioctl_cont,
- .open = me4000_open,
- .release = me4000_release,
- .fsync = me4000_ao_fsync_cont,
-};
-
-static const struct file_operations me4000_ai_fops_sing = {
- .owner = THIS_MODULE,
- .ioctl = me4000_ai_ioctl_sing,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ai_fops_cont_sw = {
- .owner = THIS_MODULE,
- .read = me4000_ai_read,
- .poll = me4000_ai_poll,
- .ioctl = me4000_ai_ioctl_sw,
- .open = me4000_open,
- .release = me4000_release,
- .fasync = me4000_ai_fasync,
-};
-
-static const struct file_operations me4000_ai_fops_cont_et = {
- .owner = THIS_MODULE,
- .read = me4000_ai_read,
- .poll = me4000_ai_poll,
- .ioctl = me4000_ai_ioctl_ext,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ai_fops_cont_et_value = {
- .owner = THIS_MODULE,
- .read = me4000_ai_read,
- .poll = me4000_ai_poll,
- .ioctl = me4000_ai_ioctl_ext,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ai_fops_cont_et_chanlist = {
- .owner = THIS_MODULE,
- .read = me4000_ai_read,
- .poll = me4000_ai_poll,
- .ioctl = me4000_ai_ioctl_ext,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_dio_fops = {
- .owner = THIS_MODULE,
- .ioctl = me4000_dio_ioctl,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_cnt_fops = {
- .owner = THIS_MODULE,
- .ioctl = me4000_cnt_ioctl,
- .open = me4000_open,
- .release = me4000_release,
-};
-
-static const struct file_operations me4000_ext_int_fops = {
- .owner = THIS_MODULE,
- .ioctl = me4000_ext_int_ioctl,
- .open = me4000_open,
- .release = me4000_release,
- .fasync = me4000_ext_int_fasync,
-};
-
-static const struct file_operations *me4000_ao_fops_array[] = {
- /* single operations */
- &me4000_ao_fops_sing,
- /* wraparound operations */
- &me4000_ao_fops_wrap,
- /* continuous operations */
- &me4000_ao_fops_cont,
-};
-
-static const struct file_operations *me4000_ai_fops_array[] = {
- /* single operations */
- &me4000_ai_fops_sing,
- /* continuous operations with software start */
- &me4000_ai_fops_cont_sw,
- /* continuous operations with external trigger */
- &me4000_ai_fops_cont_et,
- /* sample values by external trigger */
- &me4000_ai_fops_cont_et_value,
- /* work through one channel list by external trigger */
- &me4000_ai_fops_cont_et_chanlist,
-};
-
-static int __init me4000_init_module(void)
-{
- int result;
-
- CALL_PDEBUG("init_module() is executed\n");
-
- /* Register driver capabilities */
- result = pci_register_driver(&me4000_driver);
- PDEBUG("init_module():%d devices detected\n", result);
- if (result < 0) {
- printk(KERN_ERR "ME4000:init_module():Can't register driver\n");
- goto INIT_ERROR_1;
- }
-
- /* Allocate major number for analog output */
- result =
- register_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME,
- &me4000_ao_fops_sing);
- if (result < 0) {
- printk(KERN_ERR "ME4000:init_module():Can't get AO major no\n");
- goto INIT_ERROR_2;
- } else {
- me4000_ao_major_driver_no = result;
- }
- PDEBUG("init_module():Major driver number for AO = %ld\n",
- me4000_ao_major_driver_no);
-
- /* Allocate major number for analog input */
- result =
- register_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME,
- &me4000_ai_fops_sing);
- if (result < 0) {
- printk(KERN_ERR "ME4000:init_module():Can't get AI major no\n");
- goto INIT_ERROR_3;
- } else {
- me4000_ai_major_driver_no = result;
- }
- PDEBUG("init_module():Major driver number for AI = %ld\n",
- me4000_ai_major_driver_no);
-
- /* Allocate major number for digital I/O */
- result =
- register_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME,
- &me4000_dio_fops);
- if (result < 0) {
- printk(KERN_ERR
- "ME4000:init_module():Can't get DIO major no\n");
- goto INIT_ERROR_4;
- } else {
- me4000_dio_major_driver_no = result;
- }
- PDEBUG("init_module():Major driver number for DIO = %ld\n",
- me4000_dio_major_driver_no);
-
- /* Allocate major number for counter */
- result =
- register_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME,
- &me4000_cnt_fops);
- if (result < 0) {
- printk(KERN_ERR
- "ME4000:init_module():Can't get CNT major no\n");
- goto INIT_ERROR_5;
- } else {
- me4000_cnt_major_driver_no = result;
- }
- PDEBUG("init_module():Major driver number for CNT = %ld\n",
- me4000_cnt_major_driver_no);
-
- /* Allocate major number for external interrupt */
- result =
- register_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME,
- &me4000_ext_int_fops);
- if (result < 0) {
- printk(KERN_ERR
- "ME4000:init_module():Can't get major no for external interrupt\n");
- goto INIT_ERROR_6;
- } else {
- me4000_ext_int_major_driver_no = result;
- }
- PDEBUG
- ("init_module():Major driver number for external interrupt = %ld\n",
- me4000_ext_int_major_driver_no);
-
- /* Create the /proc/me4000 entry */
- if (!create_proc_read_entry
- ("me4000", 0, NULL, me4000_read_procmem, NULL)) {
- result = -ENODEV;
- printk(KERN_ERR
- "ME4000:init_module():Can't create proc entry\n");
- goto INIT_ERROR_7;
- }
-
- return 0;
-
-INIT_ERROR_7:
- unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME);
-
-INIT_ERROR_6:
- unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME);
-
-INIT_ERROR_5:
- unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME);
-
-INIT_ERROR_4:
- unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME);
-
-INIT_ERROR_3:
- unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME);
-
-INIT_ERROR_2:
- pci_unregister_driver(&me4000_driver);
- clear_board_info_list();
-
-INIT_ERROR_1:
- return result;
-}
-
-module_init(me4000_init_module);
-
-static void clear_board_info_list(void)
-{
- struct me4000_info *board_info, *board_info_safe;
- struct me4000_ao_context *ao_context, *ao_context_safe;
-
- /* Clear context lists */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- /* Clear analog output context list */
- list_for_each_entry_safe(ao_context, ao_context_safe,
- &board_info->ao_context_list, list) {
- me4000_ao_reset(ao_context);
- free_irq(ao_context->irq, ao_context);
- kfree(ao_context->circ_buf.buf);
- list_del(&ao_context->list);
- kfree(ao_context);
- }
-
- /* Clear analog input context */
- kfree(board_info->ai_context->circ_buf.buf);
- kfree(board_info->ai_context);
-
- /* Clear digital I/O context */
- kfree(board_info->dio_context);
-
- /* Clear counter context */
- kfree(board_info->cnt_context);
-
- /* Clear external interrupt context */
- kfree(board_info->ext_int_context);
- }
-
- /* Clear the board info list */
- list_for_each_entry_safe(board_info, board_info_safe,
- &me4000_board_info_list, list) {
- pci_release_regions(board_info->pci_dev_p);
- list_del(&board_info->list);
- kfree(board_info);
- }
-}
-
-static int get_registers(struct pci_dev *dev, struct me4000_info *board_info)
-{
-
- /*--------------------------- plx regbase ---------------------------------*/
-
- board_info->plx_regbase = pci_resource_start(dev, 1);
- if (board_info->plx_regbase == 0) {
- printk(KERN_ERR
- "ME4000:get_registers():PCI base address 1 is not available\n");
- return -ENODEV;
- }
- board_info->plx_regbase_size = pci_resource_len(dev, 1);
-
- PDEBUG
- ("get_registers():PLX configuration registers at address 0x%4lX [0x%4lX]\n",
- board_info->plx_regbase, board_info->plx_regbase_size);
-
- /*--------------------------- me4000 regbase ------------------------------*/
-
- board_info->me4000_regbase = pci_resource_start(dev, 2);
- if (board_info->me4000_regbase == 0) {
- printk(KERN_ERR
- "ME4000:get_registers():PCI base address 2 is not available\n");
- return -ENODEV;
- }
- board_info->me4000_regbase_size = pci_resource_len(dev, 2);
-
- PDEBUG("get_registers():ME4000 registers at address 0x%4lX [0x%4lX]\n",
- board_info->me4000_regbase, board_info->me4000_regbase_size);
-
- /*--------------------------- timer regbase ------------------------------*/
-
- board_info->timer_regbase = pci_resource_start(dev, 3);
- if (board_info->timer_regbase == 0) {
- printk(KERN_ERR
- "ME4000:get_registers():PCI base address 3 is not available\n");
- return -ENODEV;
- }
- board_info->timer_regbase_size = pci_resource_len(dev, 3);
-
- PDEBUG("get_registers():Timer registers at address 0x%4lX [0x%4lX]\n",
- board_info->timer_regbase, board_info->timer_regbase_size);
-
- /*--------------------------- program regbase ------------------------------*/
-
- board_info->program_regbase = pci_resource_start(dev, 5);
- if (board_info->program_regbase == 0) {
- printk(KERN_ERR
- "get_registers():ME4000:PCI base address 5 is not available\n");
- return -ENODEV;
- }
- board_info->program_regbase_size = pci_resource_len(dev, 5);
-
- PDEBUG("get_registers():Program registers at address 0x%4lX [0x%4lX]\n",
- board_info->program_regbase, board_info->program_regbase_size);
-
- return 0;
-}
-
-static int init_board_info(struct pci_dev *pci_dev_p,
- struct me4000_info *board_info)
-{
- int i;
- int result;
- struct list_head *board_p;
- board_info->pci_dev_p = pci_dev_p;
-
- for (i = 0; i < ARRAY_SIZE(me4000_boards); i++) {
- if (me4000_boards[i].device_id == pci_dev_p->device) {
- board_info->board_p = &me4000_boards[i];
- break;
- }
- }
- if (i == ARRAY_SIZE(me4000_boards)) {
- printk(KERN_ERR
- "ME4000:init_board_info():Device ID not valid\n");
- return -ENODEV;
- }
-
- /* Get the index of the board in the global list */
- i = 0;
- list_for_each(board_p, &me4000_board_info_list) {
- if (board_p == &board_info->list) {
- board_info->board_count = i;
- break;
- }
- i++;
- }
- if (board_p == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:init_board_info():Cannot get index of board\n");
- return -ENODEV;
- }
-
- /* Init list head for analog output contexts */
- INIT_LIST_HEAD(&board_info->ao_context_list);
-
- /* Init spin locks */
- spin_lock_init(&board_info->preload_lock);
- spin_lock_init(&board_info->ai_ctrl_lock);
-
- /* Get the serial number */
- result = pci_read_config_dword(pci_dev_p, 0x2C, &board_info->serial_no);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_WARNING
- "ME4000:init_board_info: Can't get serial_no\n");
- return result;
- }
- PDEBUG("init_board_info():serial_no = 0x%x\n", board_info->serial_no);
-
- /* Get the hardware revision */
- result =
- pci_read_config_byte(pci_dev_p, 0x08, &board_info->hw_revision);
- if (result != PCIBIOS_SUCCESSFUL) {
- printk(KERN_WARNING
- "ME4000:init_board_info():Can't get hw_revision\n");
- return result;
- }
- PDEBUG("init_board_info():hw_revision = 0x%x\n",
- board_info->hw_revision);
-
- /* Get the vendor id */
- board_info->vendor_id = pci_dev_p->vendor;
- PDEBUG("init_board_info():vendor_id = 0x%x\n", board_info->vendor_id);
-
- /* Get the device id */
- board_info->device_id = pci_dev_p->device;
- PDEBUG("init_board_info():device_id = 0x%x\n", board_info->device_id);
-
- /* Get the pci device number */
- board_info->pci_dev_no = PCI_FUNC(pci_dev_p->devfn);
- PDEBUG("init_board_info():pci_func_no = 0x%x\n",
- board_info->pci_func_no);
-
- /* Get the pci slot number */
- board_info->pci_dev_no = PCI_SLOT(pci_dev_p->devfn);
- PDEBUG("init_board_info():pci_dev_no = 0x%x\n", board_info->pci_dev_no);
-
- /* Get the pci bus number */
- board_info->pci_bus_no = pci_dev_p->bus->number;
- PDEBUG("init_board_info():pci_bus_no = 0x%x\n", board_info->pci_bus_no);
-
- /* Get the irq assigned to the board */
- board_info->irq = pci_dev_p->irq;
- PDEBUG("init_board_info():irq = %d\n", board_info->irq);
-
- return 0;
-}
-
-static int alloc_ao_contexts(struct me4000_info *info)
-{
- int i;
- int err;
- struct me4000_ao_context *ao_context;
-
- for (i = 0; i < info->board_p->ao.count; i++) {
- ao_context = kzalloc(sizeof(struct me4000_ao_context),
- GFP_KERNEL);
- if (!ao_context) {
- printk(KERN_ERR
- "alloc_ao_contexts():Can't get memory for ao context\n");
- release_ao_contexts(info);
- return -ENOMEM;
- }
-
- spin_lock_init(&ao_context->use_lock);
- spin_lock_init(&ao_context->int_lock);
- ao_context->irq = info->irq;
- init_waitqueue_head(&ao_context->wait_queue);
- ao_context->board_info = info;
-
- if (info->board_p->ao.fifo_count) {
- /* Allocate circular buffer */
- ao_context->circ_buf.buf =
- kzalloc(ME4000_AO_BUFFER_SIZE, GFP_KERNEL);
- if (!ao_context->circ_buf.buf) {
- printk(KERN_ERR
- "alloc_ao_contexts():Can't get circular buffer\n");
- release_ao_contexts(info);
- return -ENOMEM;
- }
-
- /* Clear the circular buffer */
- ao_context->circ_buf.head = 0;
- ao_context->circ_buf.tail = 0;
- }
-
- switch (i) {
- case 0:
- ao_context->ctrl_reg =
- info->me4000_regbase + ME4000_AO_00_CTRL_REG;
- ao_context->status_reg =
- info->me4000_regbase + ME4000_AO_00_STATUS_REG;
- ao_context->fifo_reg =
- info->me4000_regbase + ME4000_AO_00_FIFO_REG;
- ao_context->single_reg =
- info->me4000_regbase + ME4000_AO_00_SINGLE_REG;
- ao_context->timer_reg =
- info->me4000_regbase + ME4000_AO_00_TIMER_REG;
- ao_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- ao_context->preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 1:
- ao_context->ctrl_reg =
- info->me4000_regbase + ME4000_AO_01_CTRL_REG;
- ao_context->status_reg =
- info->me4000_regbase + ME4000_AO_01_STATUS_REG;
- ao_context->fifo_reg =
- info->me4000_regbase + ME4000_AO_01_FIFO_REG;
- ao_context->single_reg =
- info->me4000_regbase + ME4000_AO_01_SINGLE_REG;
- ao_context->timer_reg =
- info->me4000_regbase + ME4000_AO_01_TIMER_REG;
- ao_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- ao_context->preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 2:
- ao_context->ctrl_reg =
- info->me4000_regbase + ME4000_AO_02_CTRL_REG;
- ao_context->status_reg =
- info->me4000_regbase + ME4000_AO_02_STATUS_REG;
- ao_context->fifo_reg =
- info->me4000_regbase + ME4000_AO_02_FIFO_REG;
- ao_context->single_reg =
- info->me4000_regbase + ME4000_AO_02_SINGLE_REG;
- ao_context->timer_reg =
- info->me4000_regbase + ME4000_AO_02_TIMER_REG;
- ao_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- ao_context->preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- case 3:
- ao_context->ctrl_reg =
- info->me4000_regbase + ME4000_AO_03_CTRL_REG;
- ao_context->status_reg =
- info->me4000_regbase + ME4000_AO_03_STATUS_REG;
- ao_context->fifo_reg =
- info->me4000_regbase + ME4000_AO_03_FIFO_REG;
- ao_context->single_reg =
- info->me4000_regbase + ME4000_AO_03_SINGLE_REG;
- ao_context->timer_reg =
- info->me4000_regbase + ME4000_AO_03_TIMER_REG;
- ao_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- ao_context->preload_reg =
- info->me4000_regbase + ME4000_AO_LOADSETREG_XX;
- break;
- default:
- break;
- }
-
- if (info->board_p->ao.fifo_count) {
- /* Request the interrupt line */
- err =
- request_irq(ao_context->irq, me4000_ao_isr,
- IRQF_DISABLED | IRQF_SHARED,
- ME4000_NAME, ao_context);
- if (err) {
- printk(KERN_ERR
- "%s:Can't get interrupt line", __func__);
- kfree(ao_context->circ_buf.buf);
- kfree(ao_context);
- release_ao_contexts(info);
- return -ENODEV;
- }
- }
-
- list_add_tail(&ao_context->list, &info->ao_context_list);
- ao_context->index = i;
- }
-
- return 0;
-}
-
-static void release_ao_contexts(struct me4000_info *board_info)
-{
- struct me4000_ao_context *ao_context, *ao_context_safe;
-
- /* Clear analog output context list */
- list_for_each_entry_safe(ao_context, ao_context_safe,
- &board_info->ao_context_list, list) {
- free_irq(ao_context->irq, ao_context);
- kfree(ao_context->circ_buf.buf);
- list_del(&ao_context->list);
- kfree(ao_context);
- }
-}
-
-static int alloc_ai_context(struct me4000_info *info)
-{
- struct me4000_ai_context *ai_context;
-
- if (info->board_p->ai.count) {
- ai_context = kzalloc(sizeof(struct me4000_ai_context),
- GFP_KERNEL);
- if (!ai_context) {
- printk(KERN_ERR
- "ME4000:alloc_ai_context():Can't get memory for ai context\n");
- return -ENOMEM;
- }
-
- info->ai_context = ai_context;
-
- spin_lock_init(&ai_context->use_lock);
- spin_lock_init(&ai_context->int_lock);
- ai_context->number = 0;
- ai_context->irq = info->irq;
- init_waitqueue_head(&ai_context->wait_queue);
- ai_context->board_info = info;
-
- ai_context->ctrl_reg =
- info->me4000_regbase + ME4000_AI_CTRL_REG;
- ai_context->status_reg =
- info->me4000_regbase + ME4000_AI_STATUS_REG;
- ai_context->channel_list_reg =
- info->me4000_regbase + ME4000_AI_CHANNEL_LIST_REG;
- ai_context->data_reg =
- info->me4000_regbase + ME4000_AI_DATA_REG;
- ai_context->chan_timer_reg =
- info->me4000_regbase + ME4000_AI_CHAN_TIMER_REG;
- ai_context->chan_pre_timer_reg =
- info->me4000_regbase + ME4000_AI_CHAN_PRE_TIMER_REG;
- ai_context->scan_timer_low_reg =
- info->me4000_regbase + ME4000_AI_SCAN_TIMER_LOW_REG;
- ai_context->scan_timer_high_reg =
- info->me4000_regbase + ME4000_AI_SCAN_TIMER_HIGH_REG;
- ai_context->scan_pre_timer_low_reg =
- info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG;
- ai_context->scan_pre_timer_high_reg =
- info->me4000_regbase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG;
- ai_context->start_reg =
- info->me4000_regbase + ME4000_AI_START_REG;
- ai_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- ai_context->sample_counter_reg =
- info->me4000_regbase + ME4000_AI_SAMPLE_COUNTER_REG;
- }
-
- return 0;
-}
-
-static int alloc_dio_context(struct me4000_info *info)
-{
- struct me4000_dio_context *dio_context;
-
- if (info->board_p->dio.count) {
- dio_context = kzalloc(sizeof(struct me4000_dio_context),
- GFP_KERNEL);
- if (!dio_context) {
- printk(KERN_ERR
- "ME4000:alloc_dio_context():Can't get memory for dio context\n");
- return -ENOMEM;
- }
-
- info->dio_context = dio_context;
-
- spin_lock_init(&dio_context->use_lock);
- dio_context->board_info = info;
-
- dio_context->dio_count = info->board_p->dio.count;
-
- dio_context->dir_reg =
- info->me4000_regbase + ME4000_DIO_DIR_REG;
- dio_context->ctrl_reg =
- info->me4000_regbase + ME4000_DIO_CTRL_REG;
- dio_context->port_0_reg =
- info->me4000_regbase + ME4000_DIO_PORT_0_REG;
- dio_context->port_1_reg =
- info->me4000_regbase + ME4000_DIO_PORT_1_REG;
- dio_context->port_2_reg =
- info->me4000_regbase + ME4000_DIO_PORT_2_REG;
- dio_context->port_3_reg =
- info->me4000_regbase + ME4000_DIO_PORT_3_REG;
- }
-
- return 0;
-}
-
-static int alloc_cnt_context(struct me4000_info *info)
-{
- struct me4000_cnt_context *cnt_context;
-
- if (info->board_p->cnt.count) {
- cnt_context = kzalloc(sizeof(struct me4000_cnt_context),
- GFP_KERNEL);
- if (!cnt_context) {
- printk(KERN_ERR
- "ME4000:alloc_cnt_context():Can't get memory for cnt context\n");
- return -ENOMEM;
- }
-
- info->cnt_context = cnt_context;
-
- spin_lock_init(&cnt_context->use_lock);
- cnt_context->board_info = info;
-
- cnt_context->ctrl_reg =
- info->timer_regbase + ME4000_CNT_CTRL_REG;
- cnt_context->counter_0_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_0_REG;
- cnt_context->counter_1_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_1_REG;
- cnt_context->counter_2_reg =
- info->timer_regbase + ME4000_CNT_COUNTER_2_REG;
- }
-
- return 0;
-}
-
-static int alloc_ext_int_context(struct me4000_info *info)
-{
- struct me4000_ext_int_context *ext_int_context;
-
- if (info->board_p->cnt.count) {
- ext_int_context =
- kzalloc(sizeof(struct me4000_ext_int_context), GFP_KERNEL);
- if (!ext_int_context) {
- printk(KERN_ERR
- "ME4000:alloc_ext_int_context():Can't get memory for cnt context\n");
- return -ENOMEM;
- }
-
- info->ext_int_context = ext_int_context;
-
- spin_lock_init(&ext_int_context->use_lock);
- ext_int_context->board_info = info;
-
- ext_int_context->fasync_ptr = NULL;
- ext_int_context->irq = info->irq;
-
- ext_int_context->ctrl_reg =
- info->me4000_regbase + ME4000_AI_CTRL_REG;
- ext_int_context->irq_status_reg =
- info->me4000_regbase + ME4000_IRQ_STATUS_REG;
- }
-
- return 0;
-}
-
-static int me4000_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
- int result = 0;
- struct me4000_info *board_info;
-
- CALL_PDEBUG("me4000_probe() is executed\n");
-
- /* Allocate structure for board context */
- board_info = kzalloc(sizeof(struct me4000_info), GFP_KERNEL);
- if (!board_info) {
- printk(KERN_ERR
- "ME4000:Can't get memory for board info structure\n");
- result = -ENOMEM;
- goto PROBE_ERROR_1;
- }
-
- /* Add to global linked list */
- list_add_tail(&board_info->list, &me4000_board_info_list);
-
- /* Get the PCI base registers */
- result = get_registers(dev, board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot get registers\n", __func__);
- goto PROBE_ERROR_2;
- }
-
- /* Enable the device */
- result = pci_enable_device(dev);
- if (result < 0) {
- printk(KERN_ERR "%s:Cannot enable PCI device\n", __func__);
- goto PROBE_ERROR_2;
- }
-
- /* Request the PCI register regions */
- result = pci_request_regions(dev, ME4000_NAME);
- if (result < 0) {
- printk(KERN_ERR "%s:Cannot request I/O regions\n", __func__);
- goto PROBE_ERROR_2;
- }
-
- /* Initialize board info */
- result = init_board_info(dev, board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot init baord info\n", __func__);
- goto PROBE_ERROR_3;
- }
-
- /* Download the xilinx firmware */
- result = me4000_xilinx_download(board_info);
- if (result) {
- printk(KERN_ERR "%s:Can't download firmware\n", __func__);
- goto PROBE_ERROR_3;
- }
-
- /* Make a hardware reset */
- result = me4000_reset_board(board_info);
- if (result) {
- printk(KERN_ERR "%s :Can't reset board\n", __func__);
- goto PROBE_ERROR_3;
- }
-
- /* Allocate analog output context structures */
- result = alloc_ao_contexts(board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot allocate ao contexts\n", __func__);
- goto PROBE_ERROR_3;
- }
-
- /* Allocate analog input context */
- result = alloc_ai_context(board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot allocate ai context\n", __func__);
- goto PROBE_ERROR_4;
- }
-
- /* Allocate digital I/O context */
- result = alloc_dio_context(board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot allocate dio context\n", __func__);
- goto PROBE_ERROR_5;
- }
-
- /* Allocate counter context */
- result = alloc_cnt_context(board_info);
- if (result) {
- printk(KERN_ERR "%s:Cannot allocate cnt context\n", __func__);
- goto PROBE_ERROR_6;
- }
-
- /* Allocate external interrupt context */
- result = alloc_ext_int_context(board_info);
- if (result) {
- printk(KERN_ERR
- "%s:Cannot allocate ext_int context\n", __func__);
- goto PROBE_ERROR_7;
- }
-
- return 0;
-
-PROBE_ERROR_7:
- kfree(board_info->cnt_context);
-
-PROBE_ERROR_6:
- kfree(board_info->dio_context);
-
-PROBE_ERROR_5:
- kfree(board_info->ai_context);
-
-PROBE_ERROR_4:
- release_ao_contexts(board_info);
-
-PROBE_ERROR_3:
- pci_release_regions(dev);
-
-PROBE_ERROR_2:
- list_del(&board_info->list);
- kfree(board_info);
-
-PROBE_ERROR_1:
- return result;
-}
-
-static int me4000_xilinx_download(struct me4000_info *info)
-{
- int size = 0;
- u32 value = 0;
- int idx = 0;
- unsigned char *firm;
- wait_queue_head_t queue;
-
- CALL_PDEBUG("me4000_xilinx_download() is executed\n");
-
- init_waitqueue_head(&queue);
-
- firm = (info->device_id == 0x4610) ? xilinx_firm_4610 : xilinx_firm;
-
- /*
- * Set PLX local interrupt 2 polarity to high.
- * Interrupt is thrown by init pin of xilinx.
- */
- outl(0x10, info->plx_regbase + PLX_INTCSR);
-
- /* Set /CS and /WRITE of the Xilinx */
- value = inl(info->plx_regbase + PLX_ICR);
- value |= 0x100;
- outl(value, info->plx_regbase + PLX_ICR);
-
- /* Init Xilinx with CS1 */
- inb(info->program_regbase + 0xC8);
-
- /* Wait until /INIT pin is set */
- udelay(20);
- if (!(inl(info->plx_regbase + PLX_INTCSR) & 0x20)) {
- printk(KERN_ERR "%s:Can't init Xilinx\n", __func__);
- return -EIO;
- }
-
- /* Reset /CS and /WRITE of the Xilinx */
- value = inl(info->plx_regbase + PLX_ICR);
- value &= ~0x100;
- outl(value, info->plx_regbase + PLX_ICR);
-
- /* Download Xilinx firmware */
- size = (firm[0] << 24) + (firm[1] << 16) + (firm[2] << 8) + firm[3];
- udelay(10);
-
- for (idx = 0; idx < size; idx++) {
- outb(firm[16 + idx], info->program_regbase);
-
- udelay(10);
-
- /* Check if BUSY flag is low */
- if (inl(info->plx_regbase + PLX_ICR) & 0x20) {
- printk(KERN_ERR
- "%s:Xilinx is still busy (idx = %d)\n", __func__,
- idx);
- return -EIO;
- }
- }
-
- PDEBUG("me4000_xilinx_download():%d bytes written\n", idx);
-
- /* If done flag is high download was successful */
- if (inl(info->plx_regbase + PLX_ICR) & 0x4) {
- PDEBUG("me4000_xilinx_download():Done flag is set\n");
- PDEBUG("me4000_xilinx_download():Download was successful\n");
- } else {
- printk(KERN_ERR
- "ME4000:%s:DONE flag is not set\n", __func__);
- printk(KERN_ERR
- "ME4000:%s:Download not succesful\n", __func__);
- return -EIO;
- }
-
- /* Set /CS and /WRITE */
- value = inl(info->plx_regbase + PLX_ICR);
- value |= 0x100;
- outl(value, info->plx_regbase + PLX_ICR);
-
- return 0;
-}
-
-static int me4000_reset_board(struct me4000_info *info)
-{
- unsigned long icr;
-
- CALL_PDEBUG("me4000_reset_board() is executed\n");
-
- /* Make a hardware reset */
- icr = me4000_inl(info->plx_regbase + PLX_ICR);
- icr |= 0x40000000;
- me4000_outl(icr, info->plx_regbase + PLX_ICR);
- icr &= ~0x40000000;
- me4000_outl(icr, info->plx_regbase + PLX_ICR);
-
- /* Set both stop bits in the analog input control register */
- me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AI_CTRL_REG);
-
- /* Set both stop bits in the analog output control register */
- me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_00_CTRL_REG);
- me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_01_CTRL_REG);
- me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_02_CTRL_REG);
- me4000_outl(ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP,
- info->me4000_regbase + ME4000_AO_03_CTRL_REG);
-
- /* 0x8000 to the DACs means an output voltage of 0V */
- me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_00_SINGLE_REG);
- me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_01_SINGLE_REG);
- me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_02_SINGLE_REG);
- me4000_outl(0x8000, info->me4000_regbase + ME4000_AO_03_SINGLE_REG);
-
- /* Enable interrupts on the PLX */
- me4000_outl(0x43, info->plx_regbase + PLX_INTCSR);
-
- /* Set the adustment register for AO demux */
- me4000_outl(ME4000_AO_DEMUX_ADJUST_VALUE,
- info->me4000_regbase + ME4000_AO_DEMUX_ADJUST_REG);
-
- /* Set digital I/O direction for port 0 to output on isolated versions */
- if (!(me4000_inl(info->me4000_regbase + ME4000_DIO_DIR_REG) & 0x1))
- me4000_outl(0x1, info->me4000_regbase + ME4000_DIO_CTRL_REG);
-
- return 0;
-}
-
-static int me4000_open(struct inode *inode_p, struct file *file_p)
-{
- int board, dev, mode;
- int err = 0;
- int i;
- struct list_head *ptr;
- struct me4000_info *board_info = NULL;
- struct me4000_ao_context *ao_context = NULL;
- struct me4000_ai_context *ai_context = NULL;
- struct me4000_dio_context *dio_context = NULL;
- struct me4000_cnt_context *cnt_context = NULL;
- struct me4000_ext_int_context *ext_int_context = NULL;
-
- CALL_PDEBUG("me4000_open() is executed\n");
-
- /* Analog output */
- if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) {
- board = AO_BOARD(inode_p->i_rdev);
- dev = AO_PORT(inode_p->i_rdev);
- mode = AO_MODE(inode_p->i_rdev);
-
- PDEBUG("me4000_open():board = %d ao = %d mode = %d\n", board,
- dev, mode);
-
- /* Search for the board context */
- i = 0;
- list_for_each(ptr, &me4000_board_info_list) {
- if (i == board)
- break;
- i++;
- }
- board_info = list_entry(ptr, struct me4000_info, list);
-
- if (ptr == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Board %d not in device list\n",
- board);
- return -ENODEV;
- }
-
- /* Search for the dac context */
- i = 0;
- list_for_each(ptr, &board_info->ao_context_list) {
- if (i == dev)
- break;
- i++;
- }
- ao_context = list_entry(ptr, struct me4000_ao_context, list);
-
- if (ptr == &board_info->ao_context_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Device %d not in device list\n",
- dev);
- return -ENODEV;
- }
-
- /* Check if mode is valid */
- if (mode > 2) {
- printk(KERN_ERR
- "ME4000:me4000_open():Mode is not valid\n");
- return -ENODEV;
- }
-
- /* Check if mode is valid for this AO */
- if ((mode != ME4000_AO_CONV_MODE_SINGLE)
- && (dev >= board_info->board_p->ao.fifo_count)) {
- printk(KERN_ERR
- "ME4000:me4000_open():AO %d only in single mode available\n",
- dev);
- return -ENODEV;
- }
-
- /* Check if already opened */
- spin_lock(&ao_context->use_lock);
- if (ao_context->dac_in_use) {
- printk(KERN_ERR
- "ME4000:me4000_open():AO %d already in use\n",
- dev);
- spin_unlock(&ao_context->use_lock);
- return -EBUSY;
- }
- ao_context->dac_in_use = 1;
- spin_unlock(&ao_context->use_lock);
-
- ao_context->mode = mode;
-
- /* Hold the context in private data */
- file_p->private_data = ao_context;
-
- /* Set file operations pointer */
- file_p->f_op = me4000_ao_fops_array[mode];
-
- err = me4000_ao_prepare(ao_context);
- if (err) {
- ao_context->dac_in_use = 0;
- return 1;
- }
- }
- /* Analog input */
- else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) {
- board = AI_BOARD(inode_p->i_rdev);
- mode = AI_MODE(inode_p->i_rdev);
-
- PDEBUG("me4000_open():ai board = %d mode = %d\n", board, mode);
-
- /* Search for the board context */
- i = 0;
- list_for_each(ptr, &me4000_board_info_list) {
- if (i == board)
- break;
- i++;
- }
- board_info = list_entry(ptr, struct me4000_info, list);
-
- if (ptr == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Board %d not in device list\n",
- board);
- return -ENODEV;
- }
-
- ai_context = board_info->ai_context;
-
- /* Check if mode is valid */
- if (mode > 5) {
- printk(KERN_ERR
- "ME4000:me4000_open():Mode is not valid\n");
- return -EINVAL;
- }
-
- /* Check if already opened */
- spin_lock(&ai_context->use_lock);
- if (ai_context->in_use) {
- printk(KERN_ERR
- "ME4000:me4000_open():AI already in use\n");
- spin_unlock(&ai_context->use_lock);
- return -EBUSY;
- }
- ai_context->in_use = 1;
- spin_unlock(&ai_context->use_lock);
-
- ai_context->mode = mode;
-
- /* Hold the context in private data */
- file_p->private_data = ai_context;
-
- /* Set file operations pointer */
- file_p->f_op = me4000_ai_fops_array[mode];
-
- /* Prepare analog input */
- me4000_ai_prepare(ai_context);
- }
- /* Digital I/O */
- else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) {
- board = DIO_BOARD(inode_p->i_rdev);
- dev = 0;
- mode = 0;
-
- PDEBUG("me4000_open():board = %d\n", board);
-
- /* Search for the board context */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- if (board_info->board_count == board)
- break;
- }
-
- if (&board_info->list == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Board %d not in device list\n",
- board);
- return -ENODEV;
- }
-
- /* Search for the dio context */
- dio_context = board_info->dio_context;
-
- /* Check if already opened */
- spin_lock(&dio_context->use_lock);
- if (dio_context->in_use) {
- printk(KERN_ERR
- "ME4000:me4000_open():DIO already in use\n");
- spin_unlock(&dio_context->use_lock);
- return -EBUSY;
- }
- dio_context->in_use = 1;
- spin_unlock(&dio_context->use_lock);
-
- /* Hold the context in private data */
- file_p->private_data = dio_context;
-
- /* Set file operations pointer to single functions */
- file_p->f_op = &me4000_dio_fops;
-
- /* me4000_dio_reset(dio_context); */
- }
- /* Counters */
- else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) {
- board = CNT_BOARD(inode_p->i_rdev);
- dev = 0;
- mode = 0;
-
- PDEBUG("me4000_open():board = %d\n", board);
-
- /* Search for the board context */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- if (board_info->board_count == board)
- break;
- }
-
- if (&board_info->list == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Board %d not in device list\n",
- board);
- return -ENODEV;
- }
-
- /* Get the cnt context */
- cnt_context = board_info->cnt_context;
-
- /* Check if already opened */
- spin_lock(&cnt_context->use_lock);
- if (cnt_context->in_use) {
- printk(KERN_ERR
- "ME4000:me4000_open():CNT already in use\n");
- spin_unlock(&cnt_context->use_lock);
- return -EBUSY;
- }
- cnt_context->in_use = 1;
- spin_unlock(&cnt_context->use_lock);
-
- /* Hold the context in private data */
- file_p->private_data = cnt_context;
-
- /* Set file operations pointer to single functions */
- file_p->f_op = &me4000_cnt_fops;
- }
- /* External Interrupt */
- else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) {
- board = EXT_INT_BOARD(inode_p->i_rdev);
- dev = 0;
- mode = 0;
-
- PDEBUG("me4000_open():board = %d\n", board);
-
- /* Search for the board context */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- if (board_info->board_count == board)
- break;
- }
-
- if (&board_info->list == &me4000_board_info_list) {
- printk(KERN_ERR
- "ME4000:me4000_open():Board %d not in device list\n",
- board);
- return -ENODEV;
- }
-
- /* Get the external interrupt context */
- ext_int_context = board_info->ext_int_context;
-
- /* Check if already opened */
- spin_lock(&cnt_context->use_lock);
- if (ext_int_context->in_use) {
- printk(KERN_ERR
- "ME4000:me4000_open():External interrupt already in use\n");
- spin_unlock(&ext_int_context->use_lock);
- return -EBUSY;
- }
- ext_int_context->in_use = 1;
- spin_unlock(&ext_int_context->use_lock);
-
- /* Hold the context in private data */
- file_p->private_data = ext_int_context;
-
- /* Set file operations pointer to single functions */
- file_p->f_op = &me4000_ext_int_fops;
-
- /* Request the interrupt line */
- err =
- request_irq(ext_int_context->irq, me4000_ext_int_isr,
- IRQF_DISABLED | IRQF_SHARED, ME4000_NAME,
- ext_int_context);
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_open():Can't get interrupt line");
- ext_int_context->in_use = 0;
- return -ENODEV;
- }
-
- /* Reset the counter */
- me4000_ext_int_disable(ext_int_context);
- } else {
- printk(KERN_ERR "ME4000:me4000_open():Major number unknown\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_release(struct inode *inode_p, struct file *file_p)
-{
- struct me4000_ao_context *ao_context;
- struct me4000_ai_context *ai_context;
- struct me4000_dio_context *dio_context;
- struct me4000_cnt_context *cnt_context;
- struct me4000_ext_int_context *ext_int_context;
-
- CALL_PDEBUG("me4000_release() is executed\n");
-
- if (MAJOR(inode_p->i_rdev) == me4000_ao_major_driver_no) {
- ao_context = file_p->private_data;
-
- /* Mark DAC as unused */
- ao_context->dac_in_use = 0;
- } else if (MAJOR(inode_p->i_rdev) == me4000_ai_major_driver_no) {
- ai_context = file_p->private_data;
-
- /* Reset the analog input */
- me4000_ai_reset(ai_context);
-
- /* Free the interrupt and the circular buffer */
- if (ai_context->mode) {
- free_irq(ai_context->irq, ai_context);
- kfree(ai_context->circ_buf.buf);
- ai_context->circ_buf.buf = NULL;
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
- }
-
- /* Mark AI as unused */
- ai_context->in_use = 0;
- } else if (MAJOR(inode_p->i_rdev) == me4000_dio_major_driver_no) {
- dio_context = file_p->private_data;
-
- /* Mark digital I/O as unused */
- dio_context->in_use = 0;
- } else if (MAJOR(inode_p->i_rdev) == me4000_cnt_major_driver_no) {
- cnt_context = file_p->private_data;
-
- /* Mark counters as unused */
- cnt_context->in_use = 0;
- } else if (MAJOR(inode_p->i_rdev) == me4000_ext_int_major_driver_no) {
- ext_int_context = file_p->private_data;
-
- /* Disable the externel interrupt */
- me4000_ext_int_disable(ext_int_context);
-
- free_irq(ext_int_context->irq, ext_int_context);
-
- /* Mark as unused */
- ext_int_context->in_use = 0;
- } else {
- printk(KERN_ERR
- "ME4000:me4000_release():Major number unknown\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*------------------------------- Analog output stuff --------------------------------------*/
-
-static int me4000_ao_prepare(struct me4000_ao_context *ao_context)
-{
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_prepare() is executed\n");
-
- if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) {
- /* Only do anything if not already in the correct mode */
- unsigned long mode = me4000_inl(ao_context->ctrl_reg);
- if ((mode & ME4000_AO_CONV_MODE_CONTINUOUS)
- && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) {
- return 0;
- }
-
- /* Stop any conversion */
- me4000_ao_immediate_stop(ao_context);
-
- /* Set the control register to default state */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS |
- ME4000_AO_CTRL_BIT_ENABLE_FIFO |
- ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
- ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- /* Set to fastest sample rate */
- me4000_outl(65, ao_context->timer_reg);
- } else if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) {
- /* Only do anything if not already in the correct mode */
- unsigned long mode = me4000_inl(ao_context->ctrl_reg);
- if ((mode & ME4000_AO_CONV_MODE_WRAPAROUND)
- && (mode & ME4000_AO_CTRL_BIT_ENABLE_FIFO)) {
- return 0;
- }
-
- /* Stop any conversion */
- me4000_ao_immediate_stop(ao_context);
-
- /* Set the control register to default state */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND |
- ME4000_AO_CTRL_BIT_ENABLE_FIFO |
- ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
- ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- /* Set to fastest sample rate */
- me4000_outl(65, ao_context->timer_reg);
- } else if (ao_context->mode == ME4000_AO_CONV_MODE_SINGLE) {
- /* Only do anything if not already in the correct mode */
- unsigned long mode = me4000_inl(ao_context->ctrl_reg);
- if (!
- (mode &
- (ME4000_AO_CONV_MODE_WRAPAROUND |
- ME4000_AO_CONV_MODE_CONTINUOUS))) {
- return 0;
- }
-
- /* Stop any conversion */
- me4000_ao_immediate_stop(ao_context);
-
- /* Clear the control register */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- me4000_outl(0x0, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- /* Set voltage to 0V */
- me4000_outl(0x8000, ao_context->single_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_ao_prepare():Invalid mode specified\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_ao_reset(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_reset() is executed\n");
-
- init_waitqueue_head(&queue);
-
- if (ao_context->mode == ME4000_AO_CONV_MODE_WRAPAROUND) {
- /*
- * First stop conversion of the DAC before reconfigure.
- * This is essantial, cause of the state machine.
- * If not stopped before configuring mode, it could
- * walk in a undefined state.
- */
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
- me4000_outl(tmp, ao_context->ctrl_reg);
-
- wait_event_timeout(queue,
- (inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM) == 0,
- 1);
-
- /* Set to transparent mode */
- me4000_ao_simultaneous_disable(ao_context);
-
- /* Set to single mode in order to set default voltage */
- me4000_outl(0x0, ao_context->ctrl_reg);
-
- /* Set voltage to 0V */
- me4000_outl(0x8000, ao_context->single_reg);
-
- /* Set to fastest sample rate */
- me4000_outl(65, ao_context->timer_reg);
-
- /* Set the original mode and enable FIFO */
- me4000_outl(ME4000_AO_CONV_MODE_WRAPAROUND |
- ME4000_AO_CTRL_BIT_ENABLE_FIFO |
- ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
- ao_context->ctrl_reg);
- } else if (ao_context->mode == ME4000_AO_CONV_MODE_CONTINUOUS) {
- /*
- * First stop conversion of the DAC before reconfigure.
- * This is essantial, cause of the state machine.
- * If not stopped before configuring mode, it could
- * walk in a undefined state.
- */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_STOP;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- wait_event_timeout(queue,
- (inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM) == 0,
- 1);
-
- /* Clear the circular buffer */
- ao_context->circ_buf.head = 0;
- ao_context->circ_buf.tail = 0;
-
- /* Set to transparent mode */
- me4000_ao_simultaneous_disable(ao_context);
-
- /* Set to single mode in order to set default voltage */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- me4000_outl(0x0, ao_context->ctrl_reg);
-
- /* Set voltage to 0V */
- me4000_outl(0x8000, ao_context->single_reg);
-
- /* Set to fastest sample rate */
- me4000_outl(65, ao_context->timer_reg);
-
- /* Set the original mode and enable FIFO */
- me4000_outl(ME4000_AO_CONV_MODE_CONTINUOUS |
- ME4000_AO_CTRL_BIT_ENABLE_FIFO |
- ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP,
- ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- } else {
- /* Set to transparent mode */
- me4000_ao_simultaneous_disable(ao_context);
-
- /* Set voltage to 0V */
- me4000_outl(0x8000, ao_context->single_reg);
- }
-
- return 0;
-}
-
-static ssize_t me4000_ao_write_sing(struct file *filep, const char *buff,
- size_t cnt, loff_t *offp)
-{
- struct me4000_ao_context *ao_context = filep->private_data;
- u32 value;
- const u16 *buffer = (const u16 *)buff;
-
- CALL_PDEBUG("me4000_ao_write_sing() is executed\n");
-
- if (cnt != 2) {
- printk(KERN_ERR
- "%s:Write count is not 2\n", __func__);
- return -EINVAL;
- }
-
- if (get_user(value, buffer)) {
- printk(KERN_ERR
- "%s:Cannot copy data from user\n", __func__);
- return -EFAULT;
- }
-
- me4000_outl(value, ao_context->single_reg);
-
- return 2;
-}
-
-static ssize_t me4000_ao_write_wrap(struct file *filep, const char *buff,
- size_t cnt, loff_t *offp)
-{
- struct me4000_ao_context *ao_context = filep->private_data;
- size_t i;
- u32 value;
- u32 tmp;
- const u16 *buffer = (const u16 *)buff;
- size_t count = cnt / 2;
-
- CALL_PDEBUG("me4000_ao_write_wrap() is executed\n");
-
- /* Check if a conversion is already running */
- if (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "%s:There is already a conversion running\n", __func__);
- return -EBUSY;
- }
-
- if (count > ME4000_AO_FIFO_COUNT) {
- printk(KERN_ERR
- "%s:Can't load more than %d values\n", __func__,
- ME4000_AO_FIFO_COUNT);
- return -ENOSPC;
- }
-
- /* Reset the FIFO */
- tmp = inl(ao_context->ctrl_reg);
- tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_FIFO;
- outl(tmp, ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO;
- outl(tmp, ao_context->ctrl_reg);
-
- for (i = 0; i < count; i++) {
- if (get_user(value, buffer + i)) {
- printk(KERN_ERR
- "%s:Cannot copy data from user\n", __func__);
- return -EFAULT;
- }
- if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG)
- || ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG))
- value = value << 16;
- outl(value, ao_context->fifo_reg);
- }
- CALL_PDEBUG("me4000_ao_write_wrap() is leaved with %d\n", i * 2);
-
- return i * 2;
-}
-
-static ssize_t me4000_ao_write_cont(struct file *filep, const char *buff,
- size_t cnt, loff_t *offp)
-{
- struct me4000_ao_context *ao_context = filep->private_data;
- const u16 *buffer = (const u16 *)buff;
- size_t count = cnt / 2;
- unsigned long flags;
- u32 tmp;
- int c = 0;
- int k = 0;
- int ret = 0;
- u16 svalue;
- u32 lvalue;
- int i;
- wait_queue_head_t queue;
-
- CALL_PDEBUG("me4000_ao_write_cont() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Check count */
- if (count <= 0) {
- PDEBUG("me4000_ao_write_cont():Count is 0\n");
- return 0;
- }
-
- if (filep->f_flags & O_APPEND) {
- PDEBUG("me4000_ao_write_cont():Append data to data stream\n");
- while (count > 0) {
- if (filep->f_flags & O_NONBLOCK) {
- if (ao_context->pipe_flag) {
- printk(KERN_ERR
- "ME4000:me4000_ao_write_cont():Broken pipe in nonblocking write\n");
- return -EPIPE;
- }
- c = me4000_space_to_end(ao_context->circ_buf,
- ME4000_AO_BUFFER_COUNT);
- if (!c) {
- PDEBUG
- ("me4000_ao_write_cont():Returning from nonblocking write\n");
- break;
- }
- } else {
- wait_event_interruptible(ao_context->wait_queue,
- (c =
- me4000_space_to_end
- (ao_context->circ_buf,
- ME4000_AO_BUFFER_COUNT)));
- if (ao_context->pipe_flag) {
- printk(KERN_ERR
- "me4000_ao_write_cont():Broken pipe in blocking write\n");
- return -EPIPE;
- }
- if (signal_pending(current)) {
- printk(KERN_ERR
- "me4000_ao_write_cont():Wait for free buffer interrupted from signal\n");
- return -EINTR;
- }
- }
-
- PDEBUG("me4000_ao_write_cont():Space to end = %d\n", c);
-
- /* Only able to write size of free buffer or size of count */
- if (count < c)
- c = count;
-
- k = 2 * c;
- k -= copy_from_user(ao_context->circ_buf.buf +
- ao_context->circ_buf.head, buffer,
- k);
- c = k / 2;
- PDEBUG
- ("me4000_ao_write_cont():Copy %d values from user space\n",
- c);
-
- if (!c)
- return -EFAULT;
-
- ao_context->circ_buf.head =
- (ao_context->circ_buf.head +
- c) & (ME4000_AO_BUFFER_COUNT - 1);
- buffer += c;
- count -= c;
- ret += c;
-
- /* Values are now available so enable interrupts */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- if (me4000_buf_count
- (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ;
- me4000_outl(tmp, ao_context->ctrl_reg);
- }
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- }
-
- /* Wait until the state machine is stopped if O_SYNC is set */
- if (filep->f_flags & O_SYNC) {
- while (inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (ao_context->pipe_flag) {
- PDEBUG
- ("me4000_ao_write_cont():Broken pipe detected after sync\n");
- return -EPIPE;
- }
- if (signal_pending(current)) {
- printk(KERN_ERR
- "me4000_ao_write_cont():Wait on state machine after sync interrupted\n");
- return -EINTR;
- }
- }
- }
- } else {
- PDEBUG("me4000_ao_write_cont():Preload DAC FIFO\n");
- if ((me4000_inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM)) {
- printk(KERN_ERR
- "me4000_ao_write_cont():Can't Preload DAC FIFO while conversion is running\n");
- return -EBUSY;
- }
-
- /* Clear the FIFO */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp &=
- ~(ME4000_AO_CTRL_BIT_ENABLE_FIFO |
- ME4000_AO_CTRL_BIT_ENABLE_IRQ);
- me4000_outl(tmp, ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_FIFO;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- /* Clear the circular buffer */
- ao_context->circ_buf.head = 0;
- ao_context->circ_buf.tail = 0;
-
- /* Reset the broken pipe flag */
- ao_context->pipe_flag = 0;
-
- /* Only able to write size of fifo or count */
- c = ME4000_AO_FIFO_COUNT;
- if (count < c)
- c = count;
-
- PDEBUG
- ("me4000_ao_write_cont():Write %d values to DAC on 0x%lX\n",
- c, ao_context->fifo_reg);
-
- /* Write values to the fifo */
- for (i = 0; i < c; i++) {
- if (get_user(svalue, buffer))
- return -EFAULT;
-
- if (((ao_context->fifo_reg & 0xFF) ==
- ME4000_AO_01_FIFO_REG)
- || ((ao_context->fifo_reg & 0xFF) ==
- ME4000_AO_03_FIFO_REG)) {
- lvalue = ((u32) svalue) << 16;
- } else
- lvalue = (u32) svalue;
-
- outl(lvalue, ao_context->fifo_reg);
- buffer++;
- }
- count -= c;
- ret += c;
-
- while (1) {
- /* Get free buffer */
- c = me4000_space_to_end(ao_context->circ_buf,
- ME4000_AO_BUFFER_COUNT);
-
- if (c == 0)
- return 2 * ret;
-
- /* Only able to write size of free buffer or size of count */
- if (count < c)
- c = count;
-
- /* If count = 0 return to user */
- if (c <= 0) {
- PDEBUG
- ("me4000_ao_write_cont():Count reached 0\n");
- break;
- }
-
- k = 2 * c;
- k -= copy_from_user(ao_context->circ_buf.buf +
- ao_context->circ_buf.head, buffer,
- k);
- c = k / 2;
- PDEBUG
- ("me4000_ao_write_cont():Wrote %d values to buffer\n",
- c);
-
- if (!c)
- return -EFAULT;
-
- ao_context->circ_buf.head =
- (ao_context->circ_buf.head +
- c) & (ME4000_AO_BUFFER_COUNT - 1);
- buffer += c;
- count -= c;
- ret += c;
-
- /* If values in the buffer are available so enable interrupts */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- if (me4000_buf_count
- (ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
- PDEBUG
- ("me4000_ao_write_cont():Enable Interrupts\n");
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_IRQ;
- me4000_outl(tmp, ao_context->ctrl_reg);
- }
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- }
- }
-
- if (filep->f_flags & O_NONBLOCK)
- return (ret == 0) ? -EAGAIN : 2 * ret;
-
- return 2 * ret;
-}
-
-static unsigned int me4000_ao_poll_cont(struct file *file_p, poll_table *wait)
-{
- struct me4000_ao_context *ao_context;
- unsigned long mask = 0;
-
- CALL_PDEBUG("me4000_ao_poll_cont() is executed\n");
-
- ao_context = file_p->private_data;
-
- poll_wait(file_p, &ao_context->wait_queue, wait);
-
- /* Get free buffer */
- if (me4000_space_to_end(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT))
- mask |= POLLOUT | POLLWRNORM;
-
- CALL_PDEBUG("me4000_ao_poll_cont():Return mask %lX\n", mask);
-
- return mask;
-}
-
-static int me4000_ao_fsync_cont(struct file *file_p, struct dentry *dentry_p,
- int datasync)
-{
- struct me4000_ao_context *ao_context;
- wait_queue_head_t queue;
-
- CALL_PDEBUG("me4000_ao_fsync_cont() is executed\n");
-
- ao_context = file_p->private_data;
- init_waitqueue_head(&queue);
-
- while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- wait_event_interruptible_timeout(queue,
- !(inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM),
- 1);
- if (ao_context->pipe_flag) {
- printk(KERN_ERR
- "%s:Broken pipe detected\n", __func__);
- return -EPIPE;
- }
-
- if (signal_pending(current)) {
- printk(KERN_ERR
- "%s:Wait on state machine interrupted\n",
- __func__);
- return -EINTR;
- }
- }
-
- return 0;
-}
-
-static int me4000_ao_ioctl_sing(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ao_context *ao_context;
-
- CALL_PDEBUG("me4000_ao_ioctl_sing() is executed\n");
-
- ao_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- return -ENOTTY;
- PDEBUG("me4000_ao_ioctl_sing():Wrong magic number\n");
- }
-
- switch (service) {
- case ME4000_AO_EX_TRIG_SETUP:
- return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
- case ME4000_AO_EX_TRIG_ENABLE:
- return me4000_ao_ex_trig_enable(ao_context);
- case ME4000_AO_EX_TRIG_DISABLE:
- return me4000_ao_ex_trig_disable(ao_context);
- case ME4000_AO_PRELOAD:
- return me4000_ao_preload(ao_context);
- case ME4000_AO_PRELOAD_UPDATE:
- return me4000_ao_preload_update(ao_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ao_context->board_info);
- case ME4000_AO_SIMULTANEOUS_EX_TRIG:
- return me4000_ao_simultaneous_ex_trig(ao_context);
- case ME4000_AO_SIMULTANEOUS_SW:
- return me4000_ao_simultaneous_sw(ao_context);
- case ME4000_AO_SIMULTANEOUS_DISABLE:
- return me4000_ao_simultaneous_disable(ao_context);
- case ME4000_AO_SIMULTANEOUS_UPDATE:
- return
- me4000_ao_simultaneous_update(
- (struct me4000_ao_channel_list *)arg,
- ao_context);
- case ME4000_AO_EX_TRIG_TIMEOUT:
- return me4000_ao_ex_trig_timeout((unsigned long *)arg,
- ao_context);
- case ME4000_AO_DISABLE_DO:
- return me4000_ao_disable_do(ao_context);
- default:
- printk(KERN_ERR
- "me4000_ao_ioctl_sing():Service number invalid\n");
- return -ENOTTY;
- }
-
- return 0;
-}
-
-static int me4000_ao_ioctl_wrap(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ao_context *ao_context;
-
- CALL_PDEBUG("me4000_ao_ioctl_wrap() is executed\n");
-
- ao_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- return -ENOTTY;
- PDEBUG("me4000_ao_ioctl_wrap():Wrong magic number\n");
- }
-
- switch (service) {
- case ME4000_AO_START:
- return me4000_ao_start((unsigned long *)arg, ao_context);
- case ME4000_AO_STOP:
- return me4000_ao_stop(ao_context);
- case ME4000_AO_IMMEDIATE_STOP:
- return me4000_ao_immediate_stop(ao_context);
- case ME4000_AO_RESET:
- return me4000_ao_reset(ao_context);
- case ME4000_AO_TIMER_SET_DIVISOR:
- return me4000_ao_timer_set_divisor((u32 *) arg, ao_context);
- case ME4000_AO_EX_TRIG_SETUP:
- return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
- case ME4000_AO_EX_TRIG_ENABLE:
- return me4000_ao_ex_trig_enable(ao_context);
- case ME4000_AO_EX_TRIG_DISABLE:
- return me4000_ao_ex_trig_disable(ao_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ao_context->board_info);
- case ME4000_AO_FSM_STATE:
- return me4000_ao_fsm_state((int *)arg, ao_context);
- case ME4000_AO_ENABLE_DO:
- return me4000_ao_enable_do(ao_context);
- case ME4000_AO_DISABLE_DO:
- return me4000_ao_disable_do(ao_context);
- case ME4000_AO_SYNCHRONOUS_EX_TRIG:
- return me4000_ao_synchronous_ex_trig(ao_context);
- case ME4000_AO_SYNCHRONOUS_SW:
- return me4000_ao_synchronous_sw(ao_context);
- case ME4000_AO_SYNCHRONOUS_DISABLE:
- return me4000_ao_synchronous_disable(ao_context);
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ao_ioctl_cont(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ao_context *ao_context;
-
- CALL_PDEBUG("me4000_ao_ioctl_cont() is executed\n");
-
- ao_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- return -ENOTTY;
- PDEBUG("me4000_ao_ioctl_cont():Wrong magic number\n");
- }
-
- switch (service) {
- case ME4000_AO_START:
- return me4000_ao_start((unsigned long *)arg, ao_context);
- case ME4000_AO_STOP:
- return me4000_ao_stop(ao_context);
- case ME4000_AO_IMMEDIATE_STOP:
- return me4000_ao_immediate_stop(ao_context);
- case ME4000_AO_RESET:
- return me4000_ao_reset(ao_context);
- case ME4000_AO_TIMER_SET_DIVISOR:
- return me4000_ao_timer_set_divisor((u32 *) arg, ao_context);
- case ME4000_AO_EX_TRIG_SETUP:
- return me4000_ao_ex_trig_set_edge((int *)arg, ao_context);
- case ME4000_AO_EX_TRIG_ENABLE:
- return me4000_ao_ex_trig_enable(ao_context);
- case ME4000_AO_EX_TRIG_DISABLE:
- return me4000_ao_ex_trig_disable(ao_context);
- case ME4000_AO_ENABLE_DO:
- return me4000_ao_enable_do(ao_context);
- case ME4000_AO_DISABLE_DO:
- return me4000_ao_disable_do(ao_context);
- case ME4000_AO_FSM_STATE:
- return me4000_ao_fsm_state((int *)arg, ao_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ao_context->board_info);
- case ME4000_AO_SYNCHRONOUS_EX_TRIG:
- return me4000_ao_synchronous_ex_trig(ao_context);
- case ME4000_AO_SYNCHRONOUS_SW:
- return me4000_ao_synchronous_sw(ao_context);
- case ME4000_AO_SYNCHRONOUS_DISABLE:
- return me4000_ao_synchronous_disable(ao_context);
- case ME4000_AO_GET_FREE_BUFFER:
- return me4000_ao_get_free_buffer((unsigned long *)arg,
- ao_context);
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ao_start(unsigned long *arg,
- struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long ref;
- unsigned long timeout;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_start() is executed\n");
-
- if (get_user(timeout, arg)) {
- printk(KERN_ERR
- "me4000_ao_start():Cannot copy data from user\n");
- return -EFAULT;
- }
-
- init_waitqueue_head(&queue);
-
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = inl(ao_context->ctrl_reg);
- tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) {
- if (timeout) {
- ref = jiffies;
- while (!
- (inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ao_start():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- /* kernel 2.6 has different definitions for HZ
- * in user and kernel space */
- if ((jiffies - ref) > (timeout * HZ / USER_HZ)) {
- printk(KERN_ERR
- "ME4000:me4000_ao_start():Timeout reached\n");
- return -EIO;
- }
- }
- }
- } else {
- me4000_outl(0x8000, ao_context->single_reg);
- }
-
- return 0;
-}
-
-static int me4000_ao_stop(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long flags;
-
- init_waitqueue_head(&queue);
-
- CALL_PDEBUG("me4000_ao_stop() is executed\n");
-
- /* Set the stop bit */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_STOP;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "me4000_ao_stop():Wait on state machine after stop interrupted\n");
- return -EINTR;
- }
- }
-
- /* Clear the stop bit */
- /* tmp &= ~ME4000_AO_CTRL_BIT_STOP; */
- /* me4000_outl(tmp, ao_context->ctrl_reg); */
-
- return 0;
-}
-
-static int me4000_ao_immediate_stop(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long flags;
-
- init_waitqueue_head(&queue);
-
- CALL_PDEBUG("me4000_ao_immediate_stop() is executed\n");
-
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- while (inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "me4000_ao_immediate_stop():Wait on state machine after stop interrupted\n");
- return -EINTR;
- }
- }
-
- /* Clear the stop bits */
- /* tmp &= ~(ME4000_AO_CTRL_BIT_STOP | ME4000_AO_CTRL_BIT_IMMEDIATE_STOP); */
- /* me4000_outl(tmp, ao_context->ctrl_reg); */
-
- return 0;
-}
-
-static int me4000_ao_timer_set_divisor(u32 *arg,
- struct me4000_ao_context *ao_context)
-{
- u32 divisor;
- u32 tmp;
-
- CALL_PDEBUG("me4000_ao_timer set_divisor() is executed\n");
-
- if (get_user(divisor, arg))
- return -EFAULT;
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_timer_set_divisor():Can't set timer while DAC is running\n");
- return -EBUSY;
- }
-
- PDEBUG("me4000_ao_timer set_divisor():Divisor from user = %d\n",
- divisor);
-
- /* Check if the divisor is right. ME4000_AO_MIN_TICKS is the lowest */
- if (divisor < ME4000_AO_MIN_TICKS) {
- printk(KERN_ERR
- "ME4000:me4000_ao_timer set_divisor():Divisor to low\n");
- return -EINVAL;
- }
-
- /* Fix bug in Firmware */
- divisor -= 2;
-
- PDEBUG("me4000_ao_timer set_divisor():Divisor to HW = %d\n", divisor);
-
- /* Write the divisor */
- me4000_outl(divisor, ao_context->timer_reg);
-
- return 0;
-}
-
-static int me4000_ao_ex_trig_set_edge(int *arg,
- struct me4000_ao_context *ao_context)
-{
- int mode;
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_ex_trig_set_edge() is executed\n");
-
- if (get_user(mode, arg))
- return -EFAULT;
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_ex_trig_set_edge():Can't set trigger while DAC is running\n");
- return -EBUSY;
- }
-
- if (mode == ME4000_AO_TRIGGER_EXT_EDGE_RISING) {
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp &=
- ~(ME4000_AO_CTRL_BIT_EX_TRIG_EDGE |
- ME4000_AO_CTRL_BIT_EX_TRIG_BOTH);
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_FALLING) {
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp &= ~ME4000_AO_CTRL_BIT_EX_TRIG_BOTH;
- tmp |= ME4000_AO_CTRL_BIT_EX_TRIG_EDGE;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- } else if (mode == ME4000_AO_TRIGGER_EXT_EDGE_BOTH) {
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |=
- ME4000_AO_CTRL_BIT_EX_TRIG_EDGE |
- ME4000_AO_CTRL_BIT_EX_TRIG_BOTH;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
- } else {
- printk(KERN_ERR
- "me4000_ao_ex_trig_set_edge():Invalid trigger mode\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_ao_ex_trig_enable(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_ex_trig_enable() is executed\n");
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_ex_trig_enable():Can't enable trigger while DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_ex_trig_disable(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_ex_trig_disable() is executed\n");
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_ex_trig_disable():Can't disable trigger while DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_simultaneous_disable(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
-
- CALL_PDEBUG("me4000_ao_simultaneous_disable() is executed\n");
-
- /* Check if the state machine is stopped */
- /* Be careful here because this function is called from
- me4000_ao_synchronous disable */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_simultaneous_disable():Can't disable while DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- /* Disable preload bit */
- tmp &= ~(0x1 << ao_context->index);
- /* Disable hw simultaneous bit */
- tmp &= ~(0x1 << (ao_context->index + 16));
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- return 0;
-}
-
-static int me4000_ao_simultaneous_ex_trig(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
-
- CALL_PDEBUG("me4000_ao_simultaneous_ex_trig() is executed\n");
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- /* Enable preload bit */
- tmp |= (0x1 << ao_context->index);
- /* Enable hw simulatenous bit */
- tmp |= (0x1 << (ao_context->index + 16));
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- return 0;
-}
-
-static int me4000_ao_simultaneous_sw(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
-
- CALL_PDEBUG("me4000_ao_simultaneous_sw() is executed\n");
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- /* Enable preload bit */
- tmp |= (0x1 << ao_context->index);
- /* Enable hw simulatenous bit */
- tmp &= ~(0x1 << (ao_context->index + 16));
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- return 0;
-}
-
-static int me4000_ao_preload(struct me4000_ao_context *ao_context)
-{
- CALL_PDEBUG("me4000_ao_preload() is executed\n");
- return me4000_ao_simultaneous_sw(ao_context);
-}
-
-static int me4000_ao_preload_update(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- u32 ctrl;
- struct list_head *entry;
-
- CALL_PDEBUG("me4000_ao_preload_update() is executed\n");
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- list_for_each(entry, &ao_context->board_info->ao_context_list) {
- /* The channels we update must be in the following state :
- - Mode A
- - Hardware trigger is disabled
- - Corresponding simultaneous bit is reset
- */
- ctrl = me4000_inl(ao_context->ctrl_reg);
- if (!
- (ctrl &
- (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1 |
- ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG))) {
- if (!
- (tmp &
- (0x1 <<
- (((struct me4000_ao_context *)entry)->index
- + 16)))) {
- tmp &=
- ~(0x1 <<
- (((struct me4000_ao_context *)entry)->
- index));
- }
- }
- }
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- return 0;
-}
-
-static int me4000_ao_simultaneous_update(struct me4000_ao_channel_list *arg,
- struct me4000_ao_context *ao_context)
-{
- int err;
- int i;
- u32 tmp;
- struct me4000_ao_channel_list channels;
-
- CALL_PDEBUG("me4000_ao_simultaneous_update() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&channels, arg,
- sizeof(struct me4000_ao_channel_list));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ao_simultaneous_update():Can't copy command\n");
- return -EFAULT;
- }
-
- channels.list =
- kzalloc(sizeof(unsigned long) * channels.count, GFP_KERNEL);
- if (!channels.list) {
- printk(KERN_ERR
- "ME4000:me4000_ao_simultaneous_update():Can't get buffer\n");
- return -ENOMEM;
- }
-
- /* Copy channel list from user */
- err =
- copy_from_user(channels.list, arg->list,
- sizeof(unsigned long) * channels.count);
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ao_simultaneous_update():Can't copy list\n");
- kfree(channels.list);
- return -EFAULT;
- }
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- for (i = 0; i < channels.count; i++) {
- if (channels.list[i] >
- ao_context->board_info->board_p->ao.count) {
- spin_unlock(&ao_context->board_info->preload_lock);
- kfree(channels.list);
- printk(KERN_ERR
- "ME4000:me4000_ao_simultaneous_update():Invalid board number specified\n");
- return -EFAULT;
- }
- /* Clear the preload bit */
- tmp &= ~(0x1 << channels.list[i]);
- /* Clear the hw simultaneous bit */
- tmp &= ~(0x1 << (channels.list[i] + 16));
- }
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
- kfree(channels.list);
-
- return 0;
-}
-
-static int me4000_ao_synchronous_ex_trig(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_synchronous_ex_trig() is executed\n");
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "me4000_ao_synchronous_ex_trig(): DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- /* Disable synchronous sw bit */
- tmp &= ~(0x1 << ao_context->index);
- /* Enable synchronous hw bit */
- tmp |= 0x1 << (ao_context->index + 16);
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- /* Make runnable */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) {
- tmp &=
- ~(ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
- me4000_outl(tmp, ao_context->ctrl_reg);
- }
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_synchronous_sw(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_synchronous_sw() is executed\n");
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR "me4000_ao_synchronous_sw(): DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock(&ao_context->board_info->preload_lock);
- tmp = me4000_inl(ao_context->preload_reg);
- /* Enable synchronous sw bit */
- tmp |= 0x1 << ao_context->index;
- /* Disable synchronous hw bit */
- tmp &= ~(0x1 << (ao_context->index + 16));
- me4000_outl(tmp, ao_context->preload_reg);
- spin_unlock(&ao_context->board_info->preload_lock);
-
- /* Make runnable */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = me4000_inl(ao_context->ctrl_reg);
- if (tmp & (ME4000_AO_CTRL_BIT_MODE_0 | ME4000_AO_CTRL_BIT_MODE_1)) {
- tmp &=
- ~(ME4000_AO_CTRL_BIT_STOP |
- ME4000_AO_CTRL_BIT_IMMEDIATE_STOP);
- me4000_outl(tmp, ao_context->ctrl_reg);
- }
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_synchronous_disable(struct me4000_ao_context *ao_context)
-{
- return me4000_ao_simultaneous_disable(ao_context);
-}
-
-static int me4000_ao_get_free_buffer(unsigned long *arg,
- struct me4000_ao_context *ao_context)
-{
- unsigned long c;
- int err;
-
- c = me4000_buf_space(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT);
-
- err = copy_to_user(arg, &c, sizeof(unsigned long));
- if (err) {
- printk(KERN_ERR
- "%s:Can't copy to user space\n", __func__);
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int me4000_ao_ex_trig_timeout(unsigned long *arg,
- struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long ref;
- unsigned long timeout;
-
- CALL_PDEBUG("me4000_ao_ex_trig_timeout() is executed\n");
-
- if (get_user(timeout, arg)) {
- printk(KERN_ERR
- "me4000_ao_ex_trig_timeout():Cannot copy data from user\n");
- return -EFAULT;
- }
-
- init_waitqueue_head(&queue);
-
- tmp = inl(ao_context->ctrl_reg);
-
- if ((tmp & ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG)) {
- if (timeout) {
- ref = jiffies;
- while ((inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- /* kernel 2.6 has different definitions for HZ
- * in user and kernel space */
- if ((jiffies - ref) > (timeout * HZ / USER_HZ)) {
- printk(KERN_ERR
- "ME4000:me4000_ao_ex_trig_timeout():Timeout reached\n");
- return -EIO;
- }
- }
- } else {
- while ((inl(ao_context->status_reg) &
- ME4000_AO_STATUS_BIT_FSM)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ao_ex_trig_timeout():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- }
- }
- } else {
- printk(KERN_ERR
- "ME4000:me4000_ao_ex_trig_timeout():External Trigger is not enabled\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_ao_enable_do(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_enable_do() is executed\n");
-
- /* Only available for analog output 3 */
- if (ao_context->index != 3) {
- printk(KERN_ERR
- "me4000_ao_enable_do():Only available for analog output 3\n");
- return -ENOTTY;
- }
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR "me4000_ao_enable_do(): DAC is running\n");
- return -EBUSY;
- }
-
- /* Set the stop bit */
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_ENABLE_DO;
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_disable_do(struct me4000_ao_context *ao_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ao_disable_do() is executed\n");
-
- /* Only available for analog output 3 */
- if (ao_context->index != 3) {
- printk(KERN_ERR
- "me4000_ao_disable():Only available for analog output 3\n");
- return -ENOTTY;
- }
-
- /* Check if the state machine is stopped */
- tmp = me4000_inl(ao_context->status_reg);
- if (tmp & ME4000_AO_STATUS_BIT_FSM) {
- printk(KERN_ERR "me4000_ao_disable_do(): DAC is running\n");
- return -EBUSY;
- }
-
- spin_lock_irqsave(&ao_context->int_lock, flags);
- tmp = inl(ao_context->ctrl_reg);
- tmp &= ~(ME4000_AO_CTRL_BIT_ENABLE_DO);
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock_irqrestore(&ao_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ao_fsm_state(int *arg, struct me4000_ao_context *ao_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ao_fsm_state() is executed\n");
-
- tmp =
- (me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM) ? 1
- : 0;
-
- if (ao_context->pipe_flag) {
- printk(KERN_ERR "me4000_ao_fsm_state():Broken pipe detected\n");
- return -EPIPE;
- }
-
- if (put_user(tmp, arg)) {
- printk(KERN_ERR "me4000_ao_fsm_state():Cannot copy to user\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-/*------------------------- Analog input stuff -------------------------------*/
-
-static int me4000_ai_prepare(struct me4000_ai_context *ai_context)
-{
- wait_queue_head_t queue;
- int err;
-
- CALL_PDEBUG("me4000_ai_prepare() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Set the new mode and stop bits */
- me4000_outl(ai_context->
- mode | ME4000_AI_CTRL_BIT_STOP |
- ME4000_AI_CTRL_BIT_IMMEDIATE_STOP, ai_context->ctrl_reg);
-
- /* Set the timer registers */
- ai_context->chan_timer = 66;
- ai_context->chan_pre_timer = 66;
- ai_context->scan_timer_low = 0;
- ai_context->scan_timer_high = 0;
-
- me4000_outl(65, ai_context->chan_timer_reg);
- me4000_outl(65, ai_context->chan_pre_timer_reg);
- me4000_outl(0, ai_context->scan_timer_low_reg);
- me4000_outl(0, ai_context->scan_timer_high_reg);
- me4000_outl(0, ai_context->scan_pre_timer_low_reg);
- me4000_outl(0, ai_context->scan_pre_timer_high_reg);
-
- ai_context->channel_list_count = 0;
-
- if (ai_context->mode) {
- /* Request the interrupt line */
- err =
- request_irq(ai_context->irq, me4000_ai_isr,
- IRQF_DISABLED | IRQF_SHARED, ME4000_NAME,
- ai_context);
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_prepare():Can't get interrupt line");
- return -ENODEV;
- }
-
- /* Allocate circular buffer */
- ai_context->circ_buf.buf =
- kzalloc(ME4000_AI_BUFFER_SIZE, GFP_KERNEL);
- if (!ai_context->circ_buf.buf) {
- printk(KERN_ERR
- "ME4000:me4000_ai_prepare():Can't get circular buffer\n");
- free_irq(ai_context->irq, ai_context);
- return -ENOMEM;
- }
-
- /* Clear the circular buffer */
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
- }
-
- return 0;
-}
-
-static int me4000_ai_reset(struct me4000_ai_context *ai_context)
-{
- wait_queue_head_t queue;
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_reset() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /*
- * First stop conversion of the state machine before reconfigure.
- * If not stopped before configuring mode, it could
- * walk in a undefined state.
- */
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "me4000_ai_reset():Wait on state machine after stop interrupted\n");
- return -EINTR;
- }
- }
-
- /* Clear the control register and set the stop bits */
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- me4000_outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
- ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- /* Reset timer registers */
- ai_context->chan_timer = 66;
- ai_context->chan_pre_timer = 66;
- ai_context->scan_timer_low = 0;
- ai_context->scan_timer_high = 0;
- ai_context->sample_counter = 0;
- ai_context->sample_counter_reload = 0;
-
- me4000_outl(65, ai_context->chan_timer_reg);
- me4000_outl(65, ai_context->chan_pre_timer_reg);
- me4000_outl(0, ai_context->scan_timer_low_reg);
- me4000_outl(0, ai_context->scan_timer_high_reg);
- me4000_outl(0, ai_context->scan_pre_timer_low_reg);
- me4000_outl(0, ai_context->scan_pre_timer_high_reg);
- me4000_outl(0, ai_context->sample_counter_reg);
-
- ai_context->channel_list_count = 0;
-
- /* Clear the circular buffer */
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
-
- return 0;
-}
-
-static int me4000_ai_ioctl_sing(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ai_context *ai_context;
-
- CALL_PDEBUG("me4000_ai_ioctl_sing() is executed\n");
-
- ai_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_ai_ioctl_sing():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR
- "me4000_ai_ioctl_sing():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_AI_SINGLE:
- return me4000_ai_single((struct me4000_ai_single *)arg,
- ai_context);
- case ME4000_AI_EX_TRIG_ENABLE:
- return me4000_ai_ex_trig_enable(ai_context);
- case ME4000_AI_EX_TRIG_DISABLE:
- return me4000_ai_ex_trig_disable(ai_context);
- case ME4000_AI_EX_TRIG_SETUP:
- return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg,
- ai_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ai_context->board_info);
- case ME4000_AI_OFFSET_ENABLE:
- return me4000_ai_offset_enable(ai_context);
- case ME4000_AI_OFFSET_DISABLE:
- return me4000_ai_offset_disable(ai_context);
- case ME4000_AI_FULLSCALE_ENABLE:
- return me4000_ai_fullscale_enable(ai_context);
- case ME4000_AI_FULLSCALE_DISABLE:
- return me4000_ai_fullscale_disable(ai_context);
- case ME4000_AI_EEPROM_READ:
- return me4000_eeprom_read((struct me4000_eeprom *)arg,
- ai_context);
- case ME4000_AI_EEPROM_WRITE:
- return me4000_eeprom_write((struct me4000_eeprom *)arg,
- ai_context);
- default:
- printk(KERN_ERR
- "me4000_ai_ioctl_sing():Invalid service number\n");
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ai_single(struct me4000_ai_single *arg,
- struct me4000_ai_context *ai_context)
-{
- struct me4000_ai_single cmd;
- int err;
- u32 tmp;
- wait_queue_head_t queue;
- unsigned long jiffy;
-
- CALL_PDEBUG("me4000_ai_single() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_single));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Check range parameter */
- switch (cmd.range) {
- case ME4000_AI_LIST_RANGE_BIPOLAR_10:
- case ME4000_AI_LIST_RANGE_BIPOLAR_2_5:
- case ME4000_AI_LIST_RANGE_UNIPOLAR_10:
- case ME4000_AI_LIST_RANGE_UNIPOLAR_2_5:
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Invalid range specified\n");
- return -EINVAL;
- }
-
- /* Check mode and channel number */
- switch (cmd.mode) {
- case ME4000_AI_LIST_INPUT_SINGLE_ENDED:
- if (cmd.channel >= ai_context->board_info->board_p->ai.count) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Analog input is not available\n");
- return -EINVAL;
- }
- break;
- case ME4000_AI_LIST_INPUT_DIFFERENTIAL:
- if (cmd.channel >=
- ai_context->board_info->board_p->ai.diff_count) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Analog input is not available in differential mode\n");
- return -EINVAL;
- }
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Invalid mode specified\n");
- return -EINVAL;
- }
-
- /* Clear channel list, data fifo and both stop bits */
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &=
- ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO |
- ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- /* Enable channel list and data fifo */
- tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- /* Generate channel list entry */
- me4000_outl(cmd.channel | cmd.range | cmd.
- mode | ME4000_AI_LIST_LAST_ENTRY,
- ai_context->channel_list_reg);
-
- /* Set the timer to maximum */
- me4000_outl(66, ai_context->chan_timer_reg);
- me4000_outl(66, ai_context->chan_pre_timer_reg);
-
- if (tmp & ME4000_AI_CTRL_BIT_EX_TRIG) {
- jiffy = jiffies;
- while (!
- (me4000_inl(ai_context->status_reg) &
- ME4000_AI_STATUS_BIT_EF_DATA)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- /* 2.6 has different definitions for HZ in user and kernel space */
- if (((jiffies - jiffy) > (cmd.timeout * HZ / USER_HZ)) && cmd.timeout) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Timeout reached\n");
- return -EIO;
- }
- }
- } else {
- /* Start conversion */
- me4000_inl(ai_context->start_reg);
-
- /* Wait until ready */
- udelay(10);
- if (!
- (me4000_inl(ai_context->status_reg) &
- ME4000_AI_STATUS_BIT_EF_DATA)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Value not available after wait\n");
- return -EIO;
- }
- }
-
- /* Read value from data fifo */
- cmd.value = me4000_inl(ai_context->data_reg) & 0xFFFF;
-
- /* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(struct me4000_ai_single));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_single():Can't copy to user space\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int me4000_ai_ioctl_sw(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ai_context *ai_context;
-
- CALL_PDEBUG("me4000_ai_ioctl_sw() is executed\n");
-
- ai_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_ai_ioctl_sw():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR
- "me4000_ai_ioctl_sw():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_AI_SC_SETUP:
- return me4000_ai_sc_setup((struct me4000_ai_sc *)arg,
- ai_context);
- case ME4000_AI_CONFIG:
- return me4000_ai_config((struct me4000_ai_config *)arg,
- ai_context);
- case ME4000_AI_START:
- return me4000_ai_start(ai_context);
- case ME4000_AI_STOP:
- return me4000_ai_stop(ai_context);
- case ME4000_AI_IMMEDIATE_STOP:
- return me4000_ai_immediate_stop(ai_context);
- case ME4000_AI_FSM_STATE:
- return me4000_ai_fsm_state((int *)arg, ai_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ai_context->board_info);
- case ME4000_AI_EEPROM_READ:
- return me4000_eeprom_read((struct me4000_eeprom *)arg,
- ai_context);
- case ME4000_AI_EEPROM_WRITE:
- return me4000_eeprom_write((struct me4000_eeprom *)arg,
- ai_context);
- case ME4000_AI_GET_COUNT_BUFFER:
- return me4000_ai_get_count_buffer((unsigned long *)arg,
- ai_context);
- default:
- printk(KERN_ERR
- "%s:Invalid service number %d\n", __func__, service);
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ai_ioctl_ext(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ai_context *ai_context;
-
- CALL_PDEBUG("me4000_ai_ioctl_ext() is executed\n");
-
- ai_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_ai_ioctl_ext():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR
- "me4000_ai_ioctl_ext():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_AI_SC_SETUP:
- return me4000_ai_sc_setup((struct me4000_ai_sc *)arg,
- ai_context);
- case ME4000_AI_CONFIG:
- return me4000_ai_config((struct me4000_ai_config *)arg,
- ai_context);
- case ME4000_AI_START:
- return me4000_ai_start_ex((unsigned long *)arg, ai_context);
- case ME4000_AI_STOP:
- return me4000_ai_stop(ai_context);
- case ME4000_AI_IMMEDIATE_STOP:
- return me4000_ai_immediate_stop(ai_context);
- case ME4000_AI_EX_TRIG_ENABLE:
- return me4000_ai_ex_trig_enable(ai_context);
- case ME4000_AI_EX_TRIG_DISABLE:
- return me4000_ai_ex_trig_disable(ai_context);
- case ME4000_AI_EX_TRIG_SETUP:
- return me4000_ai_ex_trig_setup((struct me4000_ai_trigger *)arg,
- ai_context);
- case ME4000_AI_FSM_STATE:
- return me4000_ai_fsm_state((int *)arg, ai_context);
- case ME4000_GET_USER_INFO:
- return me4000_get_user_info((struct me4000_user_info *)arg,
- ai_context->board_info);
- case ME4000_AI_GET_COUNT_BUFFER:
- return me4000_ai_get_count_buffer((unsigned long *)arg,
- ai_context);
- default:
- printk(KERN_ERR
- "%s:Invalid service number %d\n", __func__ , service);
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ai_fasync(int fd, struct file *file_p, int mode)
-{
- struct me4000_ai_context *ai_context;
-
- CALL_PDEBUG("me4000_ao_fasync_cont() is executed\n");
-
- ai_context = file_p->private_data;
- return fasync_helper(fd, file_p, mode, &ai_context->fasync_p);
-}
-
-static int me4000_ai_config(struct me4000_ai_config *arg,
- struct me4000_ai_context *ai_context)
-{
- struct me4000_ai_config cmd;
- u32 *list = NULL;
- u32 mode;
- int i;
- int err;
- wait_queue_head_t queue;
- u64 scan;
- u32 tmp;
-
- CALL_PDEBUG("me4000_ai_config() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Check if conversion is stopped */
- if (inl(ai_context->ctrl_reg) & ME4000_AI_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Conversion is not stopped\n");
- err = -EBUSY;
- goto AI_CONFIG_ERR;
- }
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_config));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Can't copy from user space\n");
- err = -EFAULT;
- goto AI_CONFIG_ERR;
- }
-
- PDEBUG
- ("me4000_ai_config():chan = %ld, pre_chan = %ld, scan_low = %ld, scan_high = %ld, count = %ld\n",
- cmd.timer.chan, cmd.timer.pre_chan, cmd.timer.scan_low,
- cmd.timer.scan_high, cmd.channel_list.count);
-
- /* Check whether sample and hold is available for this board */
- if (cmd.sh) {
- if (!ai_context->board_info->board_p->ai.sh_count) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Sample and Hold is not available for this board\n");
- err = -ENODEV;
- goto AI_CONFIG_ERR;
- }
- }
-
- /* Check the channel list size */
- if (cmd.channel_list.count > ME4000_AI_CHANNEL_LIST_COUNT) {
- printk(KERN_ERR
- "me4000_ai_config():Channel list is to large\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
-
- /* Copy channel list from user */
- list = kmalloc(sizeof(u32) * cmd.channel_list.count, GFP_KERNEL);
- if (!list) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Can't get memory for channel list\n");
- err = -ENOMEM;
- goto AI_CONFIG_ERR;
- }
- err =
- copy_from_user(list, cmd.channel_list.list,
- sizeof(u32) * cmd.channel_list.count);
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Can't copy from user space\n");
- err = -EFAULT;
- goto AI_CONFIG_ERR;
- }
-
- /* Check if last entry bit is set */
- if (!(list[cmd.channel_list.count - 1] & ME4000_AI_LIST_LAST_ENTRY)) {
- printk(KERN_WARNING
- "me4000_ai_config():Last entry bit is not set\n");
- list[cmd.channel_list.count - 1] |= ME4000_AI_LIST_LAST_ENTRY;
- }
-
- /* Check whether mode is equal for all entries */
- mode = list[0] & 0x20;
- for (i = 0; i < cmd.channel_list.count; i++) {
- if ((list[i] & 0x20) != mode) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Mode is not equal for all entries\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
- }
-
- /* Check whether channels are available for this mode */
- if (mode == ME4000_AI_LIST_INPUT_SINGLE_ENDED) {
- for (i = 0; i < cmd.channel_list.count; i++) {
- if ((list[i] & 0x1F) >=
- ai_context->board_info->board_p->ai.count) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Channel is not available for single ended\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
- }
- } else if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) {
- for (i = 0; i < cmd.channel_list.count; i++) {
- if ((list[i] & 0x1F) >=
- ai_context->board_info->board_p->ai.diff_count) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Channel is not available for differential\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
- }
- }
-
- /* Check if bipolar is set for all entries when in differential mode */
- if (mode == ME4000_AI_LIST_INPUT_DIFFERENTIAL) {
- for (i = 0; i < cmd.channel_list.count; i++) {
- if ((list[i] & 0xC0) != ME4000_AI_LIST_RANGE_BIPOLAR_10
- && (list[i] & 0xC0) !=
- ME4000_AI_LIST_RANGE_BIPOLAR_2_5) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Bipolar is not selected in differential mode\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
- }
- }
-
- if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_VALUE) {
- /* Check for minimum channel divisor */
- if (cmd.timer.chan < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Channel timer divisor is to low\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
-
- /* Check if minimum channel divisor is adjusted when sample and hold is activated */
- if ((cmd.sh) && (cmd.timer.chan != ME4000_AI_MIN_TICKS)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Channel timer divisor must be at minimum when sample and hold is activated\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
-
- /* Check for minimum channel pre divisor */
- if (cmd.timer.pre_chan < ME4000_AI_MIN_TICKS) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Channel pre timer divisor is to low\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
-
- /* Write the channel timers */
- me4000_outl(cmd.timer.chan - 1, ai_context->chan_timer_reg);
- me4000_outl(cmd.timer.pre_chan - 1,
- ai_context->chan_pre_timer_reg);
-
- /* Save the timer values in the board context */
- ai_context->chan_timer = cmd.timer.chan;
- ai_context->chan_pre_timer = cmd.timer.pre_chan;
-
- if (ai_context->mode != ME4000_AI_ACQ_MODE_EXT_SINGLE_CHANLIST) {
- /* Check for scan timer divisor */
- scan =
- (u64) cmd.timer.scan_low | ((u64) cmd.timer.
- scan_high << 32);
- if (scan != 0) {
- if (scan <
- cmd.channel_list.count * cmd.timer.chan +
- 1) {
- printk(KERN_ERR
- "ME4000:me4000_ai_config():Scan timer divisor is to low\n");
- err = -EINVAL;
- goto AI_CONFIG_ERR;
- }
- }
-
- /* Write the scan timers */
- if (scan != 0) {
- scan--;
- tmp = (u32) (scan & 0xFFFFFFFF);
- me4000_outl(tmp,
- ai_context->scan_timer_low_reg);
- tmp = (u32) ((scan >> 32) & 0xFFFFFFFF);
- me4000_outl(tmp,
- ai_context->scan_timer_high_reg);
-
- scan =
- scan - (cmd.timer.chan - 1) +
- (cmd.timer.pre_chan - 1);
- tmp = (u32) (scan & 0xFFFFFFFF);
- me4000_outl(tmp,
- ai_context->scan_pre_timer_low_reg);
- tmp = (u32) ((scan >> 32) & 0xFFFFFFFF);
- me4000_outl(tmp,
- ai_context->
- scan_pre_timer_high_reg);
- } else {
- me4000_outl(0x0,
- ai_context->scan_timer_low_reg);
- me4000_outl(0x0,
- ai_context->scan_timer_high_reg);
-
- me4000_outl(0x0,
- ai_context->scan_pre_timer_low_reg);
- me4000_outl(0x0,
- ai_context->
- scan_pre_timer_high_reg);
- }
-
- ai_context->scan_timer_low = cmd.timer.scan_low;
- ai_context->scan_timer_high = cmd.timer.scan_high;
- }
- }
-
- /* Clear the channel list */
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_CHANNEL_FIFO;
- me4000_outl(tmp, ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- /* Write the channel list */
- for (i = 0; i < cmd.channel_list.count; i++)
- me4000_outl(list[i], ai_context->channel_list_reg);
-
- /* Setup sample and hold */
- if (cmd.sh) {
- tmp |= ME4000_AI_CTRL_BIT_SAMPLE_HOLD;
- me4000_outl(tmp, ai_context->ctrl_reg);
- } else {
- tmp &= ~ME4000_AI_CTRL_BIT_SAMPLE_HOLD;
- me4000_outl(tmp, ai_context->ctrl_reg);
- }
-
- /* Save the channel list size in the board context */
- ai_context->channel_list_count = cmd.channel_list.count;
-
- kfree(list);
-
- return 0;
-
-AI_CONFIG_ERR:
-
- /* Reset the timers */
- ai_context->chan_timer = 66;
- ai_context->chan_pre_timer = 66;
- ai_context->scan_timer_low = 0;
- ai_context->scan_timer_high = 0;
-
- me4000_outl(65, ai_context->chan_timer_reg);
- me4000_outl(65, ai_context->chan_pre_timer_reg);
- me4000_outl(0, ai_context->scan_timer_high_reg);
- me4000_outl(0, ai_context->scan_timer_low_reg);
- me4000_outl(0, ai_context->scan_pre_timer_high_reg);
- me4000_outl(0, ai_context->scan_pre_timer_low_reg);
-
- ai_context->channel_list_count = 0;
-
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &=
- ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_SAMPLE_HOLD);
-
- kfree(list);
-
- return err;
-
-}
-
-static int ai_common_start(struct me4000_ai_context *ai_context)
-{
- u32 tmp;
- CALL_PDEBUG("ai_common_start() is executed\n");
-
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- /* Check if conversion is stopped */
- if (tmp & ME4000_AI_STATUS_BIT_FSM) {
- printk(KERN_ERR
- "ME4000:ai_common_start():Conversion is not stopped\n");
- return -EBUSY;
- }
-
- /* Clear data fifo, disable all interrupts, clear sample counter reload */
- tmp &= ~(ME4000_AI_CTRL_BIT_DATA_FIFO | ME4000_AI_CTRL_BIT_LE_IRQ |
- ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_SC_RELOAD);
-
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- /* Clear circular buffer */
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
-
- /* Enable data fifo */
- tmp |= ME4000_AI_CTRL_BIT_DATA_FIFO;
-
- /* Determine interrupt setup */
- if (ai_context->sample_counter && !ai_context->sample_counter_reload) {
- /* Enable Half Full Interrupt and Sample Counter Interrupt */
- tmp |= ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ;
- } else if (ai_context->sample_counter
- && ai_context->sample_counter_reload) {
- if (ai_context->sample_counter <= ME4000_AI_FIFO_COUNT / 2) {
- /* Enable only Sample Counter Interrupt */
- tmp |=
- ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_SC_RELOAD;
- } else {
- /* Enable Half Full Interrupt and Sample Counter Interrupt */
- tmp |=
- ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_SC_RELOAD;
- }
- } else {
- /* Enable only Half Full Interrupt */
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
- }
-
- /* Clear the stop bits */
- tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
-
- /* Write setup to hardware */
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- /* Write sample counter */
- me4000_outl(ai_context->sample_counter, ai_context->sample_counter_reg);
-
- return 0;
-}
-
-static int me4000_ai_start(struct me4000_ai_context *ai_context)
-{
- int err;
- CALL_PDEBUG("me4000_ai_start() is executed\n");
-
- /* Prepare Hardware */
- err = ai_common_start(ai_context);
- if (err)
- return err;
-
- /* Start conversion by dummy read */
- me4000_inl(ai_context->start_reg);
-
- return 0;
-}
-
-static int me4000_ai_start_ex(unsigned long *arg,
- struct me4000_ai_context *ai_context)
-{
- int err;
- wait_queue_head_t queue;
- unsigned long ref;
- unsigned long timeout;
-
- CALL_PDEBUG("me4000_ai_start_ex() is executed\n");
-
- if (get_user(timeout, arg)) {
- printk(KERN_ERR
- "me4000_ai_start_ex():Cannot copy data from user\n");
- return -EFAULT;
- }
-
- init_waitqueue_head(&queue);
-
- /* Prepare Hardware */
- err = ai_common_start(ai_context);
- if (err)
- return err;
-
- if (timeout) {
- ref = jiffies;
- while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- /* 2.6 has different definitions for HZ in user and kernel space */
- if ((jiffies - ref) > (timeout * HZ / USER_HZ)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_start_ex():Timeout reached\n");
- return -EIO;
- }
- }
- } else {
- while (!(inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_start_ex():Wait on start of state machine interrupted\n");
- return -EINTR;
- }
- }
- }
-
- return 0;
-}
-
-static int me4000_ai_stop(struct me4000_ai_context *ai_context)
-{
- wait_queue_head_t queue;
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_stop() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Disable irqs and clear data fifo */
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &=
- ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_DATA_FIFO);
- /* Stop conversion of the state machine */
- tmp |= ME4000_AI_CTRL_BIT_STOP;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- /* Clear circular buffer */
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
-
- while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n");
- return -EINTR;
- }
- }
-
- return 0;
-}
-
-static int me4000_ai_immediate_stop(struct me4000_ai_context *ai_context)
-{
- wait_queue_head_t queue;
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_stop() is executed\n");
-
- init_waitqueue_head(&queue);
-
- /* Disable irqs and clear data fifo */
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &=
- ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_DATA_FIFO);
- /* Stop conversion of the state machine */
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- /* Clear circular buffer */
- ai_context->circ_buf.head = 0;
- ai_context->circ_buf.tail = 0;
-
- while (inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) {
- interruptible_sleep_on_timeout(&queue, 1);
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_stop():Wait on state machine after stop interrupted\n");
- return -EINTR;
- }
- }
-
- return 0;
-}
-
-static int me4000_ai_ex_trig_enable(struct me4000_ai_context *ai_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_ex_trig_enable() is executed\n");
-
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_EX_TRIG;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ai_ex_trig_disable(struct me4000_ai_context *ai_context)
-{
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_ex_trig_disable() is executed\n");
-
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
-
- return 0;
-}
-
-static int me4000_ai_ex_trig_setup(struct me4000_ai_trigger *arg,
- struct me4000_ai_context *ai_context)
-{
- struct me4000_ai_trigger cmd;
- int err;
- u32 tmp;
- unsigned long flags;
-
- CALL_PDEBUG("me4000_ai_ex_trig_setup() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_trigger));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_ex_trig_setup():Can't copy from user space\n");
- return -EFAULT;
- }
-
- spin_lock_irqsave(&ai_context->int_lock, flags);
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- if (cmd.mode == ME4000_AI_TRIGGER_EXT_DIGITAL) {
- tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG;
- } else if (cmd.mode == ME4000_AI_TRIGGER_EXT_ANALOG) {
- if (!ai_context->board_info->board_p->ai.ex_trig_analog) {
- printk(KERN_ERR
- "ME4000:me4000_ai_ex_trig_setup():No analog trigger available\n");
- return -EINVAL;
- }
- tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG;
- } else {
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
- printk(KERN_ERR
- "ME4000:me4000_ai_ex_trig_setup():Invalid trigger mode specified\n");
- return -EINVAL;
- }
-
- if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_RISING) {
- tmp &=
- ~(ME4000_AI_CTRL_BIT_EX_TRIG_BOTH |
- ME4000_AI_CTRL_BIT_EX_TRIG_FALLING);
- } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_FALLING) {
- tmp |= ME4000_AI_CTRL_BIT_EX_TRIG_FALLING;
- tmp &= ~ME4000_AI_CTRL_BIT_EX_TRIG_BOTH;
- } else if (cmd.edge == ME4000_AI_TRIGGER_EXT_EDGE_BOTH) {
- tmp |=
- ME4000_AI_CTRL_BIT_EX_TRIG_BOTH |
- ME4000_AI_CTRL_BIT_EX_TRIG_FALLING;
- } else {
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
- printk(KERN_ERR
- "ME4000:me4000_ai_ex_trig_setup():Invalid trigger edge specified\n");
- return -EINVAL;
- }
-
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
- return 0;
-}
-
-static int me4000_ai_sc_setup(struct me4000_ai_sc *arg,
- struct me4000_ai_context *ai_context)
-{
- struct me4000_ai_sc cmd;
- int err;
-
- CALL_PDEBUG("me4000_ai_sc_setup() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_ai_sc));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_ai_sc_setup():Can't copy from user space\n");
- return -EFAULT;
- }
-
- ai_context->sample_counter = cmd.value;
- ai_context->sample_counter_reload = cmd.reload;
-
- return 0;
-}
-
-static ssize_t me4000_ai_read(struct file *filep, char *buff, size_t cnt,
- loff_t *offp)
-{
- struct me4000_ai_context *ai_context = filep->private_data;
- s16 *buffer = (s16 *) buff;
- size_t count = cnt / 2;
- unsigned long flags;
- int tmp;
- int c = 0;
- int k = 0;
- int ret = 0;
- wait_queue_t wait;
-
- CALL_PDEBUG("me4000_ai_read() is executed\n");
-
- init_waitqueue_entry(&wait, current);
-
- /* Check count */
- if (count <= 0) {
- PDEBUG("me4000_ai_read():Count is 0\n");
- return 0;
- }
-
- while (count > 0) {
- if (filep->f_flags & O_NONBLOCK) {
- c = me4000_values_to_end(ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT);
- if (!c) {
- PDEBUG
- ("me4000_ai_read():Returning from nonblocking read\n");
- break;
- }
- } else {
- /* Check if conversion is still running */
- if (!
- (me4000_inl(ai_context->status_reg) &
- ME4000_AI_STATUS_BIT_FSM)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_read():Conversion interrupted\n");
- return -EPIPE;
- }
-
- wait_event_interruptible(ai_context->wait_queue,
- (me4000_values_to_end
- (ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT)));
- if (signal_pending(current)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_read():Wait on values interrupted from signal\n");
- return -EINTR;
- }
- }
-
- /* Only read count values or as much as available */
- c = me4000_values_to_end(ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT);
- PDEBUG("me4000_ai_read():%d values to end\n", c);
- if (count < c)
- c = count;
-
- PDEBUG("me4000_ai_read():Copy %d values to user space\n", c);
- k = 2 * c;
- k -= copy_to_user(buffer,
- ai_context->circ_buf.buf +
- ai_context->circ_buf.tail, k);
- c = k / 2;
- if (!c) {
- printk(KERN_ERR
- "ME4000:me4000_ai_read():Cannot copy new values to user\n");
- return -EFAULT;
- }
-
- ai_context->circ_buf.tail =
- (ai_context->circ_buf.tail + c) & (ME4000_AI_BUFFER_COUNT -
- 1);
- buffer += c;
- count -= c;
- ret += c;
-
- spin_lock_irqsave(&ai_context->int_lock, flags);
- if (me4000_buf_space
- (ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- /* Determine interrupt setup */
- if (ai_context->sample_counter
- && !ai_context->sample_counter_reload) {
- /* Enable Half Full Interrupt and Sample Counter Interrupt */
- tmp |=
- ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_HF_IRQ;
- } else if (ai_context->sample_counter
- && ai_context->sample_counter_reload) {
- if (ai_context->sample_counter <
- ME4000_AI_FIFO_COUNT / 2) {
- /* Enable only Sample Counter Interrupt */
- tmp |= ME4000_AI_CTRL_BIT_SC_IRQ;
- } else {
- /* Enable Half Full Interrupt and Sample Counter Interrupt */
- tmp |=
- ME4000_AI_CTRL_BIT_SC_IRQ |
- ME4000_AI_CTRL_BIT_HF_IRQ;
- }
- } else {
- /* Enable only Half Full Interrupt */
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
- }
-
- me4000_outl(tmp, ai_context->ctrl_reg);
- }
- spin_unlock_irqrestore(&ai_context->int_lock, flags);
- }
-
- /* Check if conversion is still running */
- if (!(me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM)) {
- printk(KERN_ERR
- "ME4000:me4000_ai_read():Conversion not running after complete read\n");
- return -EPIPE;
- }
-
- if (filep->f_flags & O_NONBLOCK)
- return (k == 0) ? -EAGAIN : 2 * ret;
-
- CALL_PDEBUG("me4000_ai_read() is leaved\n");
- return ret * 2;
-}
-
-static unsigned int me4000_ai_poll(struct file *file_p, poll_table *wait)
-{
- struct me4000_ai_context *ai_context;
- unsigned long mask = 0;
-
- CALL_PDEBUG("me4000_ai_poll() is executed\n");
-
- ai_context = file_p->private_data;
-
- /* Register wait queue */
- poll_wait(file_p, &ai_context->wait_queue, wait);
-
- /* Get available values */
- if (me4000_values_to_end(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT))
- mask |= POLLIN | POLLRDNORM;
-
- PDEBUG("me4000_ai_poll():Return mask %lX\n", mask);
-
- return mask;
-}
-
-static int me4000_ai_offset_enable(struct me4000_ai_context *ai_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ai_offset_enable() is executed\n");
-
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_OFFSET;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ai_offset_disable(struct me4000_ai_context *ai_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ai_offset_disable() is executed\n");
-
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_OFFSET;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ai_fullscale_enable(struct me4000_ai_context *ai_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ai_fullscale_enable() is executed\n");
-
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_FULLSCALE;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ai_fullscale_disable(struct me4000_ai_context *ai_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ai_fullscale_disable() is executed\n");
-
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_FULLSCALE;
- me4000_outl(tmp, ai_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ai_fsm_state(int *arg, struct me4000_ai_context *ai_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ai_fsm_state() is executed\n");
-
- tmp =
- (me4000_inl(ai_context->status_reg) & ME4000_AI_STATUS_BIT_FSM) ? 1
- : 0;
-
- if (put_user(tmp, arg)) {
- printk(KERN_ERR "me4000_ai_fsm_state():Cannot copy to user\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int me4000_ai_get_count_buffer(unsigned long *arg,
- struct me4000_ai_context *ai_context)
-{
- unsigned long c;
- int err;
-
- c = me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT);
-
- err = copy_to_user(arg, &c, sizeof(unsigned long));
- if (err) {
- printk(KERN_ERR
- "%s:Can't copy to user space\n", __func__);
- return -EFAULT;
- }
-
- return 0;
-}
-
-/*---------------------------------- EEPROM stuff ---------------------------*/
-
-static int eeprom_write_cmd(struct me4000_ai_context *ai_context, unsigned long cmd,
- int length)
-{
- int i;
- unsigned long value;
-
- CALL_PDEBUG("eeprom_write_cmd() is executed\n");
-
- PDEBUG("eeprom_write_cmd():Write command 0x%08lX with length = %d\n",
- cmd, length);
-
- /* Get the ICR register and clear the related bits */
- value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR);
- value &= ~(PLX_ICR_MASK_EEPROM);
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
-
- /* Raise the chip select */
- value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT;
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- for (i = 0; i < length; i++) {
- if (cmd & ((0x1 << (length - 1)) >> i))
- value |= PLX_ICR_BIT_EEPROM_WRITE;
- else
- value &= ~PLX_ICR_BIT_EEPROM_WRITE;
-
- /* Write to EEPROM */
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Raising edge of the clock */
- value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Falling edge of the clock */
- value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
- }
-
- /* Clear the chip select */
- value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT;
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Wait until hardware is ready for sure */
- mdelay(10);
-
- return 0;
-}
-
-static unsigned short eeprom_read_cmd(struct me4000_ai_context *ai_context,
- unsigned long cmd, int length)
-{
- int i;
- unsigned long value;
- unsigned short id = 0;
-
- CALL_PDEBUG("eeprom_read_cmd() is executed\n");
-
- PDEBUG("eeprom_read_cmd():Read command 0x%08lX with length = %d\n", cmd,
- length);
-
- /* Get the ICR register and clear the related bits */
- value = me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR);
- value &= ~(PLX_ICR_MASK_EEPROM);
-
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
-
- /* Raise the chip select */
- value |= PLX_ICR_BIT_EEPROM_CHIP_SELECT;
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Write the read command to the eeprom */
- for (i = 0; i < length; i++) {
- if (cmd & ((0x1 << (length - 1)) >> i))
- value |= PLX_ICR_BIT_EEPROM_WRITE;
- else
- value &= ~PLX_ICR_BIT_EEPROM_WRITE;
-
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Raising edge of the clock */
- value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- /* Falling edge of the clock */
- value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
- }
-
- /* Read the value from the eeprom */
- for (i = 0; i < 16; i++) {
- /* Raising edge of the clock */
- value |= PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- if (me4000_inl(ai_context->board_info->plx_regbase + PLX_ICR) &
- PLX_ICR_BIT_EEPROM_READ) {
- id |= (0x8000 >> i);
- PDEBUG("eeprom_read_cmd():OR with 0x%04X\n",
- (0x8000 >> i));
- } else {
- PDEBUG("eeprom_read_cmd():Dont't OR\n");
- }
-
- /* Falling edge of the clock */
- value &= ~PLX_ICR_BIT_EEPROM_CLOCK_SET;
- me4000_outl(value,
- ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
- }
-
- /* Clear the chip select */
- value &= ~PLX_ICR_BIT_EEPROM_CHIP_SELECT;
- me4000_outl(value, ai_context->board_info->plx_regbase + PLX_ICR);
- udelay(EEPROM_DELAY);
-
- return id;
-}
-
-static int me4000_eeprom_write(struct me4000_eeprom *arg,
- struct me4000_ai_context *ai_context)
-{
- int err;
- struct me4000_eeprom setup;
- unsigned long cmd;
- unsigned long date_high;
- unsigned long date_low;
-
- CALL_PDEBUG("me4000_eeprom_write() is executed\n");
-
- err = copy_from_user(&setup, arg, sizeof(setup));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_eeprom_write():Cannot copy from user\n");
- return err;
- }
-
- /* Enable writing */
- eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_ENABLE,
- ME4000_EEPROM_CMD_LENGTH_WRITE_ENABLE);
-
- /* Command for date */
- date_high = (setup.date & 0xFFFF0000) >> 16;
- date_low = (setup.date & 0x0000FFFF);
-
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_HIGH <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- date_high);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_DATE_LOW <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- date_low);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for unipolar 10V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- uni_10_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for unipolar 10V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- uni_10_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for unipolar 2,5V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- uni_2_5_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for unipolar 2,5V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- uni_2_5_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for bipolar 10V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- bi_10_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for bipolar 10V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- bi_10_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for bipolar 2,5V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- bi_2_5_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for bipolar 2,5V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- bi_2_5_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for differential 10V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- diff_10_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for differential 10V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE
- << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- diff_10_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for differential 2,5V offset */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET <<
- ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- diff_2_5_offset);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Command for differential 2,5V fullscale */
- cmd =
- ME4000_EEPROM_CMD_WRITE | (ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE
- << ME4000_EEPROM_DATA_LENGTH) | (0xFFFF &
- (unsigned
- long)
- setup.
- diff_2_5_fullscale);
- err = eeprom_write_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_WRITE);
- if (err)
- return err;
-
- /* Disable writing */
- eeprom_write_cmd(ai_context, ME4000_EEPROM_CMD_WRITE_DISABLE,
- ME4000_EEPROM_CMD_LENGTH_WRITE_DISABLE);
-
- return 0;
-}
-
-static int me4000_eeprom_read(struct me4000_eeprom *arg,
- struct me4000_ai_context *ai_context)
-{
- int err;
- unsigned long cmd;
- struct me4000_eeprom setup;
-
- CALL_PDEBUG("me4000_eeprom_read() is executed\n");
-
- /* Command for date */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_HIGH;
- setup.date =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
- setup.date <<= 16;
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_DATE_LOW;
- setup.date |=
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for unipolar 10V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_OFFSET;
- setup.uni_10_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for unipolar 10V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_UNI_FULLSCALE;
- setup.uni_10_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for unipolar 2,5V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_OFFSET;
- setup.uni_2_5_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for unipolar 2,5V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_UNI_FULLSCALE;
- setup.uni_2_5_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for bipolar 10V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_OFFSET;
- setup.bi_10_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for bipolar 10V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_BI_FULLSCALE;
- setup.bi_10_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for bipolar 2,5V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_OFFSET;
- setup.bi_2_5_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for bipolar 2,5V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_BI_FULLSCALE;
- setup.bi_2_5_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for differntial 10V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_OFFSET;
- setup.diff_10_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for differential 10V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_1_DIFF_FULLSCALE;
- setup.diff_10_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for differntial 2,5V offset */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_OFFSET;
- setup.diff_2_5_offset =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- /* Command for differential 2,5V fullscale */
- cmd = ME4000_EEPROM_CMD_READ | ME4000_EEPROM_ADR_GAIN_4_DIFF_FULLSCALE;
- setup.diff_2_5_fullscale =
- eeprom_read_cmd(ai_context, cmd, ME4000_EEPROM_CMD_LENGTH_READ);
-
- err = copy_to_user(arg, &setup, sizeof(setup));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_eeprom_read():Cannot copy to user\n");
- return err;
- }
-
- return 0;
-}
-
-/*------------------------------------ DIO stuff ----------------------------------------------*/
-
-static int me4000_dio_ioctl(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_dio_context *dio_context;
-
- CALL_PDEBUG("me4000_dio_ioctl() is executed\n");
-
- dio_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_DIO_CONFIG:
- return me4000_dio_config((struct me4000_dio_config *)arg,
- dio_context);
- case ME4000_DIO_SET_BYTE:
- return me4000_dio_set_byte((struct me4000_dio_byte *)arg,
- dio_context);
- case ME4000_DIO_GET_BYTE:
- return me4000_dio_get_byte((struct me4000_dio_byte *)arg,
- dio_context);
- case ME4000_DIO_RESET:
- return me4000_dio_reset(dio_context);
- default:
- printk(KERN_ERR
- "ME4000:me4000_dio_ioctl():Invalid service number %d\n",
- service);
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_dio_config(struct me4000_dio_config *arg,
- struct me4000_dio_context *dio_context)
-{
- struct me4000_dio_config cmd;
- u32 tmp;
- int err;
-
- CALL_PDEBUG("me4000_dio_config() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_config));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Check port parameter */
- if (cmd.port >= dio_context->dio_count) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port,
- cmd.mode, cmd.function);
-
- if (cmd.port == ME4000_DIO_PORT_A) {
- if (cmd.mode == ME4000_DIO_PORT_INPUT) {
- /* Check if opto isolated version */
- if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Cannot set to input on opto isolated versions\n");
- return -EIO;
- }
-
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_0 |
- ME4000_DIO_CTRL_BIT_MODE_1);
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_0 |
- ME4000_DIO_CTRL_BIT_MODE_1);
- tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_0 |
- ME4000_DIO_CTRL_BIT_MODE_1 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_0);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_0 |
- ME4000_DIO_CTRL_BIT_MODE_1;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_0 |
- ME4000_DIO_CTRL_BIT_MODE_1 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_0;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Mode %d is not available\n",
- cmd.mode);
- return -EINVAL;
- }
- } else if (cmd.port == ME4000_DIO_PORT_B) {
- if (cmd.mode == ME4000_DIO_PORT_INPUT) {
- /* Only do anything when TTL version is installed */
- if ((me4000_inl(dio_context->dir_reg) & 0x1)) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3);
- me4000_outl(tmp, dio_context->ctrl_reg);
- }
- } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
- /* Check if opto isolated version */
- if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Cannot set to output on opto isolated versions\n");
- return -EIO;
- }
-
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3);
- tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
- /* Check if opto isolated version */
- if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Cannot set to FIFO low output on opto isolated versions\n");
- return -EIO;
- }
-
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_1);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
- /* Check if opto isolated version */
- if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Cannot set to FIFO high output on opto isolated versions\n");
- return -EIO;
- }
-
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_1;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Mode %d is not available\n",
- cmd.mode);
- return -EINVAL;
- }
- } else if (cmd.port == ME4000_DIO_PORT_C) {
- if (cmd.mode == ME4000_DIO_PORT_INPUT) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_4 |
- ME4000_DIO_CTRL_BIT_MODE_5);
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_4 |
- ME4000_DIO_CTRL_BIT_MODE_5);
- tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_4 |
- ME4000_DIO_CTRL_BIT_MODE_5 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_2);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_4 |
- ME4000_DIO_CTRL_BIT_MODE_5;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_4 |
- ME4000_DIO_CTRL_BIT_MODE_5 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_2;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Mode %d is not available\n",
- cmd.mode);
- return -EINVAL;
- }
- } else if (cmd.port == ME4000_DIO_PORT_D) {
- if (cmd.mode == ME4000_DIO_PORT_INPUT) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_6 |
- ME4000_DIO_CTRL_BIT_MODE_7);
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_PORT_OUTPUT) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_6 |
- ME4000_DIO_CTRL_BIT_MODE_7);
- tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_LOW) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_MODE_6 |
- ME4000_DIO_CTRL_BIT_MODE_7 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_3);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_6 |
- ME4000_DIO_CTRL_BIT_MODE_7;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.mode == ME4000_DIO_FIFO_HIGH) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp |=
- ME4000_DIO_CTRL_BIT_MODE_6 |
- ME4000_DIO_CTRL_BIT_MODE_7 |
- ME4000_DIO_CTRL_BIT_FIFO_HIGH_3;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Mode %d is not available\n",
- cmd.mode);
- return -EINVAL;
- }
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- PDEBUG("me4000_dio_config(): port %d, mode %d, function %d\n", cmd.port,
- cmd.mode, cmd.function);
-
- if ((cmd.mode == ME4000_DIO_FIFO_HIGH)
- || (cmd.mode == ME4000_DIO_FIFO_LOW)) {
- tmp = me4000_inl(dio_context->ctrl_reg);
- tmp &=
- ~(ME4000_DIO_CTRL_BIT_FUNCTION_0 |
- ME4000_DIO_CTRL_BIT_FUNCTION_1);
- if (cmd.function == ME4000_DIO_FUNCTION_PATTERN) {
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.function == ME4000_DIO_FUNCTION_DEMUX) {
- tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_0;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else if (cmd.function == ME4000_DIO_FUNCTION_MUX) {
- tmp |= ME4000_DIO_CTRL_BIT_FUNCTION_1;
- me4000_outl(tmp, dio_context->ctrl_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_config():Invalid port function specified\n");
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-static int me4000_dio_set_byte(struct me4000_dio_byte *arg,
- struct me4000_dio_context *dio_context)
-{
- struct me4000_dio_byte cmd;
- int err;
-
- CALL_PDEBUG("me4000_dio_set_byte() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Check port parameter */
- if (cmd.port >= dio_context->dio_count) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- if (cmd.port == ME4000_DIO_PORT_A) {
- if ((me4000_inl(dio_context->ctrl_reg) & 0x3) != 0x1) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
- cmd.port);
- return -EIO;
- }
- me4000_outl(cmd.byte, dio_context->port_0_reg);
- } else if (cmd.port == ME4000_DIO_PORT_B) {
- if ((me4000_inl(dio_context->ctrl_reg) & 0xC) != 0x4) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
- cmd.port);
- return -EIO;
- }
- me4000_outl(cmd.byte, dio_context->port_1_reg);
- } else if (cmd.port == ME4000_DIO_PORT_C) {
- if ((me4000_inl(dio_context->ctrl_reg) & 0x30) != 0x10) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
- cmd.port);
- return -EIO;
- }
- me4000_outl(cmd.byte, dio_context->port_2_reg);
- } else if (cmd.port == ME4000_DIO_PORT_D) {
- if ((me4000_inl(dio_context->ctrl_reg) & 0xC0) != 0x40) {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not in output mode\n",
- cmd.port);
- return -EIO;
- }
- me4000_outl(cmd.byte, dio_context->port_3_reg);
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_set_byte():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_dio_get_byte(struct me4000_dio_byte *arg,
- struct me4000_dio_context *dio_context)
-{
- struct me4000_dio_byte cmd;
- int err;
-
- CALL_PDEBUG("me4000_dio_get_byte() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_dio_byte));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_dio_get_byte():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Check port parameter */
- if (cmd.port >= dio_context->dio_count) {
- printk(KERN_ERR
- "ME4000:me4000_dio_get_byte():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- if (cmd.port == ME4000_DIO_PORT_A) {
- cmd.byte = me4000_inl(dio_context->port_0_reg) & 0xFF;
- } else if (cmd.port == ME4000_DIO_PORT_B) {
- cmd.byte = me4000_inl(dio_context->port_1_reg) & 0xFF;
- } else if (cmd.port == ME4000_DIO_PORT_C) {
- cmd.byte = me4000_inl(dio_context->port_2_reg) & 0xFF;
- } else if (cmd.port == ME4000_DIO_PORT_D) {
- cmd.byte = me4000_inl(dio_context->port_3_reg) & 0xFF;
- } else {
- printk(KERN_ERR
- "ME4000:me4000_dio_get_byte():Port %d is not available\n",
- cmd.port);
- return -EINVAL;
- }
-
- /* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(struct me4000_dio_byte));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_dio_get_byte():Can't copy to user space\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int me4000_dio_reset(struct me4000_dio_context *dio_context)
-{
- CALL_PDEBUG("me4000_dio_reset() is executed\n");
-
- /* Clear the control register */
- me4000_outl(0, dio_context->ctrl_reg);
-
- /* Check for opto isolated version */
- if (!(me4000_inl(dio_context->dir_reg) & 0x1)) {
- me4000_outl(0x1, dio_context->ctrl_reg);
- me4000_outl(0x0, dio_context->port_0_reg);
- }
-
- return 0;
-}
-
-/*------------------------------------ COUNTER STUFF ------------------------------------*/
-
-static int me4000_cnt_ioctl(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_cnt_context *cnt_context;
-
- CALL_PDEBUG("me4000_cnt_ioctl() is executed\n");
-
- cnt_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_dio_ioctl():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR "me4000_dio_ioctl():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_CNT_READ:
- return me4000_cnt_read((struct me4000_cnt *)arg, cnt_context);
- case ME4000_CNT_WRITE:
- return me4000_cnt_write((struct me4000_cnt *)arg, cnt_context);
- case ME4000_CNT_CONFIG:
- return me4000_cnt_config((struct me4000_cnt_config *)arg,
- cnt_context);
- case ME4000_CNT_RESET:
- return me4000_cnt_reset(cnt_context);
- default:
- printk(KERN_ERR
- "ME4000:me4000_dio_ioctl():Invalid service number %d\n",
- service);
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_cnt_config(struct me4000_cnt_config *arg,
- struct me4000_cnt_context *cnt_context)
-{
- struct me4000_cnt_config cmd;
- u8 counter;
- u8 mode;
- int err;
-
- CALL_PDEBUG("me4000_cnt_config() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt_config));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_cnt_config():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Check counter parameter */
- switch (cmd.counter) {
- case ME4000_CNT_COUNTER_0:
- counter = ME4000_CNT_CTRL_BIT_COUNTER_0;
- break;
- case ME4000_CNT_COUNTER_1:
- counter = ME4000_CNT_CTRL_BIT_COUNTER_1;
- break;
- case ME4000_CNT_COUNTER_2:
- counter = ME4000_CNT_CTRL_BIT_COUNTER_2;
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_cnt_config():Counter %d is not available\n",
- cmd.counter);
- return -EINVAL;
- }
-
- /* Check mode parameter */
- switch (cmd.mode) {
- case ME4000_CNT_MODE_0:
- mode = ME4000_CNT_CTRL_BIT_MODE_0;
- break;
- case ME4000_CNT_MODE_1:
- mode = ME4000_CNT_CTRL_BIT_MODE_1;
- break;
- case ME4000_CNT_MODE_2:
- mode = ME4000_CNT_CTRL_BIT_MODE_2;
- break;
- case ME4000_CNT_MODE_3:
- mode = ME4000_CNT_CTRL_BIT_MODE_3;
- break;
- case ME4000_CNT_MODE_4:
- mode = ME4000_CNT_CTRL_BIT_MODE_4;
- break;
- case ME4000_CNT_MODE_5:
- mode = ME4000_CNT_CTRL_BIT_MODE_5;
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_cnt_config():Mode %d is not available\n",
- cmd.mode);
- return -EINVAL;
- }
-
- /* Write the control word */
- me4000_outb((counter | mode | 0x30), cnt_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_cnt_read(struct me4000_cnt *arg,
- struct me4000_cnt_context *cnt_context)
-{
- struct me4000_cnt cmd;
- u8 tmp;
- int err;
-
- CALL_PDEBUG("me4000_cnt_read() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_cnt_read():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Read counter */
- switch (cmd.counter) {
- case ME4000_CNT_COUNTER_0:
- tmp = me4000_inb(cnt_context->counter_0_reg);
- cmd.value = tmp;
- tmp = me4000_inb(cnt_context->counter_0_reg);
- cmd.value |= ((u16) tmp) << 8;
- break;
- case ME4000_CNT_COUNTER_1:
- tmp = me4000_inb(cnt_context->counter_1_reg);
- cmd.value = tmp;
- tmp = me4000_inb(cnt_context->counter_1_reg);
- cmd.value |= ((u16) tmp) << 8;
- break;
- case ME4000_CNT_COUNTER_2:
- tmp = me4000_inb(cnt_context->counter_2_reg);
- cmd.value = tmp;
- tmp = me4000_inb(cnt_context->counter_2_reg);
- cmd.value |= ((u16) tmp) << 8;
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_cnt_read():Counter %d is not available\n",
- cmd.counter);
- return -EINVAL;
- }
-
- /* Copy result back to user */
- err = copy_to_user(arg, &cmd, sizeof(struct me4000_cnt));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_cnt_read():Can't copy to user space\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int me4000_cnt_write(struct me4000_cnt *arg,
- struct me4000_cnt_context *cnt_context)
-{
- struct me4000_cnt cmd;
- u8 tmp;
- int err;
-
- CALL_PDEBUG("me4000_cnt_write() is executed\n");
-
- /* Copy data from user */
- err = copy_from_user(&cmd, arg, sizeof(struct me4000_cnt));
- if (err) {
- printk(KERN_ERR
- "ME4000:me4000_cnt_write():Can't copy from user space\n");
- return -EFAULT;
- }
-
- /* Write counter */
- switch (cmd.counter) {
- case ME4000_CNT_COUNTER_0:
- tmp = cmd.value & 0xFF;
- me4000_outb(tmp, cnt_context->counter_0_reg);
- tmp = (cmd.value >> 8) & 0xFF;
- me4000_outb(tmp, cnt_context->counter_0_reg);
- break;
- case ME4000_CNT_COUNTER_1:
- tmp = cmd.value & 0xFF;
- me4000_outb(tmp, cnt_context->counter_1_reg);
- tmp = (cmd.value >> 8) & 0xFF;
- me4000_outb(tmp, cnt_context->counter_1_reg);
- break;
- case ME4000_CNT_COUNTER_2:
- tmp = cmd.value & 0xFF;
- me4000_outb(tmp, cnt_context->counter_2_reg);
- tmp = (cmd.value >> 8) & 0xFF;
- me4000_outb(tmp, cnt_context->counter_2_reg);
- break;
- default:
- printk(KERN_ERR
- "ME4000:me4000_cnt_write():Counter %d is not available\n",
- cmd.counter);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int me4000_cnt_reset(struct me4000_cnt_context *cnt_context)
-{
- CALL_PDEBUG("me4000_cnt_reset() is executed\n");
-
- /* Set the mode and value for counter 0 */
- me4000_outb(0x30, cnt_context->ctrl_reg);
- me4000_outb(0x00, cnt_context->counter_0_reg);
- me4000_outb(0x00, cnt_context->counter_0_reg);
-
- /* Set the mode and value for counter 1 */
- me4000_outb(0x70, cnt_context->ctrl_reg);
- me4000_outb(0x00, cnt_context->counter_1_reg);
- me4000_outb(0x00, cnt_context->counter_1_reg);
-
- /* Set the mode and value for counter 2 */
- me4000_outb(0xB0, cnt_context->ctrl_reg);
- me4000_outb(0x00, cnt_context->counter_2_reg);
- me4000_outb(0x00, cnt_context->counter_2_reg);
-
- return 0;
-}
-
-/*------------------------------------ External Interrupt stuff ------------------------------------*/
-
-static int me4000_ext_int_ioctl(struct inode *inode_p, struct file *file_p,
- unsigned int service, unsigned long arg)
-{
- struct me4000_ext_int_context *ext_int_context;
-
- CALL_PDEBUG("me4000_ext_int_ioctl() is executed\n");
-
- ext_int_context = file_p->private_data;
-
- if (_IOC_TYPE(service) != ME4000_MAGIC) {
- printk(KERN_ERR "me4000_ext_int_ioctl():Wrong magic number\n");
- return -ENOTTY;
- }
- if (_IOC_NR(service) > ME4000_IOCTL_MAXNR) {
- printk(KERN_ERR
- "me4000_ext_int_ioctl():Service number to high\n");
- return -ENOTTY;
- }
-
- switch (service) {
- case ME4000_EXT_INT_ENABLE:
- return me4000_ext_int_enable(ext_int_context);
- case ME4000_EXT_INT_DISABLE:
- return me4000_ext_int_disable(ext_int_context);
- case ME4000_EXT_INT_COUNT:
- return me4000_ext_int_count((unsigned long *)arg,
- ext_int_context);
- default:
- printk(KERN_ERR
- "ME4000:me4000_ext_int_ioctl():Invalid service number %d\n",
- service);
- return -ENOTTY;
- }
- return 0;
-}
-
-static int me4000_ext_int_enable(struct me4000_ext_int_context *ext_int_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ext_int_enable() is executed\n");
-
- tmp = me4000_inl(ext_int_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_EX_IRQ;
- me4000_outl(tmp, ext_int_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ext_int_disable(struct me4000_ext_int_context *ext_int_context)
-{
- unsigned long tmp;
-
- CALL_PDEBUG("me4000_ext_int_disable() is executed\n");
-
- tmp = me4000_inl(ext_int_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ;
- me4000_outl(tmp, ext_int_context->ctrl_reg);
-
- return 0;
-}
-
-static int me4000_ext_int_count(unsigned long *arg,
- struct me4000_ext_int_context *ext_int_context)
-{
-
- CALL_PDEBUG("me4000_ext_int_count() is executed\n");
-
- put_user(ext_int_context->int_count, arg);
- return 0;
-}
-
-/*------------------------------------ General stuff ------------------------------------*/
-
-static int me4000_get_user_info(struct me4000_user_info *arg,
- struct me4000_info *board_info)
-{
- struct me4000_user_info user_info;
-
- CALL_PDEBUG("me4000_get_user_info() is executed\n");
-
- user_info.board_count = board_info->board_count;
- user_info.plx_regbase = board_info->plx_regbase;
- user_info.plx_regbase_size = board_info->plx_regbase_size;
- user_info.me4000_regbase = board_info->me4000_regbase;
- user_info.me4000_regbase_size = board_info->me4000_regbase_size;
- user_info.serial_no = board_info->serial_no;
- user_info.hw_revision = board_info->hw_revision;
- user_info.vendor_id = board_info->vendor_id;
- user_info.device_id = board_info->device_id;
- user_info.pci_bus_no = board_info->pci_bus_no;
- user_info.pci_dev_no = board_info->pci_dev_no;
- user_info.pci_func_no = board_info->pci_func_no;
- user_info.irq = board_info->irq;
- user_info.irq_count = board_info->irq_count;
- user_info.driver_version = ME4000_DRIVER_VERSION;
- user_info.ao_count = board_info->board_p->ao.count;
- user_info.ao_fifo_count = board_info->board_p->ao.fifo_count;
-
- user_info.ai_count = board_info->board_p->ai.count;
- user_info.ai_sh_count = board_info->board_p->ai.sh_count;
- user_info.ai_ex_trig_analog = board_info->board_p->ai.ex_trig_analog;
-
- user_info.dio_count = board_info->board_p->dio.count;
-
- user_info.cnt_count = board_info->board_p->cnt.count;
-
- if (copy_to_user(arg, &user_info, sizeof(struct me4000_user_info)))
- return -EFAULT;
-
- return 0;
-}
-
-/*------------------------------------ ISR STUFF ------------------------------------*/
-
-static int me4000_ext_int_fasync(int fd, struct file *file_ptr, int mode)
-{
- int result = 0;
- struct me4000_ext_int_context *ext_int_context;
-
- CALL_PDEBUG("me4000_ext_int_fasync() is executed\n");
-
- ext_int_context = file_ptr->private_data;
-
- result =
- fasync_helper(fd, file_ptr, mode, &ext_int_context->fasync_ptr);
-
- CALL_PDEBUG("me4000_ext_int_fasync() is leaved\n");
- return result;
-}
-
-static irqreturn_t me4000_ao_isr(int irq, void *dev_id)
-{
- u32 tmp;
- u32 value;
- struct me4000_ao_context *ao_context;
- int i;
- int c = 0;
- int c1 = 0;
-
- ISR_PDEBUG("me4000_ao_isr() is executed\n");
-
- ao_context = dev_id;
-
- /* Check if irq number is right */
- if (irq != ao_context->irq) {
- ISR_PDEBUG("me4000_ao_isr():incorrect interrupt num: %d\n",
- irq);
- return IRQ_NONE;
- }
-
- /* Check if this DAC rised an interrupt */
- if (!
- ((0x1 << (ao_context->index + 3)) &
- me4000_inl(ao_context->irq_status_reg))) {
- ISR_PDEBUG("me4000_ao_isr():Not this DAC\n");
- return IRQ_NONE;
- }
-
- /* Read status register to find out what happened */
- tmp = me4000_inl(ao_context->status_reg);
-
- if (!(tmp & ME4000_AO_STATUS_BIT_EF) && (tmp & ME4000_AO_STATUS_BIT_HF)
- && (tmp & ME4000_AO_STATUS_BIT_HF)) {
- c = ME4000_AO_FIFO_COUNT;
- ISR_PDEBUG("me4000_ao_isr():Fifo empty\n");
- } else if ((tmp & ME4000_AO_STATUS_BIT_EF)
- && (tmp & ME4000_AO_STATUS_BIT_HF)
- && (tmp & ME4000_AO_STATUS_BIT_HF)) {
- c = ME4000_AO_FIFO_COUNT / 2;
- ISR_PDEBUG("me4000_ao_isr():Fifo under half full\n");
- } else {
- c = 0;
- ISR_PDEBUG("me4000_ao_isr():Fifo full\n");
- }
-
- ISR_PDEBUG("me4000_ao_isr():Try to write 0x%04X values\n", c);
-
- while (1) {
- c1 = me4000_values_to_end(ao_context->circ_buf,
- ME4000_AO_BUFFER_COUNT);
- ISR_PDEBUG("me4000_ao_isr():Values to end = %d\n", c1);
- if (c1 > c)
- c1 = c;
-
- if (c1 <= 0) {
- ISR_PDEBUG
- ("me4000_ao_isr():Work done or buffer empty\n");
- break;
- }
- if (((ao_context->fifo_reg & 0xFF) == ME4000_AO_01_FIFO_REG) ||
- ((ao_context->fifo_reg & 0xFF) == ME4000_AO_03_FIFO_REG)) {
- for (i = 0; i < c1; i++) {
- value =
- ((u32)
- (*
- (ao_context->circ_buf.buf +
- ao_context->circ_buf.tail + i))) << 16;
- outl(value, ao_context->fifo_reg);
- }
- } else
- outsw(ao_context->fifo_reg,
- ao_context->circ_buf.buf +
- ao_context->circ_buf.tail, c1);
-
-
- ao_context->circ_buf.tail =
- (ao_context->circ_buf.tail + c1) & (ME4000_AO_BUFFER_COUNT -
- 1);
- ISR_PDEBUG("me4000_ao_isr():%d values wrote to port 0x%04X\n",
- c1, ao_context->fifo_reg);
- c -= c1;
- }
-
- /* If there are no values left in the buffer, disable interrupts */
- spin_lock(&ao_context->int_lock);
- if (!me4000_buf_count(ao_context->circ_buf, ME4000_AO_BUFFER_COUNT)) {
- ISR_PDEBUG
- ("me4000_ao_isr():Disable Interrupt because no values left in buffer\n");
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ;
- me4000_outl(tmp, ao_context->ctrl_reg);
- }
- spin_unlock(&ao_context->int_lock);
-
- /* Reset the interrupt */
- spin_lock(&ao_context->int_lock);
- tmp = me4000_inl(ao_context->ctrl_reg);
- tmp |= ME4000_AO_CTRL_BIT_RESET_IRQ;
- me4000_outl(tmp, ao_context->ctrl_reg);
- tmp &= ~ME4000_AO_CTRL_BIT_RESET_IRQ;
- me4000_outl(tmp, ao_context->ctrl_reg);
-
- /* If state machine is stopped, flow was interrupted */
- if (!(me4000_inl(ao_context->status_reg) & ME4000_AO_STATUS_BIT_FSM)) {
- printk(KERN_ERR "ME4000:me4000_ao_isr():Broken pipe\n");
- /* Set flag in order to inform write routine */
- ao_context->pipe_flag = 1;
- /* Disable interrupt */
- tmp &= ~ME4000_AO_CTRL_BIT_ENABLE_IRQ;
- }
- me4000_outl(tmp, ao_context->ctrl_reg);
- spin_unlock(&ao_context->int_lock);
-
- /* Wake up waiting process */
- wake_up_interruptible(&(ao_context->wait_queue));
-
- /* Count the interrupt */
- ao_context->board_info->irq_count++;
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t me4000_ai_isr(int irq, void *dev_id)
-{
- u32 tmp;
- struct me4000_ai_context *ai_context;
- int i;
- int c = 0;
- int c1 = 0;
-#ifdef ME4000_ISR_DEBUG
- unsigned long before;
- unsigned long after;
-#endif
-
- ISR_PDEBUG("me4000_ai_isr() is executed\n");
-
-#ifdef ME4000_ISR_DEBUG
- rdtscl(before);
-#endif
-
- ai_context = dev_id;
-
- /* Check if irq number is right */
- if (irq != ai_context->irq) {
- ISR_PDEBUG("me4000_ai_isr():incorrect interrupt num: %d\n",
- irq);
- return IRQ_NONE;
- }
-
- if (me4000_inl(ai_context->irq_status_reg) &
- ME4000_IRQ_STATUS_BIT_AI_HF) {
- ISR_PDEBUG
- ("me4000_ai_isr():Fifo half full interrupt occured\n");
-
- /* Read status register to find out what happened */
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
- !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG("me4000_ai_isr():Fifo full\n");
- c = ME4000_AI_FIFO_COUNT;
-
- /* FIFO overflow, so stop conversion and disable all interrupts */
- spin_lock(&ai_context->int_lock);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- tmp &=
- ~(ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, ai_context->ctrl_reg);
- spin_unlock(&ai_context->int_lock);
- } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
- !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG("me4000_ai_isr():Fifo half full\n");
- c = ME4000_AI_FIFO_COUNT / 2;
- } else {
- c = 0;
- ISR_PDEBUG
- ("me4000_ai_isr():Can't determine state of fifo\n");
- }
-
- ISR_PDEBUG("me4000_ai_isr():Try to read %d values\n", c);
-
- while (1) {
- c1 = me4000_space_to_end(ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT);
- ISR_PDEBUG("me4000_ai_isr():Space to end = %d\n", c1);
- if (c1 > c)
- c1 = c;
-
- if (c1 <= 0) {
- ISR_PDEBUG
- ("me4000_ai_isr():Work done or buffer full\n");
- break;
- }
-
- insw(ai_context->data_reg,
- ai_context->circ_buf.buf +
- ai_context->circ_buf.head, c1);
- ai_context->circ_buf.head =
- (ai_context->circ_buf.head +
- c1) & (ME4000_AI_BUFFER_COUNT - 1);
- c -= c1;
- }
-
- /* Work is done, so reset the interrupt */
- ISR_PDEBUG
- ("me4000_ai_isr():reset interrupt fifo half full interrupt\n");
- spin_lock(&ai_context->int_lock);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- me4000_outl(tmp, ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock(&ai_context->int_lock);
- }
-
- if (me4000_inl(ai_context->irq_status_reg) & ME4000_IRQ_STATUS_BIT_SC) {
- ISR_PDEBUG
- ("me4000_ai_isr():Sample counter interrupt occured\n");
-
- if (!ai_context->sample_counter_reload) {
- ISR_PDEBUG
- ("me4000_ai_isr():Single data block available\n");
-
- /* Poll data until fifo empty */
- for (i = 0;
- (i < ME4000_AI_FIFO_COUNT / 2)
- && (inl(ai_context->ctrl_reg) &
- ME4000_AI_STATUS_BIT_EF_DATA); i++) {
- if (me4000_space_to_end
- (ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT)) {
- *(ai_context->circ_buf.buf +
- ai_context->circ_buf.head) =
- inw(ai_context->data_reg);
- ai_context->circ_buf.head =
- (ai_context->circ_buf.head +
- 1) & (ME4000_AI_BUFFER_COUNT - 1);
- } else
- break;
- }
- ISR_PDEBUG("me4000_ai_isr():%d values read\n", i);
- } else {
- if (ai_context->sample_counter <=
- ME4000_AI_FIFO_COUNT / 2) {
- ISR_PDEBUG
- ("me4000_ai_isr():Interrupt from adjustable half full threshold\n");
-
- /* Read status register to find out what happened */
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
- !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG
- ("me4000_ai_isr():Fifo full\n");
- c = ME4000_AI_FIFO_COUNT;
-
- /* FIFO overflow, so stop conversion */
- spin_lock(&ai_context->int_lock);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |=
- ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- outl(tmp, ai_context->ctrl_reg);
- spin_unlock(&ai_context->int_lock);
- } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
- && !(tmp &
- ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp &
- ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG
- ("me4000_ai_isr():Fifo half full\n");
- c = ME4000_AI_FIFO_COUNT / 2;
- } else {
- c = ai_context->sample_counter;
- ISR_PDEBUG
- ("me4000_ai_isr():Sample count values\n");
- }
-
- ISR_PDEBUG
- ("me4000_ai_isr():Try to read %d values\n",
- c);
-
- while (1) {
- c1 = me4000_space_to_end(ai_context->
- circ_buf,
- ME4000_AI_BUFFER_COUNT);
- ISR_PDEBUG
- ("me4000_ai_isr():Space to end = %d\n",
- c1);
- if (c1 > c)
- c1 = c;
-
- if (c1 <= 0) {
- ISR_PDEBUG
- ("me4000_ai_isr():Work done or buffer full\n");
- break;
- }
-
- insw(ai_context->data_reg,
- ai_context->circ_buf.buf +
- ai_context->circ_buf.head, c1);
- ai_context->circ_buf.head =
- (ai_context->circ_buf.head +
- c1) & (ME4000_AI_BUFFER_COUNT - 1);
- c -= c1;
- }
- } else {
- ISR_PDEBUG
- ("me4000_ai_isr():Multiple data block available\n");
-
- /* Read status register to find out what happened */
- tmp = me4000_inl(ai_context->ctrl_reg);
-
- if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
- !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG
- ("me4000_ai_isr():Fifo full\n");
- c = ME4000_AI_FIFO_COUNT;
-
- /* FIFO overflow, so stop conversion */
- spin_lock(&ai_context->int_lock);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |=
- ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- outl(tmp, ai_context->ctrl_reg);
- spin_unlock(&ai_context->int_lock);
-
- while (1) {
- c1 = me4000_space_to_end
- (ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT);
- ISR_PDEBUG
- ("me4000_ai_isr():Space to end = %d\n",
- c1);
- if (c1 > c)
- c1 = c;
-
- if (c1 <= 0) {
- ISR_PDEBUG
- ("me4000_ai_isr():Work done or buffer full\n");
- break;
- }
-
- insw(ai_context->data_reg,
- ai_context->circ_buf.buf +
- ai_context->circ_buf.head,
- c1);
- ai_context->circ_buf.head =
- (ai_context->circ_buf.head +
- c1) &
- (ME4000_AI_BUFFER_COUNT -
- 1);
- c -= c1;
- }
- } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
- && !(tmp &
- ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp &
- ME4000_AI_STATUS_BIT_EF_DATA)) {
- ISR_PDEBUG
- ("me4000_ai_isr():Fifo half full\n");
- c = ME4000_AI_FIFO_COUNT / 2;
-
- while (1) {
- c1 = me4000_space_to_end
- (ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT);
- ISR_PDEBUG
- ("me4000_ai_isr():Space to end = %d\n",
- c1);
- if (c1 > c)
- c1 = c;
-
- if (c1 <= 0) {
- ISR_PDEBUG
- ("me4000_ai_isr():Work done or buffer full\n");
- break;
- }
-
- insw(ai_context->data_reg,
- ai_context->circ_buf.buf +
- ai_context->circ_buf.head,
- c1);
- ai_context->circ_buf.head =
- (ai_context->circ_buf.head +
- c1) &
- (ME4000_AI_BUFFER_COUNT -
- 1);
- c -= c1;
- }
- } else {
- /* Poll data until fifo empty */
- for (i = 0;
- (i < ME4000_AI_FIFO_COUNT / 2)
- && (inl(ai_context->ctrl_reg) &
- ME4000_AI_STATUS_BIT_EF_DATA);
- i++) {
- if (me4000_space_to_end
- (ai_context->circ_buf,
- ME4000_AI_BUFFER_COUNT)) {
- *(ai_context->circ_buf.
- buf +
- ai_context->circ_buf.
- head) =
- inw(ai_context->data_reg);
- ai_context->circ_buf.
- head =
- (ai_context->
- circ_buf.head +
- 1) &
- (ME4000_AI_BUFFER_COUNT
- - 1);
- } else
- break;
- }
- ISR_PDEBUG
- ("me4000_ai_isr():%d values read\n",
- i);
- }
- }
- }
-
- /* Work is done, so reset the interrupt */
- ISR_PDEBUG
- ("me4000_ai_isr():reset interrupt from sample counter\n");
- spin_lock(&ai_context->int_lock);
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
- me4000_outl(tmp, ai_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
- me4000_outl(tmp, ai_context->ctrl_reg);
- spin_unlock(&ai_context->int_lock);
- }
-
- /* Values are now available, so wake up waiting process */
- if (me4000_buf_count(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
- ISR_PDEBUG("me4000_ai_isr():Wake up waiting process\n");
- wake_up_interruptible(&(ai_context->wait_queue));
- }
-
- /* If there is no space left in the buffer, disable interrupts */
- spin_lock(&ai_context->int_lock);
- if (!me4000_buf_space(ai_context->circ_buf, ME4000_AI_BUFFER_COUNT)) {
- ISR_PDEBUG
- ("me4000_ai_isr():Disable Interrupt because no space left in buffer\n");
- tmp = me4000_inl(ai_context->ctrl_reg);
- tmp &=
- ~(ME4000_AI_CTRL_BIT_SC_IRQ | ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_LE_IRQ);
- me4000_outl(tmp, ai_context->ctrl_reg);
- }
- spin_unlock(&ai_context->int_lock);
-
-#ifdef ME4000_ISR_DEBUG
- rdtscl(after);
- printk(KERN_ERR "ME4000:me4000_ai_isr():Time lapse = %lu\n",
- after - before);
-#endif
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t me4000_ext_int_isr(int irq, void *dev_id)
-{
- struct me4000_ext_int_context *ext_int_context;
- unsigned long tmp;
-
- ISR_PDEBUG("me4000_ext_int_isr() is executed\n");
-
- ext_int_context = dev_id;
-
- /* Check if irq number is right */
- if (irq != ext_int_context->irq) {
- ISR_PDEBUG("me4000_ext_int_isr():incorrect interrupt num: %d\n",
- irq);
- return IRQ_NONE;
- }
-
- if (me4000_inl(ext_int_context->irq_status_reg) &
- ME4000_IRQ_STATUS_BIT_EX) {
- ISR_PDEBUG("me4000_ext_int_isr():External interrupt occured\n");
- tmp = me4000_inl(ext_int_context->ctrl_reg);
- tmp |= ME4000_AI_CTRL_BIT_EX_IRQ_RESET;
- me4000_outl(tmp, ext_int_context->ctrl_reg);
- tmp &= ~ME4000_AI_CTRL_BIT_EX_IRQ_RESET;
- me4000_outl(tmp, ext_int_context->ctrl_reg);
-
- ext_int_context->int_count++;
-
- if (ext_int_context->fasync_ptr) {
- ISR_PDEBUG
- ("me2600_ext_int_isr():Send signal to process\n");
- kill_fasync(&ext_int_context->fasync_ptr, SIGIO,
- POLL_IN);
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static void __exit me4000_module_exit(void)
-{
- struct me4000_info *board_info;
-
- CALL_PDEBUG("cleanup_module() is executed\n");
-
- unregister_chrdev(me4000_ext_int_major_driver_no, ME4000_EXT_INT_NAME);
-
- unregister_chrdev(me4000_cnt_major_driver_no, ME4000_CNT_NAME);
-
- unregister_chrdev(me4000_dio_major_driver_no, ME4000_DIO_NAME);
-
- unregister_chrdev(me4000_ai_major_driver_no, ME4000_AI_NAME);
-
- unregister_chrdev(me4000_ao_major_driver_no, ME4000_AO_NAME);
-
- remove_proc_entry("me4000", NULL);
-
- pci_unregister_driver(&me4000_driver);
-
- /* Reset the boards */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- me4000_reset_board(board_info);
- }
-
- clear_board_info_list();
-}
-
-module_exit(me4000_module_exit);
-
-static int me4000_read_procmem(char *buf, char **start, off_t offset, int count,
- int *eof, void *data)
-{
- int len = 0;
- int limit = count - 1000;
- struct me4000_info *board_info;
-
- len += sprintf(buf + len, "\nME4000 DRIVER VERSION %X.%X.%X\n\n",
- (ME4000_DRIVER_VERSION & 0xFF0000) >> 16,
- (ME4000_DRIVER_VERSION & 0xFF00) >> 8,
- (ME4000_DRIVER_VERSION & 0xFF));
-
- /* Search for the board context */
- list_for_each_entry(board_info, &me4000_board_info_list, list) {
- len +=
- sprintf(buf + len, "Board number %d:\n",
- board_info->board_count);
- len += sprintf(buf + len, "---------------\n");
- len +=
- sprintf(buf + len, "PLX base register = 0x%lX\n",
- board_info->plx_regbase);
- len +=
- sprintf(buf + len, "PLX base register size = 0x%X\n",
- (unsigned int)board_info->plx_regbase_size);
- len +=
- sprintf(buf + len, "ME4000 base register = 0x%X\n",
- (unsigned int)board_info->me4000_regbase);
- len +=
- sprintf(buf + len, "ME4000 base register size = 0x%X\n",
- (unsigned int)board_info->me4000_regbase_size);
- len +=
- sprintf(buf + len, "Serial number = 0x%X\n",
- board_info->serial_no);
- len +=
- sprintf(buf + len, "Hardware revision = 0x%X\n",
- board_info->hw_revision);
- len +=
- sprintf(buf + len, "Vendor id = 0x%X\n",
- board_info->vendor_id);
- len +=
- sprintf(buf + len, "Device id = 0x%X\n",
- board_info->device_id);
- len +=
- sprintf(buf + len, "PCI bus number = %d\n",
- board_info->pci_bus_no);
- len +=
- sprintf(buf + len, "PCI device number = %d\n",
- board_info->pci_dev_no);
- len +=
- sprintf(buf + len, "PCI function number = %d\n",
- board_info->pci_func_no);
- len += sprintf(buf + len, "IRQ = %u\n", board_info->irq);
- len +=
- sprintf(buf + len,
- "Count of interrupts since module was loaded = %d\n",
- board_info->irq_count);
-
- len +=
- sprintf(buf + len, "Count of analog outputs = %d\n",
- board_info->board_p->ao.count);
- len +=
- sprintf(buf + len, "Count of analog output fifos = %d\n",
- board_info->board_p->ao.fifo_count);
-
- len +=
- sprintf(buf + len, "Count of analog inputs = %d\n",
- board_info->board_p->ai.count);
- len +=
- sprintf(buf + len,
- "Count of sample and hold devices for analog input = %d\n",
- board_info->board_p->ai.sh_count);
- len +=
- sprintf(buf + len,
- "Analog external trigger available for analog input = %d\n",
- board_info->board_p->ai.ex_trig_analog);
-
- len +=
- sprintf(buf + len, "Count of digital ports = %d\n",
- board_info->board_p->dio.count);
-
- len +=
- sprintf(buf + len, "Count of counter devices = %d\n",
- board_info->board_p->cnt.count);
- len +=
- sprintf(buf + len, "AI control register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AI_CTRL_REG));
-
- len += sprintf(buf + len, "AO 0 control register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_00_CTRL_REG));
- len +=
- sprintf(buf + len, "AO 0 status register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_00_STATUS_REG));
- len +=
- sprintf(buf + len, "AO 1 control register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_01_CTRL_REG));
- len +=
- sprintf(buf + len, "AO 1 status register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_01_STATUS_REG));
- len +=
- sprintf(buf + len, "AO 2 control register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_02_CTRL_REG));
- len +=
- sprintf(buf + len, "AO 2 status register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_02_STATUS_REG));
- len +=
- sprintf(buf + len, "AO 3 control register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_03_CTRL_REG));
- len +=
- sprintf(buf + len, "AO 3 status register = 0x%08X\n",
- inl(board_info->me4000_regbase +
- ME4000_AO_03_STATUS_REG));
- if (len >= limit)
- break;
- }
-
- *eof = 1;
- return len;
-}