The comedi drivers should be used instead, no need to have this driver in the tree duplicating that one. Cc: Wolfgang Beiter <w.beiter@aon.at> Cc: Guenter Gebhardt <g.gebhardt@meilhaus.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/me4000/Kconfig | 10 - drivers/staging/me4000/Makefile | 1 - drivers/staging/me4000/README | 13 - drivers/staging/me4000/me4000.c | 6109 ------------------ drivers/staging/me4000/me4000.h | 966 --- drivers/staging/me4000/me4000_firmware.h |10033 ------------------------------ drivers/staging/me4000/me4610_firmware.h | 5409 ---------------- 9 files changed, 0 insertions(+), 22544 deletions(-) delete mode 100644 drivers/staging/me4000/Kconfig delete mode 100644 drivers/staging/me4000/Makefile delete mode 100644 drivers/staging/me4000/README delete mode 100644 drivers/staging/me4000/me4000.c delete mode 100644 drivers/staging/me4000/me4000.h delete mode 100644 drivers/staging/me4000/me4000_firmware.h delete mode 100644 drivers/staging/me4000/me4610_firmware.h diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ee073ce..d76f6b3 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -47,8 +47,6 @@ source "drivers/staging/slicoss/Kconfig" source "drivers/staging/sxg/Kconfig" -source "drivers/staging/me4000/Kconfig" - source "drivers/staging/meilhaus/Kconfig" source "drivers/staging/go7007/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index c5c8cae..01bf228 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_STAGING) += staging.o obj-$(CONFIG_ET131X) += et131x/ obj-$(CONFIG_SLICOSS) += slicoss/ obj-$(CONFIG_SXG) += sxg/ -obj-$(CONFIG_ME4000) += me4000/ obj-$(CONFIG_MEILHAUS) += meilhaus/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ diff --git a/drivers/staging/me4000/Kconfig b/drivers/staging/me4000/Kconfig deleted file mode 100644 index 5e6c9de..0000000 --- a/drivers/staging/me4000/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config ME4000 - tristate "Meilhaus ME-4000 support" - default n - depends on PCI - help - This driver supports the Meilhaus ME-4000 family of boards - that do data collection and multipurpose I/O. - - To compile this driver as a module, choose M here: the module - will be called me4000. diff --git a/drivers/staging/me4000/Makefile b/drivers/staging/me4000/Makefile deleted file mode 100644 index 74487cd..0000000 --- a/drivers/staging/me4000/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ME4000) += me4000.o diff --git a/drivers/staging/me4000/README b/drivers/staging/me4000/README deleted file mode 100644 index bbb8386..0000000 --- a/drivers/staging/me4000/README +++ /dev/null @@ -1,13 +0,0 @@ - -TODO: - - checkpatch.pl cleanups - - sparse cleanups - - possible /proc interaction cleanups - - more info needed for Kconfig entry - - real device id? - - module parameter cleanup - -Please send patches to Greg Kroah-Hartman <gregkh@suse.de> -and Cc: Wolfgang Beiter <w.beiter@aon.at> and -Guenter Gebhardt <g.gebhardt@meilhaus.de> - diff --git a/drivers/staging/me4000/me4000.c b/drivers/staging/me4000/me4000.c deleted file mode 100644 index 01017b7..0000000 --- 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(
