From foo@baz Wed Sep 2 21:29:37 PDT 2009 Date: Wed, 02 Sep 2009 21:29:37 -0700 To: Greg KH From: Greg Kroah-Hartman Subject: Staging: meilhaus: remove the drivers The comedi drivers should be used instead, no need to have these in here as well. Cc: David Kiliani Cc: Meilhaus Support Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 drivers/staging/Makefile | 1 drivers/staging/meilhaus/Kconfig | 128 drivers/staging/meilhaus/Makefile | 43 drivers/staging/meilhaus/TODO | 10 drivers/staging/meilhaus/me0600_device.c | 213 drivers/staging/meilhaus/me0600_device.h | 97 drivers/staging/meilhaus/me0600_dio.c | 415 - drivers/staging/meilhaus/me0600_dio.h | 68 drivers/staging/meilhaus/me0600_dio_reg.h | 41 drivers/staging/meilhaus/me0600_ext_irq.c | 469 -- drivers/staging/meilhaus/me0600_ext_irq.h | 58 drivers/staging/meilhaus/me0600_ext_irq_reg.h | 18 drivers/staging/meilhaus/me0600_optoi.c | 243 - drivers/staging/meilhaus/me0600_optoi.h | 58 drivers/staging/meilhaus/me0600_optoi_reg.h | 35 drivers/staging/meilhaus/me0600_relay.c | 359 - drivers/staging/meilhaus/me0600_relay.h | 63 drivers/staging/meilhaus/me0600_relay_reg.h | 36 drivers/staging/meilhaus/me0600_ttli.c | 238 - drivers/staging/meilhaus/me0600_ttli.h | 58 drivers/staging/meilhaus/me0600_ttli_reg.h | 35 drivers/staging/meilhaus/me0900_device.c | 178 drivers/staging/meilhaus/me0900_device.h | 92 drivers/staging/meilhaus/me0900_di.c | 245 - drivers/staging/meilhaus/me0900_di.h | 65 drivers/staging/meilhaus/me0900_do.c | 314 - drivers/staging/meilhaus/me0900_do.h | 68 drivers/staging/meilhaus/me0900_reg.h | 40 drivers/staging/meilhaus/me1000_device.c | 206 drivers/staging/meilhaus/me1000_device.h | 59 drivers/staging/meilhaus/me1000_dio.c | 438 - drivers/staging/meilhaus/me1000_dio.h | 71 drivers/staging/meilhaus/me1000_dio_reg.h | 50 drivers/staging/meilhaus/me1400_device.c | 253 - drivers/staging/meilhaus/me1400_device.h | 108 drivers/staging/meilhaus/me1400_ext_irq.c | 507 -- drivers/staging/meilhaus/me1400_ext_irq.h | 62 drivers/staging/meilhaus/me1400_ext_irq_reg.h | 56 drivers/staging/meilhaus/me1600_ao.c | 1017 ---- drivers/staging/meilhaus/me1600_ao.h | 128 drivers/staging/meilhaus/me1600_ao_reg.h | 66 drivers/staging/meilhaus/me1600_device.c | 259 - drivers/staging/meilhaus/me1600_device.h | 101 drivers/staging/meilhaus/me4600_ai.c | 3405 -------------- drivers/staging/meilhaus/me4600_ai.h | 175 drivers/staging/meilhaus/me4600_ai_reg.h | 107 drivers/staging/meilhaus/me4600_ao.c | 5974 -------------------------- drivers/staging/meilhaus/me4600_ao.h | 259 - drivers/staging/meilhaus/me4600_ao_reg.h | 113 drivers/staging/meilhaus/me4600_device.c | 371 - drivers/staging/meilhaus/me4600_device.h | 151 drivers/staging/meilhaus/me4600_di.c | 256 - drivers/staging/meilhaus/me4600_di.h | 64 drivers/staging/meilhaus/me4600_dio.c | 510 -- drivers/staging/meilhaus/me4600_dio.h | 69 drivers/staging/meilhaus/me4600_dio_reg.h | 63 drivers/staging/meilhaus/me4600_do.c | 433 - drivers/staging/meilhaus/me4600_do.h | 65 drivers/staging/meilhaus/me4600_ext_irq.c | 457 - drivers/staging/meilhaus/me4600_ext_irq.h | 78 drivers/staging/meilhaus/me4600_ext_irq_reg.h | 41 drivers/staging/meilhaus/me4600_reg.h | 46 drivers/staging/meilhaus/me6000_ao.c | 3709 ---------------- drivers/staging/meilhaus/me6000_ao.h | 195 drivers/staging/meilhaus/me6000_ao_reg.h | 177 drivers/staging/meilhaus/me6000_device.c | 209 drivers/staging/meilhaus/me6000_device.h | 149 drivers/staging/meilhaus/me6000_dio.c | 415 - drivers/staging/meilhaus/me6000_dio.h | 68 drivers/staging/meilhaus/me6000_dio_reg.h | 43 drivers/staging/meilhaus/me6000_reg.h | 35 drivers/staging/meilhaus/me8100_device.c | 185 drivers/staging/meilhaus/me8100_device.h | 97 drivers/staging/meilhaus/me8100_di.c | 684 -- drivers/staging/meilhaus/me8100_di.h | 89 drivers/staging/meilhaus/me8100_di_reg.h | 47 drivers/staging/meilhaus/me8100_do.c | 391 - drivers/staging/meilhaus/me8100_do.h | 70 drivers/staging/meilhaus/me8100_do_reg.h | 36 drivers/staging/meilhaus/me8100_reg.h | 41 drivers/staging/meilhaus/me8200_device.c | 192 drivers/staging/meilhaus/me8200_device.h | 97 drivers/staging/meilhaus/me8200_di.c | 832 --- drivers/staging/meilhaus/me8200_di.h | 92 drivers/staging/meilhaus/me8200_di_reg.h | 75 drivers/staging/meilhaus/me8200_dio.c | 418 - drivers/staging/meilhaus/me8200_dio.h | 68 drivers/staging/meilhaus/me8200_dio_reg.h | 43 drivers/staging/meilhaus/me8200_do.c | 591 -- drivers/staging/meilhaus/me8200_do.h | 75 drivers/staging/meilhaus/me8200_do_reg.h | 40 drivers/staging/meilhaus/me8200_reg.h | 46 drivers/staging/meilhaus/me8254.c | 1176 ----- drivers/staging/meilhaus/me8254.h | 80 drivers/staging/meilhaus/me8254_reg.h | 172 drivers/staging/meilhaus/me8255.c | 462 -- drivers/staging/meilhaus/me8255.h | 59 drivers/staging/meilhaus/me8255_reg.h | 50 drivers/staging/meilhaus/mecirc_buf.h | 131 drivers/staging/meilhaus/mecommon.h | 26 drivers/staging/meilhaus/medebug.h | 125 drivers/staging/meilhaus/medefines.h | 449 - drivers/staging/meilhaus/medevice.c | 1740 ------- drivers/staging/meilhaus/medevice.h | 304 - drivers/staging/meilhaus/medlist.c | 127 drivers/staging/meilhaus/medlist.h | 91 drivers/staging/meilhaus/medlock.c | 195 drivers/staging/meilhaus/medlock.h | 76 drivers/staging/meilhaus/medriver.h | 350 - drivers/staging/meilhaus/medummy.c | 1264 ----- drivers/staging/meilhaus/medummy.h | 40 drivers/staging/meilhaus/meerror.h | 100 drivers/staging/meilhaus/mefirmware.c | 137 drivers/staging/meilhaus/mefirmware.h | 57 drivers/staging/meilhaus/meids.h | 31 drivers/staging/meilhaus/meinternal.h | 363 - drivers/staging/meilhaus/meioctl.h | 515 -- drivers/staging/meilhaus/memain.c | 2084 --------- drivers/staging/meilhaus/memain.h | 266 - drivers/staging/meilhaus/meplx_reg.h | 53 drivers/staging/meilhaus/meslist.c | 173 drivers/staging/meilhaus/meslist.h | 108 drivers/staging/meilhaus/meslock.c | 136 drivers/staging/meilhaus/meslock.h | 73 drivers/staging/meilhaus/mesubdevice.c | 317 - drivers/staging/meilhaus/mesubdevice.h | 197 drivers/staging/meilhaus/metempl_device.c | 135 drivers/staging/meilhaus/metempl_device.h | 92 drivers/staging/meilhaus/metempl_sub.c | 149 drivers/staging/meilhaus/metempl_sub.h | 64 drivers/staging/meilhaus/metempl_sub_reg.h | 35 drivers/staging/meilhaus/metypes.h | 95 133 files changed, 41014 deletions(-) --- 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/meilhaus/Kconfig" - source "drivers/staging/go7007/Kconfig" source "drivers/staging/usbip/Kconfig" --- 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_MEILHAUS) += meilhaus/ obj-$(CONFIG_VIDEO_GO7007) += go7007/ obj-$(CONFIG_USB_IP_COMMON) += usbip/ obj-$(CONFIG_W35UND) += winbond/ --- a/drivers/staging/meilhaus/Kconfig +++ /dev/null @@ -1,128 +0,0 @@ -# -# Meilhaus configuration -# - -menuconfig MEILHAUS - tristate "Meilhaus support" - depends on m - ---help--- - If you have a Meilhaus card, say Y (or M) here. - - You need both this driver, and the driver for the particular - data collection card. - - To compile this driver as a module, choose M here. The module will - be called memain. - -if MEILHAUS - -config ME0600 - tristate "Meilhaus ME-600 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-600 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 me0600. - -config ME0900 - tristate "Meilhaus ME-900 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-900 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 me0900. - -config ME1000 - tristate "Meilhaus ME-1000 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-1000 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 me1000. - -config ME1400 - tristate "Meilhaus ME-1400 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-1400 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 me1400. - -config ME1600 - tristate "Meilhaus ME-1600 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-1600 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 me1600. - -config ME4600 - tristate "Meilhaus ME-4600 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-4600 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 me4600. - -config ME6000 - tristate "Meilhaus ME-6000 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-6000 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 me6000. - -config ME8100 - tristate "Meilhaus ME-8100 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-8100 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 me8100. - -config ME8200 - tristate "Meilhaus ME-8200 support" - default n - depends on PCI && m - help - This driver supports the Meilhaus ME-8200 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 me8200. - -config MEDUMMY - tristate "Meilhaus dummy driver" - default n - depends on PCI && m - help - This provides a dummy driver for the Meilhaus driver package - - To compile this driver as a module, choose M here: the module - will be called medummy. - -endif # MEILHAUS --- a/drivers/staging/meilhaus/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Makefile for Meilhaus linux driver system -# - -obj-$(CONFIG_MEILHAUS) += memain.o -obj-$(CONFIG_ME1600) += me1600.o -obj-$(CONFIG_ME1000) += me1000.o -obj-$(CONFIG_ME1400) += me1400.o -obj-$(CONFIG_ME4600) += me4600.o -obj-$(CONFIG_ME6000) += me6000.o -obj-$(CONFIG_ME0600) += me0600.o -obj-$(CONFIG_ME8100) += me8100.o -obj-$(CONFIG_ME8200) += me8200.o -obj-$(CONFIG_ME0900) += me0900.o -obj-$(CONFIG_MEDUMMY) += medummy.o - - -me1600-objs := medevice.o medlist.o medlock.o me1600_device.o -me1600-objs += mesubdevice.o meslist.o meslock.o me1600_ao.o - -me1000-objs := medevice.o medlist.o medlock.o me1000_device.o -me1000-objs += mesubdevice.o meslist.o meslock.o me1000_dio.o - -me1400-objs := medevice.o medlist.o medlock.o me1400_device.o -me1400-objs += mesubdevice.o meslist.o meslock.o me8254.o me8255.o me1400_ext_irq.o - -me4600-objs := medevice.o medlist.o medlock.o mefirmware.o me4600_device.o -me4600-objs += mesubdevice.o meslist.o meslock.o me4600_do.o me4600_di.o me4600_dio.o me8254.o me4600_ai.o me4600_ao.o me4600_ext_irq.o - -me6000-objs := medevice.o medlist.o medlock.o mefirmware.o me6000_device.o -me6000-objs += mesubdevice.o meslist.o meslock.o me6000_dio.o me6000_ao.o - -me0600-objs := medevice.o medlist.o medlock.o me0600_device.o -me0600-objs += mesubdevice.o meslist.o meslock.o me0600_relay.o me0600_ttli.o me0600_optoi.o me0600_dio.o me0600_ext_irq.o - -me8100-objs := medevice.o medlist.o medlock.o me8100_device.o -me8100-objs += mesubdevice.o meslist.o meslock.o me8100_di.o me8100_do.o me8254.o - -me8200-objs := medevice.o medlist.o medlock.o me8200_device.o -me8200-objs += mesubdevice.o meslist.o meslock.o me8200_di.o me8200_do.o me8200_dio.o - -me0900-objs := medevice.o medlist.o medlock.o me0900_device.o -me0900-objs += mesubdevice.o meslist.o meslock.o me0900_do.o me0900_di.o --- a/drivers/staging/meilhaus/me0600_device.c +++ /dev/null @@ -1,213 +0,0 @@ -/** - * @file me0600_device.c - * - * @brief ME-630 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "me0600_device.h" -#include "mesubdevice.h" -#include "me0600_relay.h" -#include "me0600_ttli.h" -#include "me0600_optoi.h" -#include "me0600_dio.h" -#include "me0600_ext_irq.h" - -me_device_t *me0600_pci_constructor(struct pci_dev *pci_device) -{ - me0600_device_t *me0600_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me0600_device = kmalloc(sizeof(me0600_device_t), GFP_KERNEL); - - if (!me0600_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me0600_device, 0, sizeof(me0600_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me0600_device, pci_device); - - if (err) { - kfree(me0600_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - me0600_versions_get_device_index(me0600_device->base.info.pci. - device_id); - - // Initialize spin lock . - spin_lock_init(&me0600_device->dio_ctrl_reg_lock); - spin_lock_init(&me0600_device->intcsr_lock); - - // Create subdevice instances. - - for (i = 0; i < me0600_versions[version_idx].optoi_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0600_optoi_constructor(me0600_device-> - base.info.pci. - reg_bases[2]); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0600_device); - kfree(me0600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0600_device->base.slist, - subdevice); - } - - for (i = 0; i < me0600_versions[version_idx].relay_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0600_relay_constructor(me0600_device-> - base.info.pci. - reg_bases[2]); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0600_device); - kfree(me0600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0600_device->base.slist, - subdevice); - } - - for (i = 0; i < me0600_versions[version_idx].ttli_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0600_ttli_constructor(me0600_device-> - base.info.pci. - reg_bases[2]); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0600_device); - kfree(me0600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0600_device->base.slist, - subdevice); - } - - for (i = 0; i < me0600_versions[version_idx].dio_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0600_dio_constructor(me0600_device-> - base.info.pci. - reg_bases[2], i, - &me0600_device-> - dio_ctrl_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0600_device); - kfree(me0600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0600_device->base.slist, - subdevice); - } - - for (i = 0; i < me0600_versions[version_idx].ext_irq_subdevices; i++) { - subdevice = - (me_subdevice_t *) - me0600_ext_irq_constructor(me0600_device->base.info.pci. - reg_bases[1], - me0600_device->base.info.pci. - reg_bases[2], - &me0600_device->intcsr_lock, i, - me0600_device->base.irq); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0600_device); - kfree(me0600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0600_device->base.slist, - subdevice); - } - - return (me_device_t *) me0600_device; -} -EXPORT_SYMBOL(me0600_pci_constructor); - -// Init and exit of module. - -static int __init me0600_init(void) -{ - PDEBUG("executed.\n"); - return 0; -} - -static void __exit me0600_exit(void) -{ - PDEBUG("executed.\n"); -} - -module_init(me0600_init); - -module_exit(me0600_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for ME-6xx Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-6xx Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me0600_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file me0600_device.h - * - * @brief ME-630 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_DEVICE_H -#define _ME0600_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-630 device capabilities. - */ -typedef struct me0600_version { - uint16_t device_id; - unsigned int relay_subdevices; - unsigned int ttli_subdevices; - unsigned int optoi_subdevices; - unsigned int dio_subdevices; - unsigned int ext_irq_subdevices; -} me0600_version_t; - -/** - * @brief Device capabilities. - */ -static me0600_version_t me0600_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME0630, 1, 1, 1, 2, 2}, - {0}, -}; - -#define ME0600_DEVICE_VERSIONS (ARRAY_SIZE(me0600_versions) - 1) /**< Returns the number of entries in #me0600_versions. */ - -/** - * @brief Returns the index of the device entry in #me0600_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me0600_versions. - */ -static inline unsigned int me0600_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME0600_DEVICE_VERSIONS; i++) - if (me0600_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-630 device class structure. - */ -typedef struct me0600_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t dio_ctrl_reg_lock; - spinlock_t intcsr_lock; -} me0600_device_t; - -/** - * @brief The ME-630 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-630 device instance. \n - * NULL on error. - */ -me_device_t *me0600_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_dio.c +++ /dev/null @@ -1,415 +0,0 @@ -/** - * @file me0600_dio.c - * - * @brief ME-630 digital input/output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me0600_dio_reg.h" -#include "me0600_dio.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0600_dio_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me0600_dio_subdevice_t *instance; - uint8_t mode; - - PDEBUG("executed.\n"); - - instance = (me0600_dio_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - mode &= ~(0x3 << (instance->dio_idx * 2)); - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - - outb(0x00, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0x00); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me0600_dio_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me0600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - int size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - - PDEBUG("executed.\n"); - - instance = (me0600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - mode &= - ~((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - mode &= - ~((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - mode |= - ME0600_DIO_CONFIG_BIT_OUT_0 << (instance-> - dio_idx * - 2); - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_dio_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - - PDEBUG("executed.\n"); - - instance = (me0600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - - if ((mode == - (ME0600_DIO_CONFIG_BIT_OUT_0 << - (instance->dio_idx * 2))) || !mode) { - *value = - inb(instance-> - port_reg) & (0x0001 << channel); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - - if ((mode == - (ME0600_DIO_CONFIG_BIT_OUT_0 << - (instance->dio_idx * 2))) || !mode) { - *value = inb(instance->port_reg) & 0x00FF; - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - - break; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_dio_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me0600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - uint8_t byte; - - PDEBUG("executed.\n"); - - instance = (me0600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - - if (mode == - (ME0600_DIO_CONFIG_BIT_OUT_0 << - (instance->dio_idx * 2))) { - byte = inb(instance->port_reg); - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outb(byte, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME0600_DIO_CONFIG_BIT_OUT_0) << - (instance->dio_idx * 2)); - - if (mode == - (ME0600_DIO_CONFIG_BIT_OUT_0 << - (instance->dio_idx * 2))) { - outb(value, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - - break; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_dio_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me0600_dio_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0600_dio_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_DIR_BYTE; - return ME_ERRNO_SUCCESS; -} - -me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t *ctrl_reg_lock) -{ - me0600_dio_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0600_dio_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0600_dio_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - /* Initialize spin locks. */ - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save digital i/o index */ - subdevice->dio_idx = dio_idx; - - /* Save the subdevice index */ - subdevice->ctrl_reg = reg_base + ME0600_DIO_CONFIG_REG; - subdevice->port_reg = reg_base + ME0600_DIO_PORT_REG + dio_idx; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0600_dio_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0600_dio_io_single_config; - subdevice->base.me_subdevice_io_single_read = me0600_dio_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me0600_dio_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me0600_dio_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0600_dio_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0600_dio_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0600_dio.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file me0600_dio.h - * - * @brief ME-630 digital input/output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_DIO_H_ -#define _ME0600_DIO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0600_dio_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - unsigned int dio_idx; /**< The index of the digital i/o on the device. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me0600_dio_subdevice_t; - -/** - * @brief The constructor to generate a ME-630 digital input/ouput subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param dio_idx The index of the digital i/o port on the device. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0600_dio_subdevice_t *me0600_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_dio_reg.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file me0600_dio_reg.h - * - * @brief ME-630 digital input/output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_DIO_REG_H_ -#define _ME0600_DIO_REG_H_ - -#ifdef __KERNEL__ - -#define ME0600_DIO_CONFIG_REG 0x0007 -#define ME0600_DIO_PORT_0_REG 0x0008 -#define ME0600_DIO_PORT_1_REG 0x0009 -#define ME0600_DIO_PORT_REG ME0600_DIO_PORT_0_REG - -#define ME0600_DIO_CONFIG_BIT_OUT_0 0x0001 -#define ME0600_DIO_CONFIG_BIT_OUT_1 0x0004 - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_ext_irq.c +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @file me0600_ext_irq.c - * - * @brief ME-630 external interrupt subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "meids.h" -#include "medebug.h" - -#include "meplx_reg.h" -#include "me0600_ext_irq_reg.h" -#include "me0600_ext_irq.h" - -/* - * Functions - */ - -static int me0600_ext_irq_io_irq_start(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me0600_ext_irq_subdevice_t *instance; - uint32_t tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me0600_ext_irq_subdevice_t *) subdevice; - - if (flags & ~ME_IO_IRQ_START_DIO_BIT) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (instance->lintno > 1) { - PERROR("Wrong idx=%d.\n", instance->lintno); - return ME_ERRNO_INVALID_SUBDEVICE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { - PERROR("Invalid irq source specified.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - if (irq_edge != ME_IRQ_EDGE_RISING) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->intcsr_lock); - tmp = inl(instance->intcsr); - switch (instance->lintno) { - case 0: - tmp |= - PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL | - PLX_INTCSR_PCI_INT_EN; - break; - case 1: - tmp |= - PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL | - PLX_INTCSR_PCI_INT_EN; - break; - } - outl(tmp, instance->intcsr); - PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); - spin_unlock(instance->intcsr_lock); - instance->rised = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me0600_ext_irq_io_irq_wait(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me0600_ext_irq_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me0600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - (instance->rised != - 0), t); - - if (t == 0) { - PERROR("Wait on interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - instance->rised = 0; - *irq_count = instance->n; - *value = 1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_ext_irq_io_irq_stop(struct me_subdevice *subdevice, - struct file *filep, - int channel, int flags) -{ - me0600_ext_irq_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me0600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (instance->lintno > 1) { - PERROR("Wrong idx=%d.\n", instance->lintno); - return ME_ERRNO_INVALID_SUBDEVICE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->intcsr_lock); - tmp = inl(instance->intcsr); - switch (instance->lintno) { - case 0: - tmp &= ~PLX_INTCSR_LOCAL_INT1_EN; - break; - case 1: - tmp &= ~PLX_INTCSR_LOCAL_INT2_EN; - break; - } - outl(tmp, instance->intcsr); - PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); - spin_unlock(instance->intcsr_lock); - instance->rised = -1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me0600_ext_irq_subdevice_t *instance; - uint32_t tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me0600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->intcsr_lock); - tmp = inl(instance->intcsr); - switch (instance->lintno) { - case 0: - tmp |= PLX_INTCSR_LOCAL_INT1_POL | PLX_INTCSR_PCI_INT_EN; - tmp &= ~PLX_INTCSR_LOCAL_INT1_EN; - break; - case 1: - tmp |= PLX_INTCSR_LOCAL_INT2_POL | PLX_INTCSR_PCI_INT_EN; - tmp &= ~PLX_INTCSR_LOCAL_INT2_EN; - break; - } - outl(tmp, instance->intcsr); - PDEBUG_REG("intcsr outl(plx:0x%X)=0x%x\n", instance->intcsr, tmp); - spin_unlock(instance->intcsr_lock); - - instance->rised = -1; - instance->n = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me0600_ext_irq_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 1; - return ME_ERRNO_SUCCESS; -} - -static int me0600_ext_irq_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_EXT_IRQ; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0600_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_EXT_IRQ_EDGE_RISING; - return ME_ERRNO_SUCCESS; -} - -static void me0600_ext_irq_destructor(struct me_subdevice *subdevice) -{ - me0600_ext_irq_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me0600_ext_irq_subdevice_t *) subdevice; - - free_irq(instance->irq, (void *)instance); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static irqreturn_t me0600_isr(int irq, void *dev_id) -{ - me0600_ext_irq_subdevice_t *instance; - uint32_t status; - uint32_t mask = PLX_INTCSR_PCI_INT_EN; - irqreturn_t ret = IRQ_HANDLED; - - instance = (me0600_ext_irq_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - if (instance->lintno > 1) { - PERROR_CRITICAL - ("%s():Wrong subdevice index=%d plx:irq_status_reg=0x%04X.\n", - __func__, instance->lintno, inl(instance->intcsr)); - return IRQ_NONE; - } - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->intcsr_lock); - status = inl(instance->intcsr); - switch (instance->lintno) { - case 0: - mask |= PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_LOCAL_INT1_EN; - break; - case 1: - mask |= PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_LOCAL_INT2_EN; - break; - } - - if ((status & mask) == mask) { - instance->rised = 1; - instance->n++; - inb(instance->reset_reg); - PDEBUG("Interrupt detected.\n"); - } else { - PINFO - ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n", - jiffies, __func__, status); - ret = IRQ_NONE; - } - spin_unlock(instance->intcsr_lock); - spin_unlock(&instance->subdevice_lock); - - wake_up_interruptible_all(&instance->wait_queue); - - return ret; -} - -me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base, - uint32_t me0600_reg_base, - spinlock_t *intcsr_lock, - unsigned ext_irq_idx, - int irq) -{ - me0600_ext_irq_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0600_ext_irq_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for 630_ext_irq instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0600_ext_irq_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->intcsr_lock = intcsr_lock; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - subdevice->lintno = ext_irq_idx; - - /* Request interrupt line */ - subdevice->irq = irq; - - err = request_irq(subdevice->irq, me0600_isr, - IRQF_DISABLED | IRQF_SHARED, - ME0600_NAME, (void *)subdevice); - - if (err) { - PERROR("Cannot get interrupt line.\n"); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - /* Initialize registers */ - subdevice->intcsr = plx_reg_base + PLX_INTCSR; - subdevice->reset_reg = - me0600_reg_base + ME0600_INT_0_RESET_REG + ext_irq_idx; - - /* Initialize the subdevice methods */ - subdevice->base.me_subdevice_io_irq_start = me0600_ext_irq_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me0600_ext_irq_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me0600_ext_irq_io_irq_stop; - subdevice->base.me_subdevice_io_reset_subdevice = - me0600_ext_irq_io_reset_subdevice; - subdevice->base.me_subdevice_query_number_channels = - me0600_ext_irq_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0600_ext_irq_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0600_ext_irq_query_subdevice_caps; - subdevice->base.me_subdevice_destructor = me0600_ext_irq_destructor; - - subdevice->rised = 0; - subdevice->n = 0; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0600_ext_irq.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file me0600_ext_irq.h - * - * @brief ME-630 external interrupt implementation. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME0600_EXT_IRQ_H_ -#define _ME0600_EXT_IRQ_H_ - -#include - -#include "mesubdevice.h" -#include "meslock.h" - -#ifdef __KERNEL__ - -/** - * @brief The ME-630 external interrupt subdevice class. - */ -typedef struct me0600_ext_irq_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *intcsr_lock; /**< Spin lock to protect #intcsr. */ - - wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */ - - int irq; /**< The irq number assigned by PCI BIOS. */ - int rised; /**< If true an interrupt has occured. */ - unsigned int n; /**< The number of interrupt since the driver was loaded. */ - unsigned int lintno; /**< The number of the local PCI interrupt. */ - - uint32_t intcsr; /**< The PLX interrupt control and status register. */ - uint32_t reset_reg; /**< The control register. */ -} me0600_ext_irq_subdevice_t; - -/** - * @brief The constructor to generate a ME-630 external interrupt instance. - * - * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS. - * @param me0600_reg_base The register base address of the ME-630 device as returned by the PCI BIOS. - * @param irq The irq assigned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0600_ext_irq_subdevice_t *me0600_ext_irq_constructor(uint32_t plx_reg_base, - uint32_t me0600_reg_base, - spinlock_t * intcsr_lock, - unsigned int ext_irq_idx, - int irq); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_ext_irq_reg.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @file me0600_ext_irq_reg.h - * - * @brief ME-630 external interrupt register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME0600_EXT_IRQ_REG_H_ -#define _ME0600_EXT_IRQ_REG_H_ - -#ifdef __KERNEL__ - -#define ME0600_INT_0_RESET_REG 0x0005 -#define ME0600_INT_1_RESET_REG 0x0006 - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_optoi.c +++ /dev/null @@ -1,243 +0,0 @@ -/** - * @file me0600_optoi.c - * - * @brief ME-630 Optoisolated input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me0600_optoi_reg.h" -#include "me0600_optoi.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0600_optoi_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - PDEBUG("executed.\n"); - return ME_ERRNO_SUCCESS; -} - -static int me0600_optoi_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, - int trig_edge, int flags) -{ - me0600_optoi_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_optoi_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) { - PERROR("Invalid port direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - - break; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_optoi_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0600_optoi_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_optoi_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_optoi_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me0600_optoi_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0600_optoi_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base) -{ - me0600_optoi_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0600_optoi_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0600_optoi_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - /* Initialize spin locks. */ - spin_lock_init(&subdevice->subdevice_lock); - - /* Save the subdevice index */ - subdevice->port_reg = reg_base + ME0600_OPTO_INPUT_REG; - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0600_optoi_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0600_optoi_io_single_config; - subdevice->base.me_subdevice_io_single_read = - me0600_optoi_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me0600_optoi_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0600_optoi_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0600_optoi_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0600_optoi.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file me0600_optoi.h - * - * @brief ME-630 Optoisolated input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_OPTOI_H_ -#define _ME0600_OPTOI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0600_optoi_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - uint32_t port_reg; /**< Register holding the port status. */ -} me0600_optoi_subdevice_t; - -/** - * @brief The constructor to generate a ME-630 Optoisolated input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0600_optoi_subdevice_t *me0600_optoi_constructor(uint32_t reg_base); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_optoi_reg.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file me0600_optoi_reg.h - * - * @brief ME-630 Optoisolated input subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_OPTOI_REG_H_ -#define _ME0600_OPTOI_REG_H_ - -#ifdef __KERNEL__ - -#define ME0600_OPTO_INPUT_REG 0x0004 - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_relay.c +++ /dev/null @@ -1,359 +0,0 @@ -/** - * @file me0600_relay.c - * - * @brief ME-630 relay subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me0600_relay_reg.h" -#include "me0600_relay.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0600_relay_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me0600_relay_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me0600_relay_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - outb(0x0, instance->port_0_reg); - PDEBUG_REG("port_0_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_0_reg - instance->reg_base, 0); - outb(0x0, instance->port_1_reg); - PDEBUG_REG("port_1_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_1_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me0600_relay_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, - int trig_edge, int flags) -{ - me0600_relay_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_relay_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_WORD: - if (channel == 0) { - if (single_config != ME_SINGLE_CONFIG_DIO_OUTPUT) { - PERROR("Invalid word direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - - break; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_relay_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0600_relay_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_relay_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_0_reg) & (0x1 << channel); - } else if ((channel >= 8) && (channel < 16)) { - *value = - inb(instance->port_1_reg) & (0x1 << (channel - 8)); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_0_reg); - } else if (channel == 1) { - *value = inb(instance->port_1_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_WORD: - if (channel == 0) { - *value = (uint32_t) inb(instance->port_1_reg) << 8; - *value |= inb(instance->port_0_reg); - } else { - PERROR("Invalid word number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_relay_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me0600_relay_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t state; - - PDEBUG("executed.\n"); - - instance = (me0600_relay_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - state = inb(instance->port_0_reg); - state = - value ? (state | (0x1 << channel)) : (state & - ~(0x1 << - channel)); - outb(state, instance->port_0_reg); - } else if ((channel >= 8) && (channel < 16)) { - state = inb(instance->port_1_reg); - state = - value ? (state | (0x1 << (channel - 8))) : (state & - ~(0x1 << - (channel - - - 8))); - outb(state, instance->port_1_reg); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - outb(value, instance->port_0_reg); - } else if (channel == 1) { - outb(value, instance->port_1_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_WORD: - if (channel == 0) { - outb(value, instance->port_0_reg); - outb(value >> 8, instance->port_1_reg); - } else { - PERROR("Invalid word number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - break; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_relay_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 16; - return ME_ERRNO_SUCCESS; -} - -static int me0600_relay_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0600_relay_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base) -{ - me0600_relay_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0600_relay_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0600_relay_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - /* Save the subdevice index */ - subdevice->port_0_reg = reg_base + ME0600_RELAIS_0_REG; - subdevice->port_1_reg = reg_base + ME0600_RELAIS_1_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0600_relay_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0600_relay_io_single_config; - subdevice->base.me_subdevice_io_single_read = - me0600_relay_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me0600_relay_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me0600_relay_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0600_relay_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0600_relay_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0600_relay.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file me0600_relay.h - * - * @brief ME-630 relay subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_RELAY_H_ -#define _ME0600_RELAY_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0600_relay_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - unsigned long port_0_reg; /**< Register holding the port status. */ - unsigned long port_1_reg; /**< Register holding the port status. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me0600_relay_subdevice_t; - -/** - * @brief The constructor to generate a ME-630 relay subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0600_relay_subdevice_t *me0600_relay_constructor(uint32_t reg_base); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_relay_reg.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file me0600_relay_reg.h - * - * @brief ME-630 relay subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_RELAY_REG_H_ -#define _ME0600_RELAY_REG_H_ - -#ifdef __KERNEL__ - -#define ME0600_RELAIS_0_REG 0x0001 -#define ME0600_RELAIS_1_REG 0x0002 - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_ttli.c +++ /dev/null @@ -1,238 +0,0 @@ -/** - * @file me0600_ttli.c - * - * @brief ME-630 TTL input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me0600_ttli_reg.h" -#include "me0600_ttli.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0600_ttli_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - PDEBUG("executed.\n"); - return ME_ERRNO_SUCCESS; -} - -static int me0600_ttli_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me0600_ttli_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_ttli_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config != ME_SINGLE_CONFIG_DIO_INPUT) { - PERROR("Invalid port direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - - break; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_ttli_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0600_ttli_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0600_ttli_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0600_ttli_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me0600_ttli_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0600_ttli_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base) -{ - me0600_ttli_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0600_ttli_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0600_ttli_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - /* Save the subdevice index */ - subdevice->port_reg = reg_base + ME0600_TTL_INPUT_REG; - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0600_ttli_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0600_ttli_io_single_config; - subdevice->base.me_subdevice_io_single_read = - me0600_ttli_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me0600_ttli_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0600_ttli_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0600_ttli_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0600_ttli.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file me0600_ttli.h - * - * @brief ME-630 TTL input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_TTLI_H_ -#define _ME0600_TTLI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0600_ttli_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - uint32_t port_reg; /**< Register holding the port status. */ -} me0600_ttli_subdevice_t; - -/** - * @brief The constructor to generate a ME-630 TTL input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0600_ttli_subdevice_t *me0600_ttli_constructor(uint32_t reg_base); - -#endif -#endif --- a/drivers/staging/meilhaus/me0600_ttli_reg.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file me0600_ttli_reg.h - * - * @brief ME-630 TTL input subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0600_TTLI_REG_H_ -#define _ME0600_TTLI_REG_H_ - -#ifdef __KERNEL__ - -#define ME0600_TTL_INPUT_REG 0x0003 - -#endif -#endif --- a/drivers/staging/meilhaus/me0900_device.c +++ /dev/null @@ -1,178 +0,0 @@ -/** - * @file me0900_device.c - * - * @brief ME-9x device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) -*/ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "me0900_device.h" -#include "me0900_reg.h" -#include "mesubdevice.h" -#include "me0900_do.h" -#include "me0900_di.h" - -me_device_t *me0900_pci_constructor(struct pci_dev *pci_device) -{ - me0900_device_t *me0900_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - int port_shift; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me0900_device = kmalloc(sizeof(me0900_device_t), GFP_KERNEL); - - if (!me0900_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me0900_device, 0, sizeof(me0900_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me0900_device, pci_device); - - if (err) { - kfree(me0900_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - me0900_versions_get_device_index(me0900_device->base.info.pci. - device_id); - - /* Initialize 8255 chip to desired mode */ - if (me0900_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME0940) { - outb(0x9B, - me0900_device->base.info.pci.reg_bases[2] + - ME0900_CTRL_REG); - } else if (me0900_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME0950) { - outb(0x89, - me0900_device->base.info.pci.reg_bases[2] + - ME0900_CTRL_REG); - outb(0x00, - me0900_device->base.info.pci.reg_bases[2] + - ME0900_WRITE_ENABLE_REG); - } else if (me0900_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME0960) { - outb(0x8B, - me0900_device->base.info.pci.reg_bases[2] + - ME0900_CTRL_REG); - outb(0x00, - me0900_device->base.info.pci.reg_bases[2] + - ME0900_WRITE_ENABLE_REG); - } - - port_shift = - (me0900_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME0960) ? 1 : 0; - // Create subdevice instances. - - for (i = 0; i < me0900_versions[version_idx].di_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0900_di_constructor(me0900_device-> - base.info.pci. - reg_bases[2], - i + port_shift); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0900_device); - kfree(me0900_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0900_device->base.slist, - subdevice); - } - - for (i = 0; i < me0900_versions[version_idx].do_subdevices; i++) { - subdevice = - (me_subdevice_t *) me0900_do_constructor(me0900_device-> - base.info.pci. - reg_bases[2], i); - - if (!subdevice) { - me_device_deinit((me_device_t *) me0900_device); - kfree(me0900_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me0900_device->base.slist, - subdevice); - } - - return (me_device_t *) me0900_device; -} -EXPORT_SYMBOL(me0900_pci_constructor); - -// Init and exit of module. - -static int __init me0900_init(void) -{ - PDEBUG("executed.\n."); - return 0; -} - -static void __exit me0900_exit(void) -{ - PDEBUG("executed.\n."); -} - -module_init(me0900_init); -module_exit(me0900_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for ME-9x Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-9x Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me0900_device.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file me0900_device.h - * - * @brief ME-0900 (ME-9x) device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0900_DEVICE_H -#define _ME0900_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-0900 (ME-9x) device capabilities. - */ -typedef struct me0900_version { - uint16_t device_id; - unsigned int di_subdevices; - unsigned int do_subdevices; -} me0900_version_t; - -/** - * @brief Device capabilities. - */ -static me0900_version_t me0900_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME0940, 2, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME0950, 0, 2}, - {PCI_DEVICE_ID_MEILHAUS_ME0960, 1, 1}, - {0}, -}; - -#define ME0900_DEVICE_VERSIONS (ARRAY_SIZE(me0900_versions) - 1) /**< Returns the number of entries in #me0900_versions. */ - -/** - * @brief Returns the index of the device entry in #me0900_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me0900_versions. - */ -static inline unsigned int me0900_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME0900_DEVICE_VERSIONS; i++) - if (me0900_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-0900 (ME-9x) device class structure. - */ -typedef struct me0900_device { - me_device_t base; /**< The Meilhaus device base class. */ -} me0900_device_t; - -/** - * @brief The ME-9x device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-0900 (ME-9x) device instance. \n - * NULL on error. - */ -me_device_t *me0900_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me0900_di.c +++ /dev/null @@ -1,245 +0,0 @@ -/** - * @file me0900_di.c - * - * @brief ME-9x digital input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "meids.h" -#include "medebug.h" -#include "meplx_reg.h" -#include "me0900_reg.h" -#include "me0900_di.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0900_di_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - PDEBUG("executed.\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - return ME_ERRNO_SUCCESS; -} - -static int me0900_di_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me0900_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0900_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - } else { - PERROR("Invalid byte direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0900_di_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0900_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0900_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = (~inb(instance->port_reg)) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = ~inb(instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0900_di_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me0900_di_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0900_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me0900_di_subdevice_t *me0900_di_constructor(uint32_t reg_base, - unsigned int di_idx) -{ - me0900_di_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0900_di_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0900_di_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - /* Save the subdevice index. */ - subdevice->di_idx = di_idx; - - /* Initialize registers */ - if (di_idx == 0) { - subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; - subdevice->port_reg = reg_base + ME0900_PORT_A_REG; - } else { - subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; - subdevice->port_reg = reg_base + ME0900_PORT_B_REG; - } -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0900_di_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0900_di_io_single_config; - subdevice->base.me_subdevice_io_single_read = me0900_di_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me0900_di_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0900_di_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0900_di_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0900_di.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file me0900_di.h - * - * @brief ME-9x digital input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0900_DI_H_ -#define _ME0900_DI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0900_di_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - unsigned int di_idx; - - unsigned long ctrl_reg; - unsigned long port_reg; -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me0900_di_subdevice_t; - -/** - * @brief The constructor to generate a ME-9x digital input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0900_di_subdevice_t *me0900_di_constructor(uint32_t me0900_reg_base, - unsigned int di_idx); - -#endif -#endif --- a/drivers/staging/meilhaus/me0900_do.c +++ /dev/null @@ -1,314 +0,0 @@ -/** - * @file me0900_do.c - * - * @brief ME-9x digital output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me0900_reg.h" -#include "me0900_do.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me0900_do_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me0900_do_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me0900_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - outb(0xFF, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0xff); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me0900_do_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me0900_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0900_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - } else { - PERROR("Invalid byte direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0900_do_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me0900_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me0900_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = (~inb(instance->port_reg)) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = ~inb(instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0900_do_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me0900_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long state; - - PDEBUG("executed.\n"); - - instance = (me0900_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - state = inb(instance->port_reg); - state = - (!value) ? (state | (0x1 << channel)) : (state & - ~(0x1 << - channel)); - outb(state, instance->port_reg); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - outb(~(value), instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me0900_do_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me0900_do_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me0900_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base, - unsigned int do_idx) -{ - me0900_do_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me0900_do_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me0900_do_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - /* Save the subdevice index */ - subdevice->do_idx = do_idx; - - /* Initialize registers */ - if (do_idx == 0) { - subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; - subdevice->port_reg = reg_base + ME0900_PORT_A_REG; - subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG; - subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG; - } else { - subdevice->ctrl_reg = reg_base + ME0900_CTRL_REG; - subdevice->port_reg = reg_base + ME0900_PORT_B_REG; - subdevice->enable_reg = reg_base + ME0900_WRITE_ENABLE_REG; - subdevice->disable_reg = reg_base + ME0900_WRITE_DISABLE_REG; - } -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me0900_do_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me0900_do_io_single_config; - subdevice->base.me_subdevice_io_single_read = me0900_do_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me0900_do_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me0900_do_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me0900_do_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me0900_do_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me0900_do.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file me0900_do.h - * - * @brief ME-9x digital output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0900_DO_H_ -#define _ME0900_DO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me0900_do_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - unsigned int do_idx; - - unsigned long ctrl_reg; - unsigned long port_reg; - unsigned long enable_reg; - unsigned long disable_reg; -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me0900_do_subdevice_t; - -/** - * @brief The constructor to generate a ME-9x digital output subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param do_idx The index of the digital output subdevice on this device. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me0900_do_subdevice_t *me0900_do_constructor(uint32_t reg_base, - unsigned int do_idx); - -#endif -#endif --- a/drivers/staging/meilhaus/me0900_reg.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file me0900_reg.h - * - * @brief ME-9x register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME0900_REG_H_ -#define _ME0900_REG_H_ - -#ifdef __KERNEL__ - -#define ME0900_PORT_A_REG 0x00 -#define ME0900_PORT_B_REG 0x01 -#define ME0900_PORT_C_REG 0x02 -#define ME0900_CTRL_REG 0x03 // ( ,w) -#define ME0900_WRITE_ENABLE_REG 0x04 // (r,w) -#define ME0900_WRITE_DISABLE_REG 0x08 // (r,w) - -#endif -#endif --- a/drivers/staging/meilhaus/me1000_device.c +++ /dev/null @@ -1,206 +0,0 @@ -/** - * @file me1000_device.c - * - * @brief ME-1000 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "me1000_device.h" -#include "mesubdevice.h" -#include "me1000_dio.h" - -static int me1000_config_load(me_device_t *me_device, struct file *filep, - me_cfg_device_entry_t *config) -{ - me1000_device_t *me1000_device; - me1000_dio_subdevice_t *dio; - - PDEBUG("executed.\n"); - - me1000_device = (me1000_device_t *) me_device; - - if (config->count == 2) { - if (me_slist_get_number_subdevices(&me1000_device->base.slist) - == 2) { - // Nothing to do. - } else { - // Remove 2 extra subdevices - dio = - (me1000_dio_subdevice_t *) - me_slist_del_subdevice_tail(&me1000_device->base. - slist); - if (dio) - dio->base. - me_subdevice_destructor((me_subdevice_t *) - dio); - - dio = - (me1000_dio_subdevice_t *) - me_slist_del_subdevice_tail(&me1000_device->base. - slist); - if (dio) - dio->base. - me_subdevice_destructor((me_subdevice_t *) - dio); - } - } else if (config->count == 4) { - //Add 2 subdevices - if (me_slist_get_number_subdevices(&me1000_device->base.slist) - == 2) { - dio = - me1000_dio_constructor(me1000_device->base.info.pci. - reg_bases[2], 2, - &me1000_device->ctrl_lock); - if (!dio) { - PERROR("Cannot create dio subdevice.\n"); - return ME_ERRNO_INTERNAL; - } - me_slist_add_subdevice_tail(&me1000_device->base.slist, - (me_subdevice_t *) dio); - - dio = - me1000_dio_constructor(me1000_device->base.info.pci. - reg_bases[2], 3, - &me1000_device->ctrl_lock); - if (!dio) { - dio = - (me1000_dio_subdevice_t *) - me_slist_del_subdevice_tail(&me1000_device-> - base.slist); - if (dio) - dio->base. - me_subdevice_destructor((me_subdevice_t *) dio); - - PERROR("Cannot create dio subdevice.\n"); - return ME_ERRNO_INTERNAL; - } - me_slist_add_subdevice_tail(&me1000_device->base.slist, - (me_subdevice_t *) dio); - } else { - // Nothing to do. - } - } else { - PERROR("Invalid configuration.\n"); - return ME_ERRNO_INTERNAL; - } - - return ME_ERRNO_SUCCESS; -} - -me_device_t *me1000_pci_constructor(struct pci_dev * pci_device) -{ - me1000_device_t *me1000_device; - me_subdevice_t *subdevice; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me1000_device = kmalloc(sizeof(me1000_device_t), GFP_KERNEL); - - if (!me1000_device) { - PERROR("Cannot get memory for ME-1000 device instance.\n"); - return NULL; - } - - memset(me1000_device, 0, sizeof(me1000_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me1000_device, pci_device); - - if (err) { - kfree(me1000_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - // Initialize spin lock . - spin_lock_init(&me1000_device->ctrl_lock); - - for (i = 0; i < 4; i++) { - subdevice = - (me_subdevice_t *) me1000_dio_constructor(me1000_device-> - base.info.pci. - reg_bases[2], i, - &me1000_device-> - ctrl_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me1000_device); - kfree(me1000_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me1000_device->base.slist, - subdevice); - } - - // Overwrite base class methods. - me1000_device->base.me_device_config_load = me1000_config_load; - - return (me_device_t *) me1000_device; -} -EXPORT_SYMBOL(me1000_pci_constructor); - -// Init and exit of module. -static int __init me1000_init(void) -{ - PDEBUG("executed.\n"); - return 0; -} - -static void __exit me1000_exit(void) -{ - PDEBUG("executed.\n"); -} - -module_init(me1000_init); -module_exit(me1000_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-1000 Devices"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-1000 Digital I/O Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me1000_device.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file me1000_device.h - * - * @brief ME-1000 device class instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1000_H_ -#define _ME1000_H_ - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -#define ME1000_MAGIC_NUMBER 1000 - -/** - * @brief The ME-1000 device class structure. - */ -typedef struct me1000_device { - me_device_t base; /**< The Meilhaus device base class. */ - spinlock_t ctrl_lock; /**< Guards the DIO mode register. */ -} me1000_device_t; - -/** - * @brief The ME-1000 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-1000 device instance. \n - * NULL on error. - */ -me_device_t *me1000_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me1000_dio.c +++ /dev/null @@ -1,438 +0,0 @@ -/** - * @file me1000_dio.c - * - * @brief ME-1000 DIO subdevice instance. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2006 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" - -#include "me1000_dio_reg.h" -#include "me1000_dio.h" - -/* - * Defines - */ -#define ME1000_DIO_MAGIC_NUMBER 0x1000 /**< The magic number of the class structure. */ - -/* - * Functions - */ - -static int me1000_dio_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me1000_dio_subdevice_t *instance; - uint32_t tmp; - - PDEBUG("executed.\n"); - - instance = (me1000_dio_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp &= ~(0x1 << instance->dio_idx); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); - - outl(0x00000000, instance->port_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me1000_dio_io_single_config(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me1000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int ctrl; - int size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - - PDEBUG("executed.\n"); - - instance = (me1000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - ctrl = inl(instance->ctrl_reg); - - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_DWORD: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - ctrl &= ~(0x1 << instance->dio_idx); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - ctrl |= 0x1 << instance->dio_idx; - } else { - PERROR("Invalid port direction.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1000_dio_io_single_read(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me1000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me1000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 32)) { - *value = inl(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if ((channel >= 0) && (channel < 4)) { - *value = - (inl(instance->port_reg) >> (channel * 8)) & 0xFF; - } else { - PERROR("Invalid byte number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_WORD: - if ((channel >= 0) && (channel < 2)) { - *value = - (inl(instance->port_reg) >> (channel * 16)) & - 0xFFFF; - } else { - PERROR("Invalid word number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_DWORD: - if (channel == 0) { - *value = inl(instance->port_reg); - } else { - PERROR("Invalid dword number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1000_dio_io_single_write(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me1000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t config; - uint32_t state; - - PDEBUG("executed.\n"); - - instance = (me1000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - config = inl(instance->ctrl_reg) & (0x1 << instance->dio_idx); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 32)) { - if (config) { - state = inl(instance->port_reg); - state = - value ? (state | (0x1 << channel)) : (state - & - ~(0x1 - << - channel)); - outl(state, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, state); - } else { - PERROR("Port is not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if ((channel >= 0) && (channel < 4)) { - if (config) { - state = inl(instance->port_reg); - state &= ~(0xFF << (channel * 8)); - state |= (value & 0xFF) << (channel * 8); - outl(state, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, state); - } else { - PERROR("Port is not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_WORD: - if ((channel >= 0) && (channel < 2)) { - if (config) { - state = inl(instance->port_reg); - state &= ~(0xFFFF << (channel * 16)); - state |= (value & 0xFFFF) << (channel * 16); - outl(state, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, state); - } else { - PERROR("Port is not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid word number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_DWORD: - if (channel == 0) { - if (config) { - outl(value, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, value); - } else { - PERROR("Port is not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid dword number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1000_dio_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = ME1000_DIO_NUMBER_CHANNELS; - return ME_ERRNO_SUCCESS; -} - -static int me1000_dio_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me1000_dio_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - me1000_dio_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me1000_dio_subdevice_t *) subdevice; - - *caps = ME_CAPS_DIO_DIR_DWORD; - - return ME_ERRNO_SUCCESS; -} - -me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t *ctrl_reg_lock) -{ - me1000_dio_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me1000_dio_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for ME-1000 DIO instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me1000_dio_subdevice_t)); - - /* Check if counter index is out of range */ - - if (dio_idx >= ME1000_DIO_NUMBER_PORTS) { - PERROR("DIO index is out of range.\n"); - kfree(subdevice); - return NULL; - } - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the DIO index */ - subdevice->dio_idx = dio_idx; - - /* Initialize registers. */ -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - subdevice->ctrl_reg = reg_base + ME1000_PORT_MODE; - subdevice->port_reg = - reg_base + ME1000_PORT + (dio_idx * ME1000_PORT_STEP); - - /* Override base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me1000_dio_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me1000_dio_io_single_config; - subdevice->base.me_subdevice_io_single_read = me1000_dio_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me1000_dio_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me1000_dio_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me1000_dio_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me1000_dio_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me1000_dio.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file me1000_dio.h - * - * @brief Meilhaus ME-1000 digital i/o implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1000_DIO_H_ -#define _ME1000_DIO_H_ - -#include "mesubdevice.h" -#include "meslock.h" - -#ifdef __KERNEL__ - -/** - * @brief The ME-1000 DIO subdevice class. - */ -typedef struct me1000_dio_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ -// uint32_t magic; /**< The magic number unique for this structure. */ - - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */ - int dio_idx; /**< The index of the DIO port on the device. */ - - unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */ - unsigned long ctrl_reg; /**< Register to configure the DIO modes. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me1000_dio_subdevice_t; - -/** - * @brief The constructor to generate a ME-1000 DIO instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param dio_idx The index of the DIO on the device. - * @param ctrl_reg_lock Pointer to spin lock protecting the control register and from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me1000_dio_subdevice_t *me1000_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me1000_dio_reg.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file me1000_dio_reg.h - * - * @brief ME-1000 digital i/o register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1000_DIO_REG_H_ -# define _ME1000_DIO_REG_H_ - -# ifdef __KERNEL__ - -# define ME1000_DIO_NUMBER_CHANNELS 32 /**< The number of channels per DIO port. */ -# define ME1000_DIO_NUMBER_PORTS 4 /**< The number of ports per ME-1000. */ - -// # define ME1000_PORT_A 0x0000 /**< Port A base register offset. */ -// # define ME1000_PORT_B 0x0004 /**< Port B base register offset. */ -// # define ME1000_PORT_C 0x0008 /**< Port C base register offset. */ -// # define ME1000_PORT_D 0x000C /**< Port D base register offset. */ -# define ME1000_PORT 0x0000 /**< Base for port's register. */ -# define ME1000_PORT_STEP 4 /**< Distance between port's register. */ - -# define ME1000_PORT_MODE 0x0010 /**< Configuration register to switch the port direction. */ -// # define ME1000_PORT_MODE_OUTPUT_A (1 << 0) /**< If set, port A is in output, otherwise in input mode. */ -// # define ME1000_PORT_MODE_OUTPUT_B (1 << 1) /**< If set, port B is in output, otherwise in input mode. */ -// # define ME1000_PORT_MODE_OUTPUT_C (1 << 2) /**< If set, port C is in output, otherwise in input mode. */ -// # define ME1000_PORT_MODE_OUTPUT_D (1 << 3) /**< If set, port D is in output, otherwise in input mode. */ - -# endif //__KERNEL__ -#endif //_ME1000_DIO_REG_H_ --- a/drivers/staging/meilhaus/me1400_device.c +++ /dev/null @@ -1,253 +0,0 @@ -/** - * @file me1400_device.c - * - * @brief ME-1400 device instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -/* - * User application could also include the kernel header files. But the - * real kernel functions are protected by #ifdef __KERNEL__. - */ -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * This must be defined before module.h is included. Not needed, when - * it is a built in driver. - */ -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" - -#include "me1400_device.h" -#include "me8254.h" -#include "me8254_reg.h" -#include "me8255.h" -#include "me1400_ext_irq.h" - -me_device_t *me1400_pci_constructor(struct pci_dev *pci_device) -{ - int err; - me1400_device_t *me1400_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - unsigned int me8255_idx; - unsigned int dio_idx; - unsigned int me8254_idx; - unsigned int ctr_idx; - unsigned int ext_irq_idx; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me1400_device = kmalloc(sizeof(me1400_device_t), GFP_KERNEL); - - if (!me1400_device) { - PERROR("Cannot get memory for 1400ate device instance.\n"); - return NULL; - } - - memset(me1400_device, 0, sizeof(me1400_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me1400_device, pci_device); - - if (err) { - kfree(me1400_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Check for ME1400 extension device. If detected we fake a ME-1400 D device id. */ - if (me1400_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME140C) { - uint8_t ctrl; - ctrl = - inb(me1400_device->base.info.pci.reg_bases[2] + - ME1400D_CLK_SRC_2_REG); - PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n", - me1400_device->base.info.pci.reg_bases[2], - ME1400D_CLK_SRC_2_REG, ctrl); - outb(ctrl | 0xF0, - me1400_device->base.info.pci.reg_bases[2] + - ME1400D_CLK_SRC_2_REG); - PDEBUG_REG("xxx_reg outb(0x%X+0x%X)=0x%x\n", - me1400_device->base.info.pci.reg_bases[2], - ME1400D_CLK_SRC_2_REG, ctrl | 0xF0); - ctrl = - inb(me1400_device->base.info.pci.reg_bases[2] + - ME1400D_CLK_SRC_2_REG); - PDEBUG_REG("xxx_reg inb(0x%X+0x%X)=0x%x\n", - me1400_device->base.info.pci.reg_bases[2], - ME1400D_CLK_SRC_2_REG, ctrl); - - if ((ctrl & 0xF0) == 0xF0) { - PINFO("ME1400 D detected.\n"); - me1400_device->base.info.pci.device_id = - PCI_DEVICE_ID_MEILHAUS_ME140D; - } - } - - /* Initialize global stuff of digital i/o subdevices. */ - for (me8255_idx = 0; me8255_idx < ME1400_MAX_8255; me8255_idx++) { - me1400_device->dio_current_mode[me8255_idx] = 0; - spin_lock_init(&me1400_device->dio_ctrl_reg_lock[me8255_idx]); - } - - /* Initialize global stuff of counter subdevices. */ - spin_lock_init(&me1400_device->clk_src_reg_lock); - - for (me8254_idx = 0; me8254_idx < ME1400_MAX_8254; me8254_idx++) - spin_lock_init(&me1400_device->ctr_ctrl_reg_lock[me8254_idx]); - - /* Get the index in the device version information table. */ - version_idx = - me1400_versions_get_device_index(me1400_device->base.info.pci. - device_id); - - /* Generate DIO subdevice instances. */ - for (me8255_idx = 0; - me8255_idx < me1400_versions[version_idx].dio_chips; - me8255_idx++) { - for (dio_idx = 0; dio_idx < 3; dio_idx++) { - subdevice = - (me_subdevice_t *) - me8255_constructor(me1400_versions[version_idx]. - device_id, - me1400_device->base.info.pci. - reg_bases[2], me8255_idx, - dio_idx, - &me1400_device-> - dio_current_mode[me8255_idx], - &me1400_device-> - dio_ctrl_reg_lock[me8255_idx]); - - if (!subdevice) { - me_device_deinit((me_device_t *) me1400_device); - kfree(me1400_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me1400_device->base.slist, - subdevice); - } - } - - /* Generate counter subdevice instances. */ - for (me8254_idx = 0; - me8254_idx < me1400_versions[version_idx].ctr_chips; - me8254_idx++) { - for (ctr_idx = 0; ctr_idx < 3; ctr_idx++) { - subdevice = - (me_subdevice_t *) - me8254_constructor(me1400_device->base.info.pci. - device_id, - me1400_device->base.info.pci. - reg_bases[2], me8254_idx, - ctr_idx, - &me1400_device-> - ctr_ctrl_reg_lock[me8254_idx], - &me1400_device-> - clk_src_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me1400_device); - kfree(me1400_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me1400_device->base.slist, - subdevice); - } - } - - /* Generate external interrupt subdevice instances. */ - for (ext_irq_idx = 0; - ext_irq_idx < me1400_versions[version_idx].ext_irq_subdevices; - ext_irq_idx++) { - subdevice = - (me_subdevice_t *) - me1400_ext_irq_constructor(me1400_device->base.info.pci. - device_id, - me1400_device->base.info.pci. - reg_bases[1], - me1400_device->base.info.pci. - reg_bases[2], - &me1400_device->clk_src_reg_lock, - me1400_device->base.irq); - - if (!subdevice) { - me_device_deinit((me_device_t *) me1400_device); - kfree(me1400_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me1400_device->base.slist, - subdevice); - } - - return (me_device_t *) me1400_device; -} -EXPORT_SYMBOL(me1400_pci_constructor); - -// Init and exit of module. - -static int __init me1400_init(void) -{ - PDEBUG("executed.\n"); - return 0; -} - -static void __exit me1400_exit(void) -{ - PDEBUG("executed.\n"); -} - -module_init(me1400_init); -module_exit(me1400_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-14xx devices"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-14xx MIO devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me1400_device.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file me1400_device.c - * - * @brief ME-1400 device family instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1400_DEVICE_H_ -#define _ME1400_DEVICE_H_ - -#include "metypes.h" -#include "medefines.h" -#include "meinternal.h" - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure to store device capabilities. - */ -typedef struct me1400_version { - uint16_t device_id; /**< The PCI device id of the device. */ - unsigned int dio_chips; /**< The number of 8255 chips on the device. */ - unsigned int ctr_chips; /**< The number of 8254 chips on the device. */ - unsigned int ext_irq_subdevices; /**< The number of external interrupt inputs on the device. */ -} me1400_version_t; - -/** - * @brief Defines for each ME-1400 device version its capabilities. - */ -static me1400_version_t me1400_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME1400, 1, 0, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME140A, 1, 1, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME140B, 2, 2, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME14E0, 1, 0, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME14EA, 1, 1, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME14EB, 2, 2, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME140C, 1, 5, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME140D, 2, 10, 1}, - {0} -}; - -#define ME1400_DEVICE_VERSIONS (ARRAY_SIZE(me1400_versions) - 1) /**< Returns the number of entries in #me1400_versions. */ - -/** - * @brief Returns the index of the device entry in #me1400_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me1400_versions. - */ -static inline unsigned int me1400_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME1400_DEVICE_VERSIONS; i++) - if (me1400_versions[i].device_id == device_id) - break; - return i; -} - -#define ME1400_MAX_8254 10 /**< The maximum number of 8254 counter subdevices available on any ME-1400 device. */ -#define ME1400_MAX_8255 2 /**< The maximum number of 8255 digital i/o subdevices available on any ME-1400 device. */ - -/** - * @brief The ME-1400 device class. - */ -typedef struct me1400_device { - me_device_t base; /**< The Meilhaus device base class. */ - - spinlock_t clk_src_reg_lock; /**< Guards the 8254 clock source registers. */ - spinlock_t ctr_ctrl_reg_lock[ME1400_MAX_8254]; /**< Guards the 8254 ctrl registers. */ - - int dio_current_mode[ME1400_MAX_8255]; /**< Saves the current mode setting of a single 8255 DIO chip. */ - spinlock_t dio_ctrl_reg_lock[ME1400_MAX_8255]; /**< Guards the 8255 ctrl register and #dio_current_mode. */ -} me1400_device_t; - -/** - * @brief The ME-1400 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-1400 device instance. \n - * NULL on error. - */ -me_device_t *me1400_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me1400_ext_irq.c +++ /dev/null @@ -1,507 +0,0 @@ -/** - * @file me1400_ext_irq.c - * - * @brief ME-1400 external interrupt subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" -#include "meids.h" - -#include "me1400_ext_irq.h" -#include "me1400_ext_irq_reg.h" - -/* - * Defines - */ -#define ME1400_EXT_IRQ_MAGIC_NUMBER 0x1401 /**< The magic number of the class structure. */ -#define ME1400_EXT_IRQ_NUMBER_CHANNELS 1 /**< One channel per counter. */ - -/* - * Functions - */ - -static int me1400_ext_irq_io_irq_start(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me1400_ext_irq_subdevice_t *instance; - unsigned long cpu_flags; - uint8_t tmp; - - PDEBUG("executed.\n"); - - instance = (me1400_ext_irq_subdevice_t *) subdevice; - - if (flags & ~ME_IO_IRQ_START_DIO_BIT) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { - PERROR("Invalid irq source.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - if (irq_edge != ME_IRQ_EDGE_RISING) { - PERROR("Invalid irq edge.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - spin_lock(instance->clk_src_reg_lock); -// // Enable IRQ on PLX -// tmp = inb(instance->plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN); -// outb(tmp, instance->plx_intcs_reg); -// PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp); - - // Enable IRQ - switch (instance->device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME140C: - case PCI_DEVICE_ID_MEILHAUS_ME140D: - tmp = inb(instance->ctrl_reg); - tmp |= ME1400CD_EXT_IRQ_CLK_EN; - outb(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - break; - - default: - outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ME1400AB_EXT_IRQ_IRQ_EN); - break; - } - spin_unlock(instance->clk_src_reg_lock); - instance->rised = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me1400_ext_irq_io_irq_wait(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me1400_ext_irq_subdevice_t *instance; - unsigned long cpu_flags; - long t = 0; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me1400_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid time out.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - /* Convert to ticks */ - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - (instance->rised != - 0), t); - - if (t == 0) { - PERROR("Wait on interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - instance->rised = 0; - *irq_count = instance->n; - *value = 1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1400_ext_irq_io_irq_stop(struct me_subdevice *subdevice, - struct file *filep, - int channel, int flags) -{ - me1400_ext_irq_subdevice_t *instance; - unsigned long cpu_flags; - uint8_t tmp; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me1400_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->clk_src_reg_lock); -// // Disable IRQ on PLX -// tmp = inb(instance->plx_intcs_reg) & ( ~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | PLX_PCI_INT_EN)); -// outb(tmp, instance->plx_intcs_reg); -// PDEBUG_REG("ctrl_reg outb(PLX:0x%lX)=0x%x\n", instance->plx_intcs_reg, tmp); - - switch (instance->device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME140C: - case PCI_DEVICE_ID_MEILHAUS_ME140D: - tmp = inb(instance->ctrl_reg); - tmp &= ~ME1400CD_EXT_IRQ_CLK_EN; - outb(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - break; - - default: - outb(0x00, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, 0x00); - break; - } - spin_unlock(instance->clk_src_reg_lock); - instance->rised = -1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1400_ext_irq_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me1400_ext_irq_subdevice_t *instance = - (me1400_ext_irq_subdevice_t *) subdevice; - - PDEBUG("executed.\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - instance->n = 0; - return me1400_ext_irq_io_irq_stop(subdevice, filep, 0, flags); -} - -static int me1400_ext_irq_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = ME1400_EXT_IRQ_NUMBER_CHANNELS; - return ME_ERRNO_SUCCESS; -} - -static int me1400_ext_irq_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_EXT_IRQ; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me1400_ext_irq_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_EXT_IRQ_EDGE_RISING; - return ME_ERRNO_SUCCESS; -} - -static int me1400_ext_irq_query_subdevice_caps_args(struct me_subdevice - *subdevice, int cap, - int *args, int count) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static irqreturn_t me1400_ext_irq_isr(int irq, void *dev_id) -{ - me1400_ext_irq_subdevice_t *instance; - uint32_t status; - uint8_t tmp; - - instance = (me1400_ext_irq_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - spin_lock(&instance->subdevice_lock); - status = inl(instance->plx_intcs_reg); -// if (!((status & PLX_LOCAL_INT1_STATE) && (status & PLX_LOCAL_INT1_EN) && (status & PLX_PCI_INT_EN))) - if ((status & - (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) != - (PLX_LOCAL_INT1_STATE | PLX_LOCAL_INT1_EN | PLX_PCI_INT_EN)) { - spin_unlock(&instance->subdevice_lock); - PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", - jiffies, __func__, status); - return IRQ_NONE; - } - - inl(instance->ctrl_reg); - - PDEBUG("executed.\n"); - - instance->n++; - instance->rised = 1; - - switch (instance->device_id) { - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - case PCI_DEVICE_ID_MEILHAUS_ME140D: - spin_lock(instance->clk_src_reg_lock); - tmp = inb(instance->ctrl_reg); - tmp &= ~ME1400CD_EXT_IRQ_CLK_EN; - outb(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - tmp |= ME1400CD_EXT_IRQ_CLK_EN; - outb(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->clk_src_reg_lock); - - break; - - default: - outb(0, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, 0); - outb(ME1400AB_EXT_IRQ_IRQ_EN, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ME1400AB_EXT_IRQ_IRQ_EN); - break; - } - - spin_unlock(&instance->subdevice_lock); - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -static void me1400_ext_irq_destructor(struct me_subdevice *subdevice) -{ - me1400_ext_irq_subdevice_t *instance; - uint8_t tmp; - - PDEBUG("executed.\n"); - - instance = (me1400_ext_irq_subdevice_t *) subdevice; - - // Disable IRQ on PLX - tmp = - inb(instance-> - plx_intcs_reg) & (~(PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | - PLX_PCI_INT_EN)); - outb(tmp, instance->plx_intcs_reg); - PDEBUG_REG("ctrl_reg outb(plx:0x%lX)=0x%x\n", instance->plx_intcs_reg, - tmp); - - free_irq(instance->irq, (void *)instance); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id, - uint32_t plx_reg_base, - uint32_t me1400_reg_base, - spinlock_t * - clk_src_reg_lock, - int irq) -{ - me1400_ext_irq_subdevice_t *subdevice; - int err; - uint8_t tmp; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me1400_ext_irq_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for 1400_ext_irq instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me1400_ext_irq_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->clk_src_reg_lock = clk_src_reg_lock; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - subdevice->irq = irq; - - err = request_irq(irq, me1400_ext_irq_isr, - IRQF_DISABLED | IRQF_SHARED, - ME1400_NAME, (void *)subdevice); - - if (err) { - PERROR("Can't get irq.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - /* Initialize registers */ - subdevice->plx_intcs_reg = plx_reg_base + PLX_INTCSR_REG; - subdevice->ctrl_reg = me1400_reg_base + ME1400AB_EXT_IRQ_CTRL_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = me1400_reg_base; -#endif - - // Enable IRQ on PLX - tmp = - inb(subdevice-> - plx_intcs_reg) | (PLX_LOCAL_INT1_EN | PLX_LOCAL_INT1_POL | - PLX_PCI_INT_EN); - outb(tmp, subdevice->plx_intcs_reg); - PDEBUG_REG("ctrl_reg outb(Pplx:0x%lX)=0x%x\n", subdevice->plx_intcs_reg, - tmp); - - /* Initialize the subdevice methods */ - subdevice->base.me_subdevice_io_irq_start = me1400_ext_irq_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me1400_ext_irq_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me1400_ext_irq_io_irq_stop; - subdevice->base.me_subdevice_io_reset_subdevice = - me1400_ext_irq_io_reset_subdevice; - subdevice->base.me_subdevice_query_number_channels = - me1400_ext_irq_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me1400_ext_irq_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me1400_ext_irq_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me1400_ext_irq_query_subdevice_caps_args; - subdevice->base.me_subdevice_destructor = me1400_ext_irq_destructor; - - subdevice->rised = 0; - subdevice->n = 0; - - return subdevice; -} --- a/drivers/staging/meilhaus/me1400_ext_irq.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file me1400_ext_irq.h - * - * @brief ME-1400 external interrupt implementation. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME1400_EXT_IRQ_H_ -#define _ME1400_EXT_IRQ_H_ - -#include - -#include "mesubdevice.h" -#include "meslock.h" - -#ifdef __KERNEL__ - -/** - * @brief The ME-1400 external interrupt subdevice class. - */ -typedef struct me1400_ext_irq_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *clk_src_reg_lock; /**< Lock protecting the clock control register. */ - - wait_queue_head_t wait_queue; /**< Queue to put on threads waiting for an interrupt. */ - - uint32_t device_id; /**< The device id of the device holding the subdevice. */ - int irq; /**< The irq number assigned by PCI BIOS. */ - int rised; /**< If true an interrupt has occured. */ - unsigned int n; /**< The number of interrupt since the driver was loaded. */ - - unsigned long plx_intcs_reg; /**< The PLX interrupt control and status register. */ - unsigned long ctrl_reg; /**< The control register. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me1400_ext_irq_subdevice_t; - -/** - * @brief The constructor to generate a ME-1400 external interrupt instance. - * - * @param plx_reg_base The register base address of the PLX chip as returned by the PCI BIOS. - * @param me1400_reg_base The register base address of the ME-1400 device as returned by the PCI BIOS. - * @param irq The irq assigned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me1400_ext_irq_subdevice_t *me1400_ext_irq_constructor(uint32_t device_id, - uint32_t plx_reg_base, - uint32_t me1400_reg_base, - spinlock_t * - clk_src_reg_lock, - int irq); - -#endif -#endif --- a/drivers/staging/meilhaus/me1400_ext_irq_reg.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file me1400_ext_irq_reg.h - * - * @brief ME-1400 external interrupt register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1400_EXT_IRQ_REG_H_ -# define _ME1400_EXT_IRQ_REG_H_ - -# ifdef __KERNEL__ - -# define PLX_INTCSR_REG 0x4C /**< The PLX interrupt control and status register offset. */ -# define PLX_ICR_REG 0x50 /**< The PLX initialization control register offset. */ - -# define PLX_LOCAL_INT1_EN 0x01 /**< If set the local interrupt 1 is enabled. */ -# define PLX_LOCAL_INT1_POL 0x02 /**< If set the local interrupt 1 polarity is high active. */ -# define PLX_LOCAL_INT1_STATE 0x04 /**< If set the local interrupt 1 is activ. */ -# define PLX_LOCAL_INT2_EN 0x08 /**< If set the local interrupt 2 is enabled. */ -# define PLX_LOCAL_INT2_POL 0x10 /**< If set the local interrupt 2 polarity is high active. */ -# define PLX_LOCAL_INT2_STATE 0x20 /**< If set the local interrupt 2 is activ. */ -# define PLX_PCI_INT_EN 0x40 /**< If set the PCI interrupt is enabled. */ -# define PLX_SOFT_INT 0x80 /**< If set an interrupt is generated. */ - -# define ME1400AB_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */ - -# define ME1400AB_EXT_IRQ_CLK_EN 0x01 /**< If this bit is set, the clock output is enabled. */ -# define ME1400AB_EXT_IRQ_IRQ_EN 0x02 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt. */ - -# define ME1400CD_EXT_IRQ_CTRL_REG 0x11 /**< The external interrupt control register offset. */ - -# define ME1400CD_EXT_IRQ_CLK_EN 0x10 /**< If set the external interrupt is enabled. Clearing this bit clears a pending interrupt.*/ - -# endif //__KERNEL__ - -#endif //_ME1400_EXT_IRQ_REG_H_ --- a/drivers/staging/meilhaus/me1600_ao.c +++ /dev/null @@ -1,1017 +0,0 @@ -/** - * @file me1600_ao.c - * - * @brief ME-1600 analog output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* Includes - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" - -#include "me1600_ao_reg.h" -#include "me1600_ao.h" - -/* Defines - */ - -static void me1600_ao_destructor(struct me_subdevice *subdevice); - -static void me1600_ao_work_control_task(struct work_struct *work); - -static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags); -static int me1600_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, int channel, - int single_config, int ref, int trig_chan, - int trig_type, int trig_edge, int flags); -static int me1600_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, int channel, int *value, - int time_out, int flags); -static int me1600_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, int channel, int value, - int time_out, int flags); -static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, - int *number); -static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, - int *subtype); -static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); -static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, int *min, int *max, - int *maxdata, int *range); -static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, int unit, - int *count); -static int me1600_ao_query_range_info(me_subdevice_t *subdevice, int range, - int *unit, int *min, int *max, - int *maxdata); - -/* Functions - */ - -me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, - unsigned int ao_idx, - int curr, - spinlock_t *config_regs_lock, - spinlock_t *ao_shadows_lock, - me1600_ao_shadow_t *ao_regs_shadows, - struct workqueue_struct *me1600_wq) -{ - me1600_ao_subdevice_t *subdevice; - int err; - - PDEBUG("executed. idx=%d\n", ao_idx); - - // Allocate memory for subdevice instance. - subdevice = kmalloc(sizeof(me1600_ao_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR - ("Cannot get memory for analog output subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me1600_ao_subdevice_t)); - - // Initialize subdevice base class. - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->config_regs_lock = config_regs_lock; - subdevice->ao_shadows_lock = ao_shadows_lock; - - // Save the subdevice index. - subdevice->ao_idx = ao_idx; - - // Initialize range lists. - subdevice->u_ranges_count = 2; - - subdevice->u_ranges[0].min = 0; //0V - subdevice->u_ranges[0].max = 9997558; //10V - - subdevice->u_ranges[1].min = -10E6; //-10V - subdevice->u_ranges[1].max = 9995117; //10V - - if (curr) { // This is version with current outputs. - subdevice->i_ranges_count = 2; - - subdevice->i_ranges[0].min = 0; //0mA - subdevice->i_ranges[0].max = 19995117; //20mA - - subdevice->i_ranges[1].min = 4E3; //4mA - subdevice->i_ranges[1].max = 19995118; //20mA - } else { // This is version without current outputs. - subdevice->i_ranges_count = 0; - - subdevice->i_ranges[0].min = 0; //0mA - subdevice->i_ranges[0].max = 0; //0mA - - subdevice->i_ranges[1].min = 0; //0mA - subdevice->i_ranges[1].max = 0; //0mA - } - - // Initialize registers. - subdevice->uni_bi_reg = reg_base + ME1600_UNI_BI_REG; - subdevice->i_range_reg = reg_base + ME1600_020_420_REG; - subdevice->sim_output_reg = reg_base + ME1600_SIM_OUTPUT_REG; - subdevice->current_on_reg = reg_base + ME1600_CURRENT_ON_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - // Initialize shadow structure. - subdevice->ao_regs_shadows = ao_regs_shadows; - - // Override base class methods. - subdevice->base.me_subdevice_destructor = me1600_ao_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me1600_ao_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me1600_ao_io_single_config; - subdevice->base.me_subdevice_io_single_read = me1600_ao_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me1600_ao_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me1600_ao_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me1600_ao_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me1600_ao_query_subdevice_caps; - subdevice->base.me_subdevice_query_range_by_min_max = - me1600_ao_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me1600_ao_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me1600_ao_query_range_info; - - // Initialize wait queue. - init_waitqueue_head(&subdevice->wait_queue); - - // Prepare work queue. - subdevice->me1600_workqueue = me1600_wq; - -/* workqueue API changed in kernel 2.6.20 */ - INIT_DELAYED_WORK(&subdevice->ao_control_task, - me1600_ao_work_control_task); - return subdevice; -} - -static void me1600_ao_destructor(struct me_subdevice *subdevice) -{ - me1600_ao_subdevice_t *instance; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - instance->ao_control_task_flag = 0; - - // Reset subdevice to asure clean exit. - me1600_ao_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - - // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). - if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2); - } -} - -static int me1600_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me1600_ao_subdevice_t *instance; - uint16_t tmp; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. - - // Reset all settings. - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ao_shadows_lock); - (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0; - (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0; - (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Not waiting for triggering. - (instance->ao_regs_shadows)->synchronous &= ~(0x1 << instance->ao_idx); //Individual triggering. - - // Set output to default (safe) state. - spin_lock(instance->config_regs_lock); - tmp = inw(instance->uni_bi_reg); // unipolar - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->uni_bi_reg); - PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->uni_bi_reg - instance->reg_base, tmp); - - tmp = inw(instance->current_on_reg); // Volts only! - tmp &= ~(0x1 << instance->ao_idx); - tmp &= 0x00FF; - outw(tmp, instance->current_on_reg); - PDEBUG_REG("current_on_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->current_on_reg - instance->reg_base, tmp); - - tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->i_range_reg); - PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->i_range_reg - instance->reg_base, tmp); - - outw(0, (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - (instance->ao_regs_shadows)->registry[instance->ao_idx] - - instance->reg_base, 0); - - // Trigger output. - outw(0x0000, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, 0x0000); - outw(0xFFFF, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, 0xFFFF); - spin_unlock(instance->config_regs_lock); - spin_unlock(instance->ao_shadows_lock); - - // Set status to 'none' - instance->status = ao_status_none; - spin_unlock(&instance->subdevice_lock); - - //Signal reset if user is on wait. - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me1600_ao_subdevice_t *instance; - uint16_t tmp; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - // Checking parameters. - if (flags) { - PERROR - ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (trig_edge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid trigger edge. Software trigger has not edge. Must be ME_TRIG_EDGE_NONE\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - - if (trig_type != ME_TRIG_TYPE_SW) { - PERROR("Invalid trigger edge. Must be ME_TRIG_TYPE_SW.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - if ((trig_chan != ME_TRIG_CHAN_DEFAULT) - && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { - PERROR("Invalid trigger channel specified.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } - - if (ref != ME_REF_AO_GROUND) { - PERROR - ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); - return ME_ERRNO_INVALID_REF; - } - - if (((single_config + 1) > - (instance->u_ranges_count + instance->i_ranges_count)) - || (single_config < 0)) { - PERROR("Invalid range specified.\n"); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - // Checking parameters - done. All is fine. Do config. - - ME_SUBDEVICE_ENTER; - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ao_shadows_lock); - (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. - (instance->ao_regs_shadows)->shadow[instance->ao_idx] = 0; - (instance->ao_regs_shadows)->mirror[instance->ao_idx] = 0; - - spin_lock(instance->config_regs_lock); - switch (single_config) { - case 0: // 0V 10V - tmp = inw(instance->current_on_reg); // Volts - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->current_on_reg); - PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->current_on_reg - instance->reg_base, tmp); - - // 0V - outw(0, - (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[instance-> - ao_idx] - - instance->reg_base, 0); - - tmp = inw(instance->uni_bi_reg); // unipolar - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->uni_bi_reg); - PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->uni_bi_reg - instance->reg_base, tmp); - - tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->i_range_reg); - PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->i_range_reg - instance->reg_base, tmp); - break; - - case 1: // -10V 10V - tmp = inw(instance->current_on_reg); // Volts - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->current_on_reg); - PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->current_on_reg - instance->reg_base, tmp); - - // 0V - outw(0x0800, - (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[instance-> - ao_idx] - - instance->reg_base, 0x0800); - - tmp = inw(instance->uni_bi_reg); // bipolar - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->uni_bi_reg); - PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->uni_bi_reg - instance->reg_base, tmp); - - tmp = inw(instance->i_range_reg); // 0..20mA <= If exists. - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->i_range_reg); - PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->i_range_reg - instance->reg_base, tmp); - break; - - case 2: // 0mA 20mA - tmp = inw(instance->current_on_reg); // mAmpers - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->current_on_reg); - PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->current_on_reg - instance->reg_base, tmp); - - tmp = inw(instance->i_range_reg); // 0..20mA - tmp &= ~(0x1 << instance->ao_idx); - outw(tmp, instance->i_range_reg); - PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->i_range_reg - instance->reg_base, tmp); - - // 0mA - outw(0, - (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[instance-> - ao_idx] - - instance->reg_base, 0); - - tmp = inw(instance->uni_bi_reg); // unipolar - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->uni_bi_reg); - PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->uni_bi_reg - instance->reg_base, tmp); - break; - - case 3: // 4mA 20mA - tmp = inw(instance->current_on_reg); // mAmpers - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->current_on_reg); - PDEBUG_REG("current_on_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->current_on_reg - instance->reg_base, tmp); - - tmp = inw(instance->i_range_reg); // 4..20mA - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->i_range_reg); - PDEBUG_REG("i_range_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->i_range_reg - instance->reg_base, tmp); - - // 4mA - outw(0, - (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[instance-> - ao_idx] - - instance->reg_base, 0); - - tmp = inw(instance->uni_bi_reg); // unipolar - tmp |= (0x1 << instance->ao_idx); - outw(tmp, instance->uni_bi_reg); - PDEBUG_REG("uni_bi_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->uni_bi_reg - instance->reg_base, tmp); - break; - } - - // Trigger output. - outw(0x0000, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, 0x0000); - outw(0xFFFF, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, 0xFFFF); - - if (trig_chan == ME_TRIG_CHAN_DEFAULT) { // Individual triggering. - (instance->ao_regs_shadows)->synchronous &= - ~(0x1 << instance->ao_idx); - PDEBUG("Individual triggering.\n"); - } else if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) { // Synchronous triggering. - (instance->ao_regs_shadows)->synchronous |= - (0x1 << instance->ao_idx); - PDEBUG("Synchronous triggering.\n"); - } - spin_unlock(instance->config_regs_lock); - spin_unlock(instance->ao_shadows_lock); - - instance->status = ao_status_single_configured; - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me1600_ao_subdevice_t *instance; - unsigned long delay = 0; - unsigned long j = 0; - int err = ME_ERRNO_SUCCESS; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & ~ME_IO_SINGLE_NONBLOCKING) { - PERROR("Invalid flag specified. %d\n", flags); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if ((!flags) && ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { //Blocking mode. Wait for software trigger. - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - j = jiffies; - - //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. - wait_event_interruptible_timeout(instance->wait_queue, - (!((instance-> - ao_regs_shadows)-> - trigger & instance-> - ao_idx)), - (delay) ? delay : LONG_MAX); - - if (instance == ao_status_none) { // Reset was called. - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - PDEBUG("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - } - - *value = (instance->ao_regs_shadows)->mirror[instance->ao_idx]; - - return err; -} - -static int me1600_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me1600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long delay = 0; - int i; - unsigned long j = 0; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & - ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | - ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (value & ~ME1600_AO_MAX_DATA) { - PERROR("Invalid value provided.\n"); - return ME_ERRNO_VALUE_OUT_OF_RANGE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - (instance->ao_regs_shadows)->trigger &= ~(0x1 << instance->ao_idx); //Cancell waiting for trigger. - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - //Write value. - spin_lock(instance->ao_shadows_lock); - (instance->ao_regs_shadows)->shadow[instance->ao_idx] = - (uint16_t) value; - - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { // Trigger all outputs from synchronous list. - for (i = 0; i < (instance->ao_regs_shadows)->count; i++) { - if (((instance->ao_regs_shadows)->synchronous & (0x1 << i)) || (i == instance->ao_idx)) { // Set all from synchronous list to correct state. - PDEBUG - ("Synchronous triggering: output %d. idx=%d\n", - i, instance->ao_idx); - (instance->ao_regs_shadows)->mirror[i] = - (instance->ao_regs_shadows)->shadow[i]; - - outw((instance->ao_regs_shadows)->shadow[i], - (instance->ao_regs_shadows)->registry[i]); - PDEBUG_REG - ("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[i] - - instance->reg_base, - (instance->ao_regs_shadows)->shadow[i]); - - (instance->ao_regs_shadows)->trigger &= - ~(0x1 << i); - } - } - - // Trigger output. - outw(0x0000, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, 0); - outw(0xFFFF, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - instance->reg_base, - 0xFFFF); - instance->status = ao_status_single_end; - } else { // Individual mode. - if ((instance->ao_regs_shadows)->synchronous & (0x1 << instance->ao_idx)) { // Put on synchronous start list. Set output as waiting for trigger. - PDEBUG("Add to synchronous list. idx=%d\n", - instance->ao_idx); - (instance->ao_regs_shadows)->trigger |= - (0x1 << instance->ao_idx); - instance->status = ao_status_single_run; - PDEBUG("Synchronous list: 0x%x.\n", - (instance->ao_regs_shadows)->synchronous); - } else { // Fired this one. - PDEBUG("Triggering. idx=%d\n", instance->ao_idx); - (instance->ao_regs_shadows)->mirror[instance->ao_idx] = - (instance->ao_regs_shadows)->shadow[instance-> - ao_idx]; - - outw((instance->ao_regs_shadows)-> - shadow[instance->ao_idx], - (instance->ao_regs_shadows)->registry[instance-> - ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)-> - registry[instance->ao_idx] - - instance->reg_base, - (instance->ao_regs_shadows)-> - shadow[instance->ao_idx]); - - // Set output as triggered. - (instance->ao_regs_shadows)->trigger &= - ~(0x1 << instance->ao_idx); - - // Trigger output. - outw(0x0000, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - - instance->reg_base, 0); - outw(0xFFFF, instance->sim_output_reg); - PDEBUG_REG("sim_output_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sim_output_reg - - instance->reg_base, 0xFFFF); - instance->status = ao_status_single_end; - } - } - spin_unlock(instance->ao_shadows_lock); - - //Init control task - instance->timeout.delay = delay; - instance->timeout.start_time = jiffies; - instance->ao_control_task_flag = 1; - queue_delayed_work(instance->me1600_workqueue, - &instance->ao_control_task, 1); - - if ((!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) && - ((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { - /* Blocking mode. Wait for software trigger. */ - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - j = jiffies; - - //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. - wait_event_interruptible_timeout(instance->wait_queue, - (!((instance-> - ao_regs_shadows)-> - trigger & instance-> - ao_idx)), - (delay) ? delay : LONG_MAX); - - if (instance == ao_status_none) { - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - PDEBUG("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1600_ao_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - me1600_ao_subdevice_t *instance; - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *number = 1; //Every subdevice has only 1 channel. - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_query_subdevice_type(me_subdevice_t *subdevice, int *type, - int *subtype) -{ - me1600_ao_subdevice_t *instance; - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *type = ME_TYPE_AO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_AO_TRIG_SYNCHRONOUS; - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - me1600_ao_subdevice_t *instance; - int i; - int r = -1; - int diff = 21E6; - - instance = (me1600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((*max - *min) < 0) { - PERROR("Invalid minimum and maximum values specified.\n"); - return ME_ERRNO_INVALID_MIN_MAX; - } - // Maximum ranges are slightly less then 10V or 20mA. For convenient we accepted this value as valid one. - if (unit == ME_UNIT_VOLT) { - for (i = 0; i < instance->u_ranges_count; i++) { - if ((instance->u_ranges[i].min <= *min) - && ((instance->u_ranges[i].max + 5000) >= *max)) { - if ((instance->u_ranges[i].max - - instance->u_ranges[i].min) - (*max - - *min) < - diff) { - r = i; - diff = - (instance->u_ranges[i].max - - instance->u_ranges[i].min) - - (*max - *min); - } - } - } - - if (r < 0) { - PERROR("No matching range found.\n"); - return ME_ERRNO_NO_RANGE; - } else { - *min = instance->u_ranges[r].min; - *max = instance->u_ranges[r].max; - *range = r; - } - } else if (unit == ME_UNIT_AMPERE) { - for (i = 0; i < instance->i_ranges_count; i++) { - if ((instance->i_ranges[i].min <= *min) - && (instance->i_ranges[i].max + 5000 >= *max)) { - if ((instance->i_ranges[i].max - - instance->i_ranges[i].min) - (*max - - *min) < - diff) { - r = i; - diff = - (instance->i_ranges[i].max - - instance->i_ranges[i].min) - - (*max - *min); - } - } - } - - if (r < 0) { - PERROR("No matching range found.\n"); - return ME_ERRNO_NO_RANGE; - } else { - *min = instance->i_ranges[r].min; - *max = instance->i_ranges[r].max; - *range = r + instance->u_ranges_count; - } - } else { - PERROR("Invalid physical unit specified.\n"); - return ME_ERRNO_INVALID_UNIT; - } - *maxdata = ME1600_AO_MAX_DATA; - - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count) -{ - me1600_ao_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me1600_ao_subdevice_t *) subdevice; - switch (unit) { - case ME_UNIT_VOLT: - *count = instance->u_ranges_count; - break; - case ME_UNIT_AMPERE: - *count = instance->i_ranges_count; - break; - case ME_UNIT_ANY: - *count = instance->u_ranges_count + instance->i_ranges_count; - break; - default: - *count = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me1600_ao_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - me1600_ao_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me1600_ao_subdevice_t *) subdevice; - - if (((range + 1) > - (instance->u_ranges_count + instance->i_ranges_count)) - || (range < 0)) { - PERROR("Invalid range number specified.\n"); - return ME_ERRNO_INVALID_RANGE; - } - - if (range < instance->u_ranges_count) { - *unit = ME_UNIT_VOLT; - *min = instance->u_ranges[range].min; - *max = instance->u_ranges[range].max; - } else if (range < instance->u_ranges_count + instance->i_ranges_count) { - *unit = ME_UNIT_AMPERE; - *min = instance->i_ranges[range - instance->u_ranges_count].min; - *max = instance->i_ranges[range - instance->u_ranges_count].max; - } - *maxdata = ME1600_AO_MAX_DATA; - - return ME_ERRNO_SUCCESS; -} - -static void me1600_ao_work_control_task(struct work_struct *work) -{ - me1600_ao_subdevice_t *instance; - int reschedule = 1; - int signaling = 0; - - instance = - container_of((void *)work, me1600_ao_subdevice_t, ao_control_task); - - PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, - instance->ao_idx); - - if (!((instance->ao_regs_shadows)->trigger & instance->ao_idx)) { // Output was triggerd. - // Signal the end. - signaling = 1; - reschedule = 0; - if (instance->status == ao_status_single_run) { - instance->status = ao_status_single_end; - } - - } else if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - spin_lock(instance->ao_shadows_lock); - // Restore old settings. - PDEBUG("Write old value back to register.\n"); - (instance->ao_regs_shadows)->shadow[instance->ao_idx] = - (instance->ao_regs_shadows)->mirror[instance->ao_idx]; - - outw((instance->ao_regs_shadows)->mirror[instance->ao_idx], - (instance->ao_regs_shadows)->registry[instance->ao_idx]); - PDEBUG_REG("channel_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - (instance->ao_regs_shadows)->registry[instance-> - ao_idx] - - instance->reg_base, - (instance->ao_regs_shadows)->mirror[instance-> - ao_idx]); - - //Remove from synchronous strt list. - (instance->ao_regs_shadows)->trigger &= - ~(0x1 << instance->ao_idx); - if (instance->status == ao_status_none) { - instance->status = ao_status_single_end; - } - spin_unlock(instance->ao_shadows_lock); - - // Signal the end. - signaling = 1; - reschedule = 0; - } - - if (signaling) { //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } - - if (instance->ao_control_task_flag && reschedule) { // Reschedule task - queue_delayed_work(instance->me1600_workqueue, - &instance->ao_control_task, 1); - } else { - PINFO("<%s> Ending control task.\n", __func__); - } - -} --- a/drivers/staging/meilhaus/me1600_ao.h +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @file me1600_ao.h - * - * @brief Meilhaus ME-1600 analog output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1600_AO_H_ -#define _ME1600_AO_H_ - -# include -# include "mesubdevice.h" - -# ifdef __KERNEL__ - -# define ME1600_MAX_RANGES 2 /**< Specifies the maximum number of ranges in me1600_ao_subdevice_t::u_ranges und me1600_ao_subdevice_t::i_ranges. */ - -/** - * @brief Defines a entry in the range table. - */ -typedef struct me1600_ao_range_entry { - int32_t min; - int32_t max; -} me1600_ao_range_entry_t; - -typedef struct me1600_ao_timeout { - unsigned long start_time; - unsigned long delay; -} me1600_ao_timeout_t; - -typedef struct me1600_ao_shadow { - int count; - unsigned long *registry; - uint16_t *shadow; - uint16_t *mirror; - uint16_t synchronous; /**< Synchronization list. */ - uint16_t trigger; /**< Synchronization flag. */ -} me1600_ao_shadow_t; - -typedef enum ME1600_AO_STATUS { - ao_status_none = 0, - ao_status_single_configured, - ao_status_single_run, - ao_status_single_end, - ao_status_last -} ME1600_AO_STATUS; - -/** - * @brief The ME-1600 analog output subdevice class. - */ -typedef struct me1600_ao_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - int ao_idx; /**< The index of the analog output subdevice on the device. */ - - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *config_regs_lock; /**< Spin lock to protect configuration registers from concurrent access. */ - - int u_ranges_count; /**< The number of voltage ranges available on this subdevice. */ - me1600_ao_range_entry_t u_ranges[ME1600_MAX_RANGES]; /**< Array holding the voltage ranges on this subdevice. */ - int i_ranges_count; /**< The number of current ranges available on this subdevice. */ - me1600_ao_range_entry_t i_ranges[ME1600_MAX_RANGES]; /**< Array holding the current ranges on this subdevice. */ - - /* Registers */ - unsigned long uni_bi_reg; /**< Register for switching between unipoar and bipolar output mode. */ - unsigned long i_range_reg; /**< Register for switching between ranges. */ - unsigned long sim_output_reg; /**< Register used in order to update all channels simultaneously. */ - unsigned long current_on_reg; /**< Register enabling current output on the fourth subdevice. */ -# ifdef PDEBUG_REG - unsigned long reg_base; -# endif - - ME1600_AO_STATUS status; - me1600_ao_shadow_t *ao_regs_shadows; /**< Addresses and shadows of output's registers. */ - spinlock_t *ao_shadows_lock; /**< Protects the shadow's struct. */ - int mode; /**< Mode in witch output should works. */ - wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ - me1600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ - struct workqueue_struct *me1600_workqueue; - struct delayed_work ao_control_task; - - volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ -} me1600_ao_subdevice_t; - -/** - * @brief The constructor to generate a subdevice template instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param ao_idx The index of the analog output subdevice on the device. - * @param current Flag indicating that analog output with #ao_idx of 3 is capable of current output. - * @param config_regs_lock Pointer to spin lock protecting the configuration registers and from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me1600_ao_subdevice_t *me1600_ao_constructor(uint32_t reg_base, - unsigned int ao_idx, - int curr, - spinlock_t * config_regs_lock, - spinlock_t * ao_shadows_lock, - me1600_ao_shadow_t * - ao_regs_shadows, - struct workqueue_struct - *me1600_wq); - -# endif //__KERNEL__ -#endif //_ME1600_AO_H_ --- a/drivers/staging/meilhaus/me1600_ao_reg.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @file me1600_ao_reg.h - * - * @brief ME-1600 analog output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1600_AO_REG_H_ -#define _ME1600_AO_REG_H_ - -#ifdef __KERNEL__ - -#define ME1600_CHANNEL_0_REG 0x00 /**< Register to set a digital value on channel 0. */ -#define ME1600_CHANNEL_1_REG 0x02 /**< Register to set a digital value on channel 1. */ -#define ME1600_CHANNEL_2_REG 0x04 /**< Register to set a digital value on channel 2. */ -#define ME1600_CHANNEL_3_REG 0x06 /**< Register to set a digital value on channel 3. */ -#define ME1600_CHANNEL_4_REG 0x08 /**< Register to set a digital value on channel 4. */ -#define ME1600_CHANNEL_5_REG 0x0A /**< Register to set a digital value on channel 5. */ -#define ME1600_CHANNEL_6_REG 0x0C /**< Register to set a digital value on channel 6. */ -#define ME1600_CHANNEL_7_REG 0x0E /**< Register to set a digital value on channel 7. */ -#define ME1600_CHANNEL_8_REG 0x10 /**< Register to set a digital value on channel 8. */ -#define ME1600_CHANNEL_9_REG 0x12 /**< Register to set a digital value on channel 9. */ -#define ME1600_CHANNEL_10_REG 0x14 /**< Register to set a digital value on channel 10. */ -#define ME1600_CHANNEL_11_REG 0x16 /**< Register to set a digital value on channel 11. */ -#define ME1600_CHANNEL_12_REG 0x18 /**< Register to set a digital value on channel 12. */ -#define ME1600_CHANNEL_13_REG 0x1A /**< Register to set a digital value on channel 13. */ -#define ME1600_CHANNEL_14_REG 0x1C /**< Register to set a digital value on channel 14. */ -#define ME1600_CHANNEL_15_REG 0x1E /**< Register to set a digital value on channel 15. */ - -/* Every channel one bit: bipolar = 0, unipolar = 1 */ -#define ME1600_UNI_BI_REG 0x20 /**< Register to switch between unipolar and bipolar. */ - -/* Every channel one bit (only lower 8 Bits): 0..20mA = 0, 4..20mA = 1 */ -#define ME1600_020_420_REG 0x22 /**< Register to switch between the two current ranges. */ - -/* If a bit is set, the corresponding DAC (4 ports each) is - not set at the moment you write to an output of it. - Clearing the bit updates the port. */ -#define ME1600_SIM_OUTPUT_REG 0x24 /**< Register to update all channels of a subdevice simultaneously. */ - -/* Current on/off (only lower 8 bits): off = 0, on = 1 */ -#define ME1600_CURRENT_ON_REG 0x26 /**< Register to swicht between voltage and current output. */ - -#define ME1600_AO_MAX_DATA 0x0FFF /**< The maximum digital data accepted by an analog output channel. */ - -#endif -#endif --- a/drivers/staging/meilhaus/me1600_device.c +++ /dev/null @@ -1,259 +0,0 @@ -/** - * @file me1600_device.c - * - * @brief ME-1600 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "mesubdevice.h" -#include "me1600_device.h" - -static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base); -static void me1600_destructor(struct me_device *device); - -/** - * @brief Global variable. - * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). - */ -static struct workqueue_struct *me1600_workqueue; - -me_device_t *me1600_pci_constructor(struct pci_dev *pci_device) -{ - int err; - me1600_device_t *me1600_device; - me_subdevice_t *subdevice; - unsigned int chip_idx; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me1600_device = kmalloc(sizeof(me1600_device_t), GFP_KERNEL); - - if (!me1600_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me1600_device, 0, sizeof(me1600_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me1600_device, pci_device); - - if (err) { - kfree(me1600_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - // Initialize spin lock . - spin_lock_init(&me1600_device->config_regs_lock); - spin_lock_init(&me1600_device->ao_shadows_lock); - - // Get the number of analog output subdevices. - chip_idx = - me1600_versions_get_device_index(me1600_device->base.info.pci. - device_id); - - // Create shadow instance. - me1600_device->ao_regs_shadows.count = - me1600_versions[chip_idx].ao_chips; - me1600_device->ao_regs_shadows.registry = - kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(unsigned long), - GFP_KERNEL); - me1600_set_registry(me1600_device, - me1600_device->base.info.pci.reg_bases[2]); - me1600_device->ao_regs_shadows.shadow = - kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t), - GFP_KERNEL); - me1600_device->ao_regs_shadows.mirror = - kmalloc(me1600_versions[chip_idx].ao_chips * sizeof(uint16_t), - GFP_KERNEL); - - // Create subdevice instances. - for (i = 0; i < me1600_versions[chip_idx].ao_chips; i++) { - subdevice = - (me_subdevice_t *) me1600_ao_constructor(me1600_device-> - base.info.pci. - reg_bases[2], i, - ((me1600_versions - [chip_idx].curr > - i) ? 1 : 0), - &me1600_device-> - config_regs_lock, - &me1600_device-> - ao_shadows_lock, - &me1600_device-> - ao_regs_shadows, - me1600_workqueue); - - if (!subdevice) { - me_device_deinit((me_device_t *) me1600_device); - kfree(me1600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me1600_device->base.slist, - subdevice); - } - - // Overwrite base class methods. - me1600_device->base.me_device_destructor = me1600_destructor; - - return (me_device_t *) me1600_device; -} -EXPORT_SYMBOL(me1600_pci_constructor); - -static void me1600_destructor(struct me_device *device) -{ - me1600_device_t *me1600_device = (me1600_device_t *) device; - PDEBUG("executed.\n"); - - // Destroy shadow instance. - kfree(me1600_device->ao_regs_shadows.registry); - kfree(me1600_device->ao_regs_shadows.shadow); - kfree(me1600_device->ao_regs_shadows.mirror); - - me_device_deinit((me_device_t *) me1600_device); - kfree(me1600_device); -} - -static void me1600_set_registry(me1600_device_t *subdevice, uint32_t reg_base) -{ // Create shadow structure. - if (subdevice->ao_regs_shadows.count >= 1) { - subdevice->ao_regs_shadows.registry[0] = - (unsigned long)(reg_base + ME1600_CHANNEL_0_REG); - } - if (subdevice->ao_regs_shadows.count >= 2) { - subdevice->ao_regs_shadows.registry[1] = - (unsigned long)(reg_base + ME1600_CHANNEL_1_REG); - } - if (subdevice->ao_regs_shadows.count >= 3) { - subdevice->ao_regs_shadows.registry[2] = - (unsigned long)(reg_base + ME1600_CHANNEL_2_REG); - } - if (subdevice->ao_regs_shadows.count >= 4) { - subdevice->ao_regs_shadows.registry[3] = - (unsigned long)(reg_base + ME1600_CHANNEL_3_REG); - } - if (subdevice->ao_regs_shadows.count >= 5) { - subdevice->ao_regs_shadows.registry[4] = - (unsigned long)(reg_base + ME1600_CHANNEL_4_REG); - } - if (subdevice->ao_regs_shadows.count >= 6) { - subdevice->ao_regs_shadows.registry[5] = - (unsigned long)(reg_base + ME1600_CHANNEL_5_REG); - } - if (subdevice->ao_regs_shadows.count >= 7) { - subdevice->ao_regs_shadows.registry[6] = - (unsigned long)(reg_base + ME1600_CHANNEL_6_REG); - } - if (subdevice->ao_regs_shadows.count >= 8) { - subdevice->ao_regs_shadows.registry[7] = - (unsigned long)(reg_base + ME1600_CHANNEL_7_REG); - } - if (subdevice->ao_regs_shadows.count >= 9) { - subdevice->ao_regs_shadows.registry[8] = - (unsigned long)(reg_base + ME1600_CHANNEL_8_REG); - } - if (subdevice->ao_regs_shadows.count >= 10) { - subdevice->ao_regs_shadows.registry[9] = - (unsigned long)(reg_base + ME1600_CHANNEL_9_REG); - } - if (subdevice->ao_regs_shadows.count >= 11) { - subdevice->ao_regs_shadows.registry[10] = - (unsigned long)(reg_base + ME1600_CHANNEL_10_REG); - } - if (subdevice->ao_regs_shadows.count >= 12) { - subdevice->ao_regs_shadows.registry[11] = - (unsigned long)(reg_base + ME1600_CHANNEL_11_REG); - } - if (subdevice->ao_regs_shadows.count >= 13) { - subdevice->ao_regs_shadows.registry[12] = - (unsigned long)(reg_base + ME1600_CHANNEL_12_REG); - } - if (subdevice->ao_regs_shadows.count >= 14) { - subdevice->ao_regs_shadows.registry[13] = - (unsigned long)(reg_base + ME1600_CHANNEL_13_REG); - } - if (subdevice->ao_regs_shadows.count >= 15) { - subdevice->ao_regs_shadows.registry[14] = - (unsigned long)(reg_base + ME1600_CHANNEL_14_REG); - } - if (subdevice->ao_regs_shadows.count >= 16) { - subdevice->ao_regs_shadows.registry[15] = - (unsigned long)(reg_base + ME1600_CHANNEL_15_REG); - } - if (subdevice->ao_regs_shadows.count > 16) { - PERROR("More than 16 outputs! (%d)\n", - subdevice->ao_regs_shadows.count); - } -} - -// Init and exit of module. - -static int __init me1600_init(void) -{ - PDEBUG("executed\n."); - - me1600_workqueue = create_singlethread_workqueue("me1600"); - return 0; -} - -static void __exit me1600_exit(void) -{ - PDEBUG("executed\n."); - - flush_workqueue(me1600_workqueue); - destroy_workqueue(me1600_workqueue); -} - -module_init(me1600_init); -module_exit(me1600_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for ME-1600 Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-1600 Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me1600_device.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @file me1600_device.h - * - * @brief ME-1600 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME1600_H -#define _ME1600_H - -#include -#include - -#include "medevice.h" -#include "me1600_ao.h" -#include "me1600_ao_reg.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure to store device capabilities. - */ -typedef struct me1600_version { - uint16_t device_id; /**< The PCI device id of the device. */ - unsigned int ao_chips; /**< The number of analog outputs on the device. */ - int curr; /**< Flag to identify amounts of current output. */ -} me1600_version_t; - -/** - * @brief Defines for each ME-1600 device version its capabilities. - */ -static me1600_version_t me1600_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME1600_4U, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME1600_8U, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME1600_12U, 12, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME1600_16U, 16, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I, 16, 8}, - {0} -}; - -/**< Returns the number of entries in #me1600_versions. */ -#define ME1600_DEVICE_VERSIONS (ARRAY_SIZE(me1600_versions) - 1) - -/** - * @brief Returns the index of the device entry in #me1600_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me1600_versions. - */ -static inline unsigned int me1600_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME1600_DEVICE_VERSIONS; i++) - if (me1600_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-1600 device class structure. - */ -typedef struct me1600_device { - me_device_t base; /**< The Meilhaus device base class. */ - spinlock_t config_regs_lock; /**< Protects the configuration registers. */ - - me1600_ao_shadow_t ao_regs_shadows; /**< Addresses and shadows of output's registers. */ - spinlock_t ao_shadows_lock; /**< Protects the shadow's struct. */ -} me1600_device_t; - -/** - * @brief The ME-1600 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-1600 device instance. \n - * NULL on error. - */ -me_device_t *me1600_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_ai.c +++ /dev/null @@ -1,3405 +0,0 @@ -/** - * @file me4600_ai.c - * - * @brief ME-4000 analog input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" -#include "meids.h" - -#include "me4600_reg.h" -#include "me4600_ai_reg.h" -#include "me4600_ai.h" - -/* - * Declarations (local) - */ - -static void me4600_ai_destructor(struct me_subdevice *subdevice); -static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags); - -static int me4600_ai_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags); - -static int me4600_ai_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags); - -static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags); -static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, - struct file *filep, - int read_mode, - int *values, int *count, int flags); -static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags); -static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * - instance, int *values, - const int count, - const int flags); - -static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags); -static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags); -static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags); - -static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range); -static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count); -static int me4600_ai_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); -static int me4600_ai_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks); -static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, - int *number); -static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype); -static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); -static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count); - -static irqreturn_t me4600_ai_isr(int irq, void *dev_id); - -static int ai_mux_toggler(me4600_ai_subdevice_t *subdevice); - -/** Immidiate stop. -* Reset all IRQ's sources. (block laches) -* Preserve FIFO -*/ -static int ai_stop_immediately(me4600_ai_subdevice_t *instance); - -/** Immidiate stop. -* Reset all IRQ's sources. (block laches) -* Reset data FIFO -*/ -inline void ai_stop_isr(me4600_ai_subdevice_t *instance); - -/** Interrupt logics. -* Read datas -* Reset latches -*/ -void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, - const uint32_t ctrl_status); -void ai_infinite_isr(me4600_ai_subdevice_t *instance, - const uint32_t irq_status, const uint32_t ctrl_status); - -/** Last chunck of datas. We must reschedule sample counter. -* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. -* When threshold is wrongly set some IRQ are lost.(!!!) -*/ -inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance); - -/** Read datas from FIFO and copy them to buffer */ -static inline int ai_read_data(me4600_ai_subdevice_t *instance, - const int count); - -/** Copy rest of data from fifo to circular buffer.*/ -static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance); - -/** Set ISM to next state for infinite data aqusation mode*/ -inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance); - -/** Set ISM to next state for define amount of data aqusation mode*/ -inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, - uint32_t irq_status); - -/** Set ISM to next stage for limited mode */ -inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance); - -static void me4600_ai_work_control_task(struct work_struct *work); - -/* Definitions - */ - -me4600_ai_subdevice_t *me4600_ai_constructor(uint32_t reg_base, - unsigned int channels, - unsigned int ranges, - int isolated, - int sh, - int irq, - spinlock_t *ctrl_reg_lock, - struct workqueue_struct *me4600_wq) -{ - me4600_ai_subdevice_t *subdevice; - int err; - unsigned int i; - - PDEBUG("executed. idx=0\n"); - - // Allocate memory for subdevice instance. - subdevice = kmalloc(sizeof(me4600_ai_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_ai_subdevice_t)); - - // Initialize subdevice base class. - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - // Initialize circular buffer. - subdevice->circ_buf.mask = ME4600_AI_CIRC_BUF_COUNT - 1; - - subdevice->circ_buf.buf = - (void *)__get_free_pages(GFP_KERNEL, ME4600_AI_CIRC_BUF_SIZE_ORDER); - PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE); - - if (!subdevice->circ_buf.buf) { - PERROR("Cannot get circular buffer.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - kfree(subdevice); - return NULL; - } - - memset(subdevice->circ_buf.buf, 0, ME4600_AI_CIRC_BUF_SIZE); - subdevice->circ_buf.head = 0; - subdevice->circ_buf.tail = 0; - subdevice->status = ai_status_none; - - // Initialize wait queue. - init_waitqueue_head(&subdevice->wait_queue); - - // Save the number of channels. - subdevice->channels = channels; - - /* Initialize the single config entries to reset values */ - for (i = 0; i < channels; i++) { - subdevice->single_config[i].status = ME_SINGLE_CHANNEL_NOT_CONFIGURED; //not configured - } - - // Save if isolated device. - subdevice->isolated = isolated; - - // Save if sample and hold is available. - subdevice->sh = sh; - - // Set stream config to not configured state. - subdevice->fifo_irq_threshold = 0; - subdevice->data_required = 0; - subdevice->chan_list_len = 0; - - // Initialize registers addresses. - subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AI_STATUS_REG; - subdevice->channel_list_reg = reg_base + ME4600_AI_CHANNEL_LIST_REG; - subdevice->data_reg = reg_base + ME4600_AI_DATA_REG; - subdevice->chan_timer_reg = reg_base + ME4600_AI_CHAN_TIMER_REG; - subdevice->chan_pre_timer_reg = reg_base + ME4600_AI_CHAN_PRE_TIMER_REG; - subdevice->scan_timer_low_reg = reg_base + ME4600_AI_SCAN_TIMER_LOW_REG; - subdevice->scan_timer_high_reg = - reg_base + ME4600_AI_SCAN_TIMER_HIGH_REG; - subdevice->scan_pre_timer_low_reg = - reg_base + ME4600_AI_SCAN_PRE_TIMER_LOW_REG; - subdevice->scan_pre_timer_high_reg = - reg_base + ME4600_AI_SCAN_PRE_TIMER_HIGH_REG; - subdevice->start_reg = reg_base + ME4600_AI_START_REG; - subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; - subdevice->sample_counter_reg = reg_base + ME4600_AI_SAMPLE_COUNTER_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - // Initialize ranges. - subdevice->ranges_len = ranges; - subdevice->ranges[0].min = -10E6; - subdevice->ranges[0].max = 9999694; - - subdevice->ranges[1].min = 0; - subdevice->ranges[1].max = 9999847; - - subdevice->ranges[2].min = -25E5; - subdevice->ranges[2].max = 2499923; - - subdevice->ranges[3].min = 0; - subdevice->ranges[3].max = 2499961; - - // We have to switch the mux in order to get it work correctly. - ai_mux_toggler(subdevice); - - // Register interrupt service routine. - subdevice->irq = irq; - if (request_irq(subdevice->irq, me4600_ai_isr, - IRQF_DISABLED | IRQF_SHARED, - ME4600_NAME, subdevice)) { - PERROR("Cannot register interrupt service routine.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - free_pages((unsigned long)subdevice->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE_ORDER); - subdevice->circ_buf.buf = NULL; - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - // Override base class methods. - subdevice->base.me_subdevice_destructor = me4600_ai_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_ai_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_ai_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_ai_io_single_read; - subdevice->base.me_subdevice_io_stream_config = - me4600_ai_io_stream_config; - subdevice->base.me_subdevice_io_stream_new_values = - me4600_ai_io_stream_new_values; - subdevice->base.me_subdevice_io_stream_read = me4600_ai_io_stream_read; - subdevice->base.me_subdevice_io_stream_start = - me4600_ai_io_stream_start; - subdevice->base.me_subdevice_io_stream_status = - me4600_ai_io_stream_status; - subdevice->base.me_subdevice_io_stream_stop = me4600_ai_io_stream_stop; - subdevice->base.me_subdevice_query_number_channels = - me4600_ai_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_ai_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_ai_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me4600_ai_query_subdevice_caps_args; - subdevice->base.me_subdevice_query_range_by_min_max = - me4600_ai_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me4600_ai_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me4600_ai_query_range_info; - subdevice->base.me_subdevice_query_timer = me4600_ai_query_timer; - - // Prepare work queue. - subdevice->me4600_workqueue = me4600_wq; - -/* workqueue API changed in kernel 2.6.20 */ - INIT_DELAYED_WORK(&subdevice->ai_control_task, - me4600_ai_work_control_task); - - return subdevice; -} - -static void me4600_ai_destructor(struct me_subdevice *subdevice) -{ - me4600_ai_subdevice_t *instance; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - instance->ai_control_task_flag = 0; - // Reset subdevice to asure clean exit. - me4600_ai_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - - // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). - if (!cancel_delayed_work(&instance->ai_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2); - } - - free_irq(instance->irq, instance); - free_pages((unsigned long)instance->circ_buf.buf, - ME4600_AI_CIRC_BUF_SIZE_ORDER); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static int me4600_ai_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - volatile uint32_t ctrl; - unsigned long status; - const int timeout = HZ / 10; //100ms - int i; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - instance->ai_control_task_flag = 0; - instance->status = ai_status_none; - - for (i = 0; i <= timeout; i++) { - spin_lock_irqsave(instance->ctrl_reg_lock, status); - ctrl = inl(instance->ctrl_reg); - //Stop DMA - ctrl &= ~ME4600_AI_CTRL_RPCI_FIFO; - // Stop all actions. No conditions! - ctrl &= ~ME4600_AI_CTRL_BIT_STOP; - ctrl |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, status); - - if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) - break; - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR("FSM is still busy.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - spin_lock_irqsave(instance->ctrl_reg_lock, status); - ctrl = inl(instance->ctrl_reg); - // Clear all features. Dissable interrupts. - ctrl &= ~(ME4600_AI_CTRL_BIT_STOP - | ME4600_AI_CTRL_BIT_LE_IRQ - | ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ); - ctrl |= (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP - | ME4600_AI_CTRL_BIT_LE_IRQ_RESET - | ME4600_AI_CTRL_BIT_HF_IRQ_RESET - | ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, status); - - outl(ME4600_AI_MIN_CHAN_TICKS - 1, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, - ME4600_AI_MIN_CHAN_TICKS); - outl(ME4600_AI_MIN_ACQ_TICKS - 1, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llx\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, - ME4600_AI_MIN_ACQ_TICKS); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0xEFFFFFFF, instance->sample_counter_reg); - PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - 0xEFFFFFFF); - - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - instance->fifo_irq_threshold = 0; - instance->data_required = 0; - instance->chan_list_len = 0; - - // Initialize the single config entries to reset values. - for (i = 0; i < instance->channels; i++) { - instance->single_config[i].status = - ME_SINGLE_CHANNEL_NOT_CONFIGURED; - } - instance->status = ai_status_none; - - //Signal reset if user is on wait. - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - int i; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - if (flags & ~ME_IO_SINGLE_CONFIG_CONTINUE) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - switch (trig_type) { - case ME_TRIG_TYPE_SW: - if (trig_edge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid trigger edge. Software trigger has not edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if (instance->channels <= 16) //Only versions with 32 channels have analog trigger (4670 and 4680) - { - PERROR("Invalid trigger type specified.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - case ME_TRIG_TYPE_EXT_DIGITAL: - if ((trig_edge != ME_TRIG_EDGE_ANY) - && (trig_edge != ME_TRIG_EDGE_RISING) - && (trig_edge != ME_TRIG_EDGE_FALLING)) { - PERROR("Invalid trigger edge specified.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - default: - PERROR("Invalid trigger type specified.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - if (trig_chan != ME_TRIG_CHAN_DEFAULT) { - PERROR("Invalid trigger channel specified.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } - - if ((single_config < 0) || (single_config >= instance->ranges_len)) { - PERROR("Invalid single config specified.\n"); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - - if ((ref != ME_REF_AI_GROUND) && (ref != ME_REF_AI_DIFFERENTIAL)) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((single_config % 2) && (ref != ME_REF_AI_GROUND)) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((ref == ME_REF_AI_DIFFERENTIAL) - && ((instance->channels == 16) || (channel >= 16))) { - PERROR("Invalid analog reference specified.\n"); - return ME_ERRNO_INVALID_REF; - } - - if (channel < 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (channel >= instance->channels) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - //Prepare data entry. - // Common for all modes. - instance->single_config[channel].entry = - channel | ME4600_AI_LIST_LAST_ENTRY; - - if (ref == ME_REF_AI_DIFFERENTIAL) { // ME_REF_AI_DIFFERENTIAL - instance->single_config[channel].entry |= - ME4600_AI_LIST_INPUT_DIFFERENTIAL; - } -/* - // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 - // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' <== Do nothing. Removed. - else - {// ME_REF_AI_GROUND - instance->single_config[channel].entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; - } -*/ - switch (single_config) { - case 0: //-10V..10V -/* - // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 - // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. - instance->single_config[channel].entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; -*/ break; - - case 1: //0V..10V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_UNIPOLAR_10; - break; - - case 2: //-2.5V..2.5V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_BIPOLAR_2_5; - break; - - case 3: //0V..2.5V - instance->single_config[channel].entry |= - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - } - - // Prepare control register. - // Common for all modes. - instance->single_config[channel].ctrl = - ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - - switch (trig_type) { - case ME_TRIG_TYPE_SW: - // Nothing to set. - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; - - case ME_TRIG_TYPE_EXT_DIGITAL: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG; - break; - } - - switch (trig_edge) { - case ME_TRIG_EDGE_RISING: - // Nothing to set. - break; - - case ME_TRIG_EDGE_ANY: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; - - case ME_TRIG_EDGE_FALLING: - instance->single_config[channel].ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; - break; - } - - // Enable this channel - instance->single_config[channel].status = ME_SINGLE_CHANNEL_CONFIGURED; - - // Copy this settings to other outputs. - if (flags == ME_IO_SINGLE_CONFIG_CONTINUE) { - for (i = channel + 1; i < instance->channels; i++) { - instance->single_config[i].ctrl = - instance->single_config[channel].ctrl; - instance->single_config[i].entry = - instance->single_config[channel].entry; - instance->single_config[i].status = - ME_SINGLE_CHANNEL_CONFIGURED; - } - } - - instance->status = ai_status_single_configured; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_ai_subdevice_t *instance; - volatile uint32_t tmp; - volatile uint32_t val; - unsigned long cpu_flags; - int err = ME_ERRNO_SUCCESS; - - unsigned long j; - unsigned long delay = 0; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (instance->status != ai_status_single_configured) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if ((channel > instance->channels) || (channel < 0)) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (instance->single_config[channel].status != - ME_SINGLE_CHANNEL_CONFIGURED) { - PERROR("Channel is not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - return ME_ERRNO_SUBDEVICE_BUSY; - } - - ME_SUBDEVICE_ENTER; - - // Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - // Mark that StreamConfig is removed. - instance->chan_list_len = 0; - - spin_lock(instance->ctrl_reg_lock); - /// @note Imprtant: Preserve EXT IRQ settings. - tmp = inl(instance->ctrl_reg); - // Clear FIFOs and dissable interrupts - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ | - ME4600_AI_CTRL_BIT_LE_IRQ); - tmp |= - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_LE_IRQ_RESET; - - tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(65, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 65); - outl(65, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, 65); - - //Reactive FIFOs. Enable work. - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - outl(instance->single_config[channel].entry, - instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - instance->single_config[channel].entry); - - // Preserve EXT IRQ settings. - tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(instance->single_config[channel].ctrl | tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, - instance->single_config[channel].ctrl | tmp); - - spin_unlock(instance->ctrl_reg_lock); - - if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - - delay = 2; - } - - j = jiffies; - - while (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { - if (delay && ((jiffies - j) >= delay)) { - if (!(instance->single_config[channel].ctrl & ME4600_AI_CTRL_BIT_EX_TRIG)) { // Software start. - PERROR("Value not available after wait.\n"); - err = ME_ERRNO_INTERNAL; - } else { // External start. - PERROR("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - break; - } - // Wait - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - - if (signal_pending(current)) { - PERROR - ("Wait on external trigger interrupted by signal.\n"); - err = ME_ERRNO_SIGNAL; - break; - } - - if (instance->status != ai_status_single_configured) { - PERROR("Wait interrupted by reset.\n"); - err = ME_ERRNO_CANCELLED; - break; - } - } - - // Read value. - if (!err) { - val = inl(instance->data_reg) ^ 0x8000; - PDEBUG_REG("data_reg inl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->data_reg - instance->reg_base, val); - *value = val & ME4600_AI_MAX_DATA; - } else { - *value = 0xFFFFFFFF; - } - - // Restore settings. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - // Clear FIFOs and dissable interrupts. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - tmp |= ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_HF_IRQ; - tmp |= - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int i; // internal multipurpose variable - unsigned long long data_required; - - volatile uint32_t entry; - volatile uint32_t ctrl = ME4600_AI_CTRL_BIT_IMMEDIATE_STOP; - volatile uint32_t tmp; // use when current copy of register's value needed - unsigned long cpu_flags; - - uint64_t acq_ticks; - uint64_t scan_ticks; - uint64_t conv_ticks; - unsigned int acq_start_ticks_low = trigger->iAcqStartTicksLow; - unsigned int acq_start_ticks_high = trigger->iAcqStartTicksHigh; - unsigned int scan_start_ticks_low = trigger->iScanStartTicksLow; - unsigned int scan_start_ticks_high = trigger->iScanStartTicksHigh; - unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; - unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER - // Convert ticks to 64 bit long values - acq_ticks = - (uint64_t) acq_start_ticks_low + - ((uint64_t) acq_start_ticks_high << 32); - scan_ticks = - (uint64_t) scan_start_ticks_low + - ((uint64_t) scan_start_ticks_high << 32); - conv_ticks = - (uint64_t) conv_start_ticks_low + - ((uint64_t) conv_start_ticks_high << 32); - - // Check settings - begin - switch (trigger->iAcqStartTrigType) { - case ME_TRIG_TYPE_SW: - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - break; - - default: - PERROR("Invalid acquisition start trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - goto ERROR; - break; - } - - if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) - && (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE)) { - PERROR("Invalid acquisition start trigger edge specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto ERROR; - } - - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) { - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - case ME_TRIG_EDGE_ANY: - break; - - default: - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto ERROR; - break; - } - } - - if (trigger->iAcqStartTrigChan != ME_TRIG_CHAN_DEFAULT) { - PERROR - ("Invalid acquisition start trigger channel specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; - goto ERROR; - } - - if ((acq_ticks < ME4600_AI_MIN_ACQ_TICKS) - || (acq_ticks > ME4600_AI_MAX_ACQ_TICKS)) { - PERROR - ("Invalid acquisition start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_ARG; - goto ERROR; - } - - switch (trigger->iScanStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - if ((scan_ticks < ME4600_AI_MIN_SCAN_TICKS) - || (scan_ticks > ME4600_AI_MAX_SCAN_TICKS) - || (scan_ticks < count * conv_ticks) - ) { - PERROR("Invalid scan start argument specified.\n"); - err = ME_ERRNO_INVALID_SCAN_START_ARG; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL) { - PERROR - ("Invalid scan start trigger type specified (Acq is HW digital)\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_ANALOG) { - PERROR - ("Invalid scan start trigger type specified (Acq is HW analog)\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_FOLLOW: - break; - - default: - PERROR("Invalid scan start trigger type specified.\n"); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto ERROR; - break; - } - - switch (trigger->iConvStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - if ((conv_ticks < ME4600_AI_MIN_CHAN_TICKS) - || (conv_ticks > ME4600_AI_MAX_CHAN_TICKS)) { - PERROR - ("Invalid conv start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_ARG; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) - || (trigger->iAcqStartTrigType != - ME_TRIG_TYPE_EXT_DIGITAL)) { - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_EXT_ANALOG: - if ((trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) - || (trigger->iAcqStartTrigType != - ME_TRIG_TYPE_EXT_ANALOG)) { - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - } - break; - - default: - PERROR("Invalid conv start trigger type specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto ERROR; - - break; - } -/** -* Aceptable settings: -* iScanStopTrigType : iAcqStopTrigType -* -* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_NONE -> infinite count with manual stop -* ME_TRIG_TYPE_NONE : ME_TRIG_TYPE_COUNT -> stop after getting iScanStopCount list of values (iScanStopCount * count) -* ME_TRIG_TYPE_COUNT : ME_TRIG_TYPE_FOLLOW -> stop after getting iAcqStopCount values (it can stops in midle of the list) -*/ - switch (trigger->iScanStopTrigType) { - - case ME_TRIG_TYPE_NONE: - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopCount <= 0) { - PERROR("Invalid scan stop argument specified.\n"); - err = ME_ERRNO_INVALID_SCAN_STOP_ARG; - goto ERROR; - } - break; - - default: - PERROR("Invalid scan stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; - goto ERROR; - break; - } - - switch (trigger->iAcqStopTrigType) { - - case ME_TRIG_TYPE_NONE: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_FOLLOW: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_COUNT) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - - if (trigger->iAcqStopCount <= 0) { - PERROR - ("Invalid acquisition or scan stop argument specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_ARG; - goto ERROR; - } - break; - - default: - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - break; - } - - if ((count <= 0) || (count > ME4600_AI_LIST_COUNT)) { - PERROR("Invalid channel list count specified.\n"); - err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT; - goto ERROR; - } -///This is general limitation -// if (fifo_irq_threshold < 0 || fifo_irq_threshold >= ME4600_AI_CIRC_BUF_COUNT) -///This is limitation from Windows. I use it for compatibility. - if (fifo_irq_threshold < 0 - || fifo_irq_threshold >= ME4600_AI_FIFO_COUNT) { - PERROR("Invalid fifo irq threshold specified.\n"); - err = ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD; - goto ERROR; - } - - if ((config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) - && (instance->channels == 16)) { - PERROR - ("Differential reference is not available on this subdevice.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { - if (!instance->sh) { - PERROR - ("Sample and hold is not available for this board.\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto ERROR; - } - if (config_list[0].iRef == ME_REF_AI_DIFFERENTIAL) { - PERROR - ("Sample and hold is not available in differential mode.\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto ERROR; - } - } - - for (i = 0; i < count; i++) { - if ((config_list[i].iStreamConfig < 0) - || (config_list[i].iStreamConfig >= instance->ranges_len)) { - PERROR("Invalid stream config specified.\n"); - err = ME_ERRNO_INVALID_STREAM_CONFIG; - goto ERROR; - } - - if ((config_list[i].iRef != ME_REF_AI_GROUND) - && (config_list[i].iRef != ME_REF_AI_DIFFERENTIAL)) { - PERROR("Invalid references in the list. Ref=0x%x\n", - config_list[i].iRef); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if (config_list[i].iStreamConfig % 2) { // StreamConfig: 1 or 3 - if (config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) { - PERROR - ("Only bipolar modes support differential measurement.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - } - - if (config_list[i].iRef != config_list[0].iRef) { - PERROR - ("Not all references in the configuration list are equal. Ref[0]=0x%x Ref[%d]=0x%x\n", - config_list[0].iRef, i, config_list[i].iRef); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if ((config_list[i].iRef == ME_REF_AI_DIFFERENTIAL) - && (config_list[i].iChannel >= 16)) { - PERROR("Channel not available in differential mode.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - - if ((config_list[i].iChannel < 0) - || (config_list[i].iChannel >= instance->channels)) { - PERROR("Invalid channel number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - } - - // Check settings - end - - //Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - // Work around from Keith Hartley - begin - if (trigger->iScanStartTrigType == ME_TRIG_TYPE_TIMER) { - if (count == 1) { - // The hardware does not work properly with a non-zero scan time - // if there is only ONE channel in the channel list. In this case - // we must set the scan time to zero and use the channel time. - - conv_ticks = scan_ticks; - trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; - } else if (scan_ticks == count * conv_ticks) { - // Another hardware problem. If the number of scan ticks is - // exactly equal to the number of channel ticks multiplied by - // the number of channels then the sampling rate is reduced - // by half. - trigger->iScanStartTrigType = ME_TRIG_TYPE_FOLLOW; - } - } - // Work around from Keith Hartley - end - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - if (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_SUBDEVICE_BUSY; - } - - instance->status = ai_status_none; - spin_lock(instance->ctrl_reg_lock); - // Stop all actions. Block all interrupts. Clear (disable) FIFOs. - ctrl = - ME4600_AI_CTRL_BIT_LE_IRQ_RESET | ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - - tmp = inl(instance->ctrl_reg); - // Preserve EXT IRQ and OFFSET settings. Clean other bits. - tmp &= - (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | - ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); - - // Send it to register. - outl(tmp | ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp | ctrl); - - // Enable channel fifo -> data fifo in stream_start(). - ctrl |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO; - outl(tmp | ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp | ctrl); - spin_unlock(instance->ctrl_reg_lock); - - // Write the channel list - for (i = 0; i < count; i++) { - entry = config_list[i].iChannel; - - switch (config_list[i].iStreamConfig) { - case 0: //BIPOLAR 10V -/* - // ME4600_AI_LIST_RANGE_BIPOLAR_10 = 0x0000 - // 'entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10' <== Do nothing. Removed. - entry |= ME4600_AI_LIST_RANGE_BIPOLAR_10; -*/ - break; - case 1: //UNIPOLAR 10V - entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_10; - break; - case 2: //BIPOLAR 2.5V - entry |= ME4600_AI_LIST_RANGE_BIPOLAR_2_5; - break; - case 3: //UNIPOLAR 2.5V - entry |= ME4600_AI_LIST_RANGE_UNIPOLAR_2_5; - break; - default: - PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); - PERROR_CRITICAL - ("WRONG range\nPosition:%d Range:0x%04X\n", i, - config_list[i].iStreamConfig); - goto VERIFY_ERROR; - break; - } - - switch (config_list[i].iRef) { - case ME_REF_AI_GROUND: //SINGLE ENDED -/* - // ME4600_AI_LIST_INPUT_SINGLE_ENDED = 0x0000 - // 'entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED' ==> Do nothing. Removed. - entry |= ME4600_AI_LIST_INPUT_SINGLE_ENDED; -*/ break; - case ME_REF_AI_DIFFERENTIAL: //DIFFERENTIAL - entry |= ME4600_AI_LIST_INPUT_DIFFERENTIAL; - break; - default: - PERROR_CRITICAL("UNCHECK ERROR in config_list!\n"); - PERROR_CRITICAL - ("WRONG reference\nPosition:%d Reference:0x%04X\n", - i, config_list[i].iRef); - goto VERIFY_ERROR; - break; - } - - //Add last entry flag - if (i == (count - 1)) { - entry |= ME4600_AI_LIST_LAST_ENTRY; - } - - outl(entry, instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - entry); - } - - // Set triggering registers - --acq_ticks; - outl(acq_ticks, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, - acq_ticks); - outl(acq_ticks, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, - acq_ticks & 0xFFFFFFFF); - outl((acq_ticks >> 32), instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, - (acq_ticks >> 32) & 0xFFFFFFFF); - - // Set triggers - switch (trigger->iAcqStartTrigType) { - // Internal - case ME_TRIG_TYPE_SW: - // Nothing to set. - break; - - // External - case ME_TRIG_TYPE_EXT_ANALOG: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_ANALOG; - case ME_TRIG_TYPE_EXT_DIGITAL: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG; - - // External trigger needs edge's definition - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - // Nothing to set. - break; - - case ME_TRIG_EDGE_FALLING: - ctrl |= ME4600_AI_CTRL_BIT_EX_TRIG_FALLING; - break; - - case ME_TRIG_EDGE_ANY: - ctrl |= - ME4600_AI_CTRL_BIT_EX_TRIG_FALLING | - ME4600_AI_CTRL_BIT_EX_TRIG_BOTH; - break; - - default: - PERROR_CRITICAL - ("UNCHECK TRIGGER EDGE in triggers structure!\n"); - PERROR_CRITICAL - ("WRONG acquisition start trigger:0x%04X.\n", - trigger->iAcqStartTrigEdge); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - goto VERIFY_ERROR; - break; - } - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG acquisition start trigger:0x%04X.\n", - trigger->iAcqStartTrigType); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - goto VERIFY_ERROR; - break; - } - - switch (trigger->iScanStartTrigType) { - case ME_TRIG_TYPE_TIMER: - --scan_ticks; - outl(scan_ticks, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - scan_ticks & 0xFFFFFFFF); - outl((scan_ticks >> 32), instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - (scan_ticks >> 32) & 0xFFFFFFFF); - - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { - ctrl |= ME4600_AI_CTRL_BIT_MODE_0; - } else { - ctrl |= ME4600_AI_CTRL_BIT_MODE_1; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - 0); - ctrl |= ME4600_AI_CTRL_BIT_MODE_2; - break; - - case ME_TRIG_TYPE_FOLLOW: - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, - 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, - 0); - - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { - ctrl |= ME4600_AI_CTRL_BIT_MODE_0; - } else { - ctrl |= ME4600_AI_CTRL_BIT_MODE_1; - } - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG scan start trigger:0x%04X.\n", - trigger->iScanStartTrigType); - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - goto VERIFY_ERROR; - break; - } - - switch (trigger->iConvStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - --conv_ticks; - outl(conv_ticks, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%llX\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, - conv_ticks); - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - case ME_TRIG_TYPE_EXT_ANALOG: - outl(0, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 0); - ctrl |= ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1; - break; - - default: - PERROR_CRITICAL("UNCHECK TRIGGER in triggers structure!\n"); - PERROR_CRITICAL("WRONG conv start trigger:0x%04X.\n", - trigger->iConvStartTrigType); - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - goto VERIFY_ERROR; - - break; - } - - //Sample & Hold feature - if (flags & ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD) { - if (instance->sh) { - ctrl |= ME4600_AI_CTRL_BIT_SAMPLE_HOLD; - } else { - PERROR_CRITICAL("UNCHECK S&H feature!\n"); - err = ME_ERRNO_INVALID_FLAGS; - goto VERIFY_ERROR; - } - } - //Enable IRQs sources but leave latches blocked. - ctrl |= (ME4600_AI_CTRL_BIT_HF_IRQ | ME4600_AI_CTRL_BIT_SC_IRQ | ME4600_AI_CTRL_BIT_LE_IRQ); //The last IRQ source (ME4600_AI_CTRL_BIT_LE_IRQ) is unused! - - //Everything is good. Finalize - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - - //Preserve EXT IRQ and OFFSET settings. Clean other bits. - tmp &= - (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET | - ME4600_AI_CTRL_BIT_FULLSCALE | ME4600_AI_CTRL_BIT_OFFSET); - - // write the control word - outl(ctrl | tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl | tmp); - spin_unlock(instance->ctrl_reg_lock); - - //Set the global parameters end exit. - instance->chan_list_len = count; - instance->fifo_irq_threshold = fifo_irq_threshold; - - if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { - data_required = - (unsigned long long)trigger->iAcqStopCount * - (unsigned long long)count; - if (data_required > UINT_MAX) - data_required = UINT_MAX; - instance->data_required = (unsigned int)data_required; - } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) - instance->data_required = - (unsigned long long)trigger->iScanStopCount; - else - instance->data_required = 0; - - // Mark subdevice as configured to work in stream mode. - instance->status = ai_status_stream_configured; - - // Deinit single config. Set all entries to NOT_CONFIGURED. - for (i = 0; i < instance->channels; i++) { - instance->single_config[i].status = - ME_SINGLE_CHANNEL_NOT_CONFIGURED; - } - -VERIFY_ERROR: // Error in code. Wrong setting check. This should never ever happend! - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); -ERROR: // Error in settings. - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long t; - unsigned long j; - int volatile head; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } else { // Max time. - t = LONG_MAX; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - j = jiffies; - - while (1) { - // Only runing device can generate break. - head = instance->circ_buf.head; - wait_event_interruptible_timeout(instance->wait_queue, - ((head != - instance->circ_buf.head) - || - ((instance->status <= - ai_status_stream_run_wait) - && (instance->status >= - ai_status_stream_end_wait))), - t); - - if (head != instance->circ_buf.head) { // New data in buffer. - break; - } else if (instance->status == ai_status_stream_end) { // End of work. - break; - } else if (instance->status == ai_status_stream_fifo_error) { - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - break; - } else if (instance->status == ai_status_stream_buffer_error) { - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - break; - } else if (instance->status == ai_status_stream_error) { - err = ME_ERRNO_INTERNAL; - break; - } else if ((jiffies - j) >= t) { - PERROR("Wait on values timed out.\n"); - err = ME_ERRNO_TIMEOUT; - break; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - break; - } - // Correct timeout. - t -= jiffies - j; - } - - *count = me_circ_buf_values(&instance->circ_buf); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static inline int me4600_ai_io_stream_read_get_value(me4600_ai_subdevice_t * - instance, int *values, - const int count, - const int flags) -{ - int n; - int i; - uint32_t value; - - ///Checking how many datas can be copied. - n = me_circ_buf_values(&instance->circ_buf); - if (n <= 0) - return 0; - - if (n > count) - n = count; - - if (flags & ME_IO_STREAM_READ_FRAMES) { - if (n < instance->chan_list_len) //Not enough data! - return 0; - n -= n % instance->chan_list_len; - } - - for (i = 0; i < n; i++) { - value = *(instance->circ_buf.buf + instance->circ_buf.tail); - if (put_user(value, values + i)) { - PERROR("Cannot copy new values to user.\n"); - return -ME_ERRNO_INTERNAL; - } - instance->circ_buf.tail++; - instance->circ_buf.tail &= instance->circ_buf.mask; - } - return n; -} - -static int me4600_ai_io_stream_read(me_subdevice_t *subdevice, - struct file *filep, - int read_mode, - int *values, int *count, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int ret; - - int c = *count; - int min = c; - - PDEBUG("executed. idx=0\n"); - - if (flags & ~ME_IO_STREAM_READ_FRAMES) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (!values || !count) { - PERROR("Request has invalid pointer.\n"); - return ME_ERRNO_INVALID_POINTER; - } - - if (c < 0) { - PERROR("Request has invalid value's counter.\n"); - return ME_ERRNO_INVALID_VALUE_COUNT; - } - - if ((read_mode != ME_READ_MODE_BLOCKING) - && (read_mode != ME_READ_MODE_NONBLOCKING)) { - PERROR("Invalid read mode specified.\n"); - return ME_ERRNO_INVALID_READ_MODE; - } - - if (c == 0) { //You get what you want! Nothing more or less. - return ME_ERRNO_SUCCESS; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - ME_SUBDEVICE_ENTER; - - //Check if subdevice is configured. - if (instance->chan_list_len <= 0) { - PERROR("Subdevice wasn't configured.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (flags & ME_IO_STREAM_READ_FRAMES) { - if (c < instance->chan_list_len) { //Not enough data requested. - PERROR - ("When using FRAME_READ mode minimal size is defined by channel list.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INVALID_VALUE_COUNT; - } - } - - if (c > (ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len)) { // To return acceptable amount of data when user pass too big value. - min = ME4600_AI_CIRC_BUF_COUNT - instance->chan_list_len; - } - - if (flags & ME_IO_STREAM_READ_FRAMES) { - //Wait for whole list. - if (read_mode == ME_READ_MODE_BLOCKING) { - min = c - (c % instance->chan_list_len); - } - - if (read_mode == ME_READ_MODE_NONBLOCKING) { - min = instance->chan_list_len; - } - } - - if ((inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { //Working - //If blocking mode -> wait for data. - if ((me_circ_buf_values(&instance->circ_buf) < min) - && (read_mode == ME_READ_MODE_BLOCKING)) { - wait_event_interruptible(instance->wait_queue, - ((me_circ_buf_values - (&instance->circ_buf) >= min) - || !(inl(instance->status_reg) - & - ME4600_AI_STATUS_BIT_FSM))); - - if (signal_pending(current)) { - PERROR - ("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - } - } - } - - ret = me4600_ai_io_stream_read_get_value(instance, values, c, flags); - if (ret < 0) { - err = -ret; - *count = 0; - } else if (ret == 0) { - *count = 0; - if (instance->status == ai_status_stream_fifo_error) { - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - instance->status = ai_status_stream_end; - } else if (instance->status == ai_status_stream_buffer_error) { - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - instance->status = ai_status_stream_end; - } else if (instance->status == ai_status_stream_end) { - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (instance->status == ai_status_stream_error) { - err = ME_ERRNO_INTERNAL; - } else if (instance->status == ai_status_none) { - PDEBUG("Stream canceled.\n"); - err = ME_ERRNO_INTERNAL; - } - } else { - *count = ret; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -/** @brief Stop aqusation. Preserve FIFOs. -* -* @param instance The subdevice instance (pointer). -*/ - -static int ai_stop_immediately(me4600_ai_subdevice_t *instance) -{ - unsigned long cpu_flags = 0; - volatile uint32_t ctrl; - const int timeout = HZ / 10; //100ms - int i; - - for (i = 0; i <= timeout; i++) { - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AI_CTRL_BIT_STOP; - ctrl |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - if (!(inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM)) { // Exit. - break; - } - - PINFO("Wait for stop: %d\n", i + 1); - //Still working! - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - return ME_ERRNO_INTERNAL; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags = 0; - unsigned long ref; - unsigned long delay = 0; - - volatile uint32_t tmp; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((start_mode != ME_START_MODE_BLOCKING) - && (start_mode != ME_START_MODE_NONBLOCKING)) { - PERROR("Invalid start mode specified.\n"); - return ME_ERRNO_INVALID_START_MODE; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - - tmp = inl(instance->ctrl_reg); - - if ((tmp & ME4600_AI_STATUS_BIT_FSM)) { - PERROR("Conversion is already running.\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - if (instance->chan_list_len == 0) { //Not configured! - PERROR("Subdevice is not configured to work in stream mode!\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - - if (!(tmp & (ME4600_AI_CTRL_BIT_MODE_0 | ME4600_AI_CTRL_BIT_MODE_1 | ME4600_AI_CTRL_BIT_MODE_2))) { //Mode 0 = single work => no stream config - PERROR("Subdevice is configured to work in single mode.\n"); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - //Reset stop bits. - tmp |= ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - //Start datas' FIFO. - tmp |= ME4600_AI_CTRL_BIT_DATA_FIFO; - //Free stop bits. - tmp &= ~(ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_STOP); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - //Cancel control task - PDEBUG("Cancel control task.\n"); - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - - //Set the starting values. - instance->ISM.global_read = 0; - instance->ISM.read = 0; - //Clear circular buffer - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - //Set everything. - ai_data_acquisition_logic(instance); - - //Set status to 'wait for start' - instance->status = ai_status_stream_run_wait; - - // Set control task's timeout - instance->timeout.delay = delay; - instance->timeout.start_time = jiffies; - - //Lets go! Start work - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - - // Schedule control task - instance->ai_control_task_flag = 1; - queue_delayed_work(instance->me4600_workqueue, - &instance->ai_control_task, 1); - - PDEVELOP("Delay:%ld\n", delay); - - if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. - ref = jiffies; - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ai_status_stream_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if ((instance->status != ai_status_stream_run) - && (instance->status != ai_status_stream_end)) { - PDEBUG("Starting stream canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ai_status_none; - ai_stop_isr(instance); - err = ME_ERRNO_SIGNAL; - } else if ((delay) && ((jiffies - ref) > delay)) { - if (instance->status != ai_status_stream_run) { - if (instance->status == ai_status_stream_end) { - PDEBUG("Timeout reached.\n"); - } else if ((jiffies - ref) > delay + 1) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - ai_stop_isr(instance); - instance->status = - ai_status_stream_error; - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - ai_stop_isr(instance); - instance->status = - ai_status_stream_error; - } - - instance->ai_control_task_flag = 0; - cancel_delayed_work(&instance->ai_control_task); - err = ME_ERRNO_TIMEOUT; - } - } - } -#ifdef MEDEBUG_INFO - tmp = inl(instance->ctrl_reg); - PDEBUG_REG("ctrl_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - PINFO("STATUS_BIT_FSM=%s.\n", - (tmp & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - PINFO("CTRL_BIT_HF_IRQ=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (tmp & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : "work"); -#endif - -ERROR: - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - switch (instance->status) { - case ai_status_single_configured: - case ai_status_stream_configured: - case ai_status_stream_end: - case ai_status_stream_fifo_error: - case ai_status_stream_buffer_error: - case ai_status_stream_error: - *status = ME_STATUS_IDLE; - break; - - case ai_status_stream_run_wait: - case ai_status_stream_run: - case ai_status_stream_end_wait: - *status = ME_STATUS_BUSY; - break; - - case ai_status_none: - default: - *status = - (inl(instance->status_reg) & ME4600_AI_STATUS_BIT_FSM) ? - ME_STATUS_BUSY : ME_STATUS_IDLE; - break; - } - - if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { - // Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - ((instance->status != - ai_status_stream_run_wait) - && (instance->status != - ai_status_stream_run) - && (instance->status != - ai_status_stream_end_wait)), - LONG_MAX); - - if (instance->status != ai_status_stream_end) { - PDEBUG("Wait for IDLE canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait for IDLE interrupted.\n"); - instance->status = ai_status_none; - ai_stop_isr(instance); - err = ME_ERRNO_SIGNAL; - } - - *status = ME_STATUS_IDLE; - } - - *values = me_circ_buf_values(&instance->circ_buf); - PDEBUG("me_circ_buf_values(&instance->circ_buf)=%d.\n", *values); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ai_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags) -{ -/** - @note Stop is implemented only in blocking mode. - @note Function return when state machine is stoped. -*/ - me4600_ai_subdevice_t *instance; - unsigned long cpu_flags; - uint32_t ctrl; - int ret; - - PDEBUG("executed. idx=0\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((stop_mode != ME_STOP_MODE_IMMEDIATE) - && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { - PERROR("Invalid stop mode specified.\n"); - return ME_ERRNO_INVALID_STOP_MODE; - } - - instance = (me4600_ai_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - // Mark as stopping. => Software stop. - instance->status = ai_status_stream_end_wait; - - if (stop_mode == ME_STOP_MODE_IMMEDIATE) { - ret = ai_stop_immediately(instance); - - if (ret) { - PERROR("FSM is still busy.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_SUBDEVICE_BUSY; - } - instance->ai_control_task_flag = 0; - - } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { - // Set stop bit in registry. - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME4600_AI_CTRL_BIT_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - - // Only runing process will interrupt this call. Events are signaled when status change. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ai_status_stream_end_wait), - LONG_MAX); - - if (instance->status != ai_status_stream_end) { - PDEBUG("Stopping stream canceled.\n"); - ret = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Stopping stream interrupted.\n"); - instance->status = ai_status_none; - ret = ME_ERRNO_SIGNAL; - } - // End of work. - ai_stop_immediately(instance); - - } - - ret = ai_read_data_pooling(instance); - if (ret > 0) { // Everything fine. More datas put to software buffer. - instance->status = ai_status_stream_end; - ret = ME_ERRNO_SUCCESS; - // Signal that we put last data to software buffer. - wake_up_interruptible_all(&instance->wait_queue); - } else if (ret == 0) { // Everything fine. No more datas in FIFO. - instance->status = ai_status_stream_end; - ret = ME_ERRNO_SUCCESS; - } else if (ret == -ME_ERRNO_RING_BUFFER_OVERFLOW) { // Stop is unsuccessful, buffer is overflow. - instance->status = ai_status_stream_buffer_error; - ret = ME_ERRNO_SUCCESS; - } else { // Stop is unsuccessful - instance->status = ai_status_stream_end; - ret = -ret; - } - - ME_SUBDEVICE_EXIT; - - return ret; -} - -static int me4600_ai_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - me4600_ai_subdevice_t *instance; - int i; - int r = -1; - int diff = 21E6; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((*max - *min) < 0) { - PERROR("Invalid minimum and maximum values specified.\n"); - return ME_ERRNO_INVALID_MIN_MAX; - } - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - for (i = 0; i < instance->ranges_len; i++) { - if ((instance->ranges[i].min <= *min) - && ((instance->ranges[i].max + 1000) >= *max)) { - if ((instance->ranges[i].max - - instance->ranges[i].min) - (*max - *min) < - diff) { - r = i; - diff = - (instance->ranges[i].max - - instance->ranges[i].min) - (*max - - *min); - } - } - } - - if (r < 0) { - PERROR("No matching range found.\n"); - return ME_ERRNO_NO_RANGE; - } else { - *min = instance->ranges[r].min; - *max = instance->ranges[r].max; - *maxdata = ME4600_AI_MAX_DATA; - *range = r; - } - } else { - PERROR("Invalid physical unit specified.\n"); - return ME_ERRNO_INVALID_UNIT; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - *count = instance->ranges_len; - } else { - *count = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - if ((range < instance->ranges_len) && (range >= 0)) { - *unit = ME_UNIT_VOLT; - *min = instance->ranges[range].min; - *max = instance->ranges[range].max; - *maxdata = ME4600_AI_MAX_DATA; - } else { - PERROR("Invalid range number specified.\n"); - return ME_ERRNO_INVALID_RANGE; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - - switch (timer) { - - case ME_TIMER_ACQ_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_ACQ_TICKS; - *max_ticks = ME4600_AI_MAX_ACQ_TICKS; - break; - - case ME_TIMER_SCAN_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_SCAN_TICKS; - *max_ticks = ME4600_AI_MAX_SCAN_TICKS; - break; - - case ME_TIMER_CONV_START: - *base_frequency = ME4600_AI_BASE_FREQUENCY; - *min_ticks = ME4600_AI_MIN_CHAN_TICKS; - *max_ticks = ME4600_AI_MAX_CHAN_TICKS; - break; - - default: - PERROR("Invalid timer specified.(0x%04x)\n", timer); - - return ME_ERRNO_INVALID_TIMER; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - me4600_ai_subdevice_t *instance; - - PDEBUG("executed. idx=0\n"); - - instance = (me4600_ai_subdevice_t *) subdevice; - *number = instance->channels; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed. idx=0\n"); - - *type = ME_TYPE_AI; - *subtype = ME_SUBTYPE_STREAMING; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed. idx=0\n"); - - *caps = - ME_CAPS_AI_TRIG_SYNCHRONOUS | ME_CAPS_AI_FIFO | - ME_CAPS_AI_FIFO_THRESHOLD; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ai_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count) -{ - me4600_ai_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me4600_ai_subdevice_t *) subdevice; - - PDEBUG("executed. idx=0\n"); - - if (count != 1) { - PERROR("Invalid capability argument count.\n"); - return ME_ERRNO_INVALID_CAP_ARG_COUNT; - } - - switch (cap) { - case ME_CAP_AI_FIFO_SIZE: - args[0] = ME4600_AI_FIFO_COUNT; - break; - - case ME_CAP_AI_BUFFER_SIZE: - args[0] = - (instance->circ_buf.buf) ? ME4600_AI_CIRC_BUF_COUNT : 0; - break; - - default: - PERROR("Invalid capability.\n"); - err = ME_ERRNO_INVALID_CAP; - args[0] = 0; - } - - return err; -} - -void ai_limited_isr(me4600_ai_subdevice_t *instance, const uint32_t irq_status, - const uint32_t ctrl_status) -{ - int to_read; - - if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. HF need reseting. - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - if (ai_read_data(instance, instance->ISM.next) != instance->ISM.next) { //ERROR! - PERROR - ("Limited amounts aqusition with TH=0: Circular buffer full!\n"); - instance->status = - ai_status_stream_buffer_error; - } else { - instance->status = ai_status_stream_end; - } - //End of work. - ai_stop_isr(instance); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - instance->ISM.global_read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR - ("Limited amounts aqusition with TH = 0: Circular buffer full!\n"); - //End of work. - ai_stop_isr(instance); - instance->status = - ai_status_stream_buffer_error; - } else { - //Continue. - ai_limited_ISM(instance, irq_status); - } - } - //Signal user. - wake_up_interruptible_all(&instance->wait_queue); - } else //if(instance->fifo_irq_threshold) - { - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - instance->ISM.read = 0; - if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) - && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) - { - to_read = - ME4600_AI_FIFO_HALF - - (ME4600_AI_FIFO_HALF % - instance->fifo_irq_threshold); - PDEBUG - ("Limited amounts aqusition with TH != 0: Not fast enough data aqusition! correction=%d\n", - to_read); - } else { - to_read = instance->ISM.next; - } - instance->ISM.global_read += to_read; - - ai_reschedule_SC(instance); - - if (ai_read_data(instance, to_read) != to_read) { //ERROR! - PERROR - ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); - //End of work. - ai_stop_isr(instance); - instance->status = - ai_status_stream_buffer_error; - } else { - //Continue. - ai_limited_ISM(instance, irq_status); - } - - //Signal user. - wake_up_interruptible_all(&instance->wait_queue); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - instance->ISM.read += ME4600_AI_FIFO_HALF; - instance->ISM.global_read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR - ("Limited amounts aqusition with TH != 0: Circular buffer full!\n"); - ai_stop_isr(instance); - - instance->status = - ai_status_stream_buffer_error; - //Signal user. - wake_up_interruptible_all(&instance-> - wait_queue); - } else { - //Countinue. - ai_limited_ISM(instance, irq_status); - } - } - - if (instance->ISM.global_read >= instance->data_required) { //End of work. Next paranoid pice of code: '>=' instead od '==' only to be sure. - ai_stop_isr(instance); - if (instance->status < ai_status_stream_end) { - instance->status = ai_status_stream_end; - } -#ifdef MEDEBUG_ERROR - if (instance->ISM.global_read > instance->data_required) { //This is security check case. This should never ever happend! - PERROR - ("Limited amounts aqusition: Read more data than necessary! data_required=%d < read=%d\n", - instance->data_required, - instance->ISM.global_read); - //Signal error (warning??). - instance->status = ai_status_stream_error; - } -#endif - } - } -} - -void ai_infinite_isr(me4600_ai_subdevice_t *instance, - const uint32_t irq_status, const uint32_t ctrl_status) -{ - int to_read; - - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { //next chunck of data -> read fifo - //Set new state in ISM. - if ((instance->fifo_irq_threshold < ME4600_AI_FIFO_HALF) && (!(ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA))) { //There is more data than we ecpected. Propably we aren't fast enough. Read as many as possible. - if (instance->fifo_irq_threshold) { - to_read = - ME4600_AI_FIFO_HALF - - (ME4600_AI_FIFO_HALF % - instance->fifo_irq_threshold); - if (to_read > instance->fifo_irq_threshold) { - PDEBUG - ("Infinite aqusition: Not fast enough data aqusition! TH != 0: correction=%d\n", - to_read); - } - } else { //No threshold specified. - to_read = ME4600_AI_FIFO_HALF; - } - } else { - to_read = instance->ISM.next; - } - - instance->ISM.read += to_read; - - //Get data - if (ai_read_data(instance, to_read) != to_read) { //ERROR! - PERROR("Infinite aqusition: Circular buffer full!\n"); - ai_stop_isr(instance); - instance->status = ai_status_stream_buffer_error; - } else { - ai_infinite_ISM(instance); - instance->ISM.global_read += instance->ISM.read; - instance->ISM.read = 0; - } - - //Signal data to user - wake_up_interruptible_all(&instance->wait_queue); - } else if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { //fifo is half full -> read fifo Large blocks only! - instance->ISM.read += ME4600_AI_FIFO_HALF; - - if (ai_read_data(instance, ME4600_AI_FIFO_HALF) != ME4600_AI_FIFO_HALF) { //ERROR! - PERROR("Infinite aqusition: Circular buffer full!\n"); - ai_stop_isr(instance); - instance->status = ai_status_stream_buffer_error; - - //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } else { - ai_infinite_ISM(instance); - } - } -} - -static irqreturn_t me4600_ai_isr(int irq, void *dev_id) -{ /// @note This is time critical function! - uint32_t irq_status; - uint32_t ctrl_status; - me4600_ai_subdevice_t *instance = dev_id; - //int to_read; - - PDEBUG("executed. idx=0\n"); - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inl(instance->irq_status_reg); - if (! - (irq_status & - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC))) { -#ifdef MEDEBUG_INFO - if ((irq_status & (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC | ME4600_IRQ_STATUS_BIT_LE)) == ME4600_IRQ_STATUS_BIT_LE) { //This is security check case. LE is unused. This should never ever happend. - PINFO - ("%ld Shared interrupt. %s(): irq_status_reg=LE_IRQ\n", - jiffies, __func__); - } else { - PINFO - ("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", - jiffies, __func__, irq_status); - } -#endif - return IRQ_NONE; - } - - if (!instance->circ_buf.buf) { //Security check. - PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); - ai_stop_isr(instance); - return IRQ_HANDLED; - } - //Get the status register. - ctrl_status = inl(instance->status_reg); - -#ifdef MEDEBUG_INFO - if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) - PINFO("HF interrupt active\n"); - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) - PINFO("SC interrupt active\n"); - if (irq_status & ME4600_IRQ_STATUS_BIT_LE) - PINFO("LE interrupt active\n"); -#endif - - //This is safety check! - if ((irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) - && (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA)) { - PDEBUG("HF interrupt active but FIFO under half\n"); - //Reset HF interrupt latch. - spin_lock(instance->ctrl_reg_lock); - outl(ctrl_status | ME4600_AI_CTRL_BIT_HF_IRQ_RESET, - instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl_status); - outl(ctrl_status, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl_status); - spin_unlock(instance->ctrl_reg_lock); - return IRQ_HANDLED; - } -#ifdef MEDEBUG_INFO - PINFO("STATUS_BIT_FSM=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - - PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : - " > HF"); - PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : - "full"); - - PINFO("STATUS_BIT_EF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); - PINFO("STATUS_BIT_FF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : - "full"); - - PINFO("CTRL_BIT_HF_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : - "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : - "work"); -#endif - - //Look for overflow error. - if (!(ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA)) { - //FIFO is full. Read datas and reset all settings. - PERROR("FIFO overflow.\n"); - ai_read_data(instance, ME4600_AI_FIFO_COUNT); - ai_stop_isr(instance); - - instance->status = ai_status_stream_fifo_error; - //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; - } - - if (!instance->data_required) { //This is infinite aqusition. -#ifdef MEDEBUG_ERROR - if ((irq_status & - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) - == - (ME4600_IRQ_STATUS_BIT_AI_HF | ME4600_IRQ_STATUS_BIT_SC)) { - ///In infinite mode only one interrupt source should be reported! - PERROR - ("Error in ISM! Infinite aqusition: HF and SC interrupts active! threshold=%d next=%d ctrl=0x%04X irq_status_reg=0x%04X", - instance->fifo_irq_threshold, instance->ISM.next, - ctrl_status, irq_status); - } -#endif - - ai_infinite_isr(instance, irq_status, ctrl_status); - -#ifdef MEDEBUG_INFO - ctrl_status = inl(instance->ctrl_reg); -#endif - } else { - - ai_limited_isr(instance, irq_status, ctrl_status); - ctrl_status = inl(instance->status_reg); - if (!(ctrl_status & (ME4600_AI_STATUS_BIT_HF_DATA | ME4600_AI_CTRL_BIT_HF_IRQ_RESET))) { //HF active, but we have more than half already => HF will never come - PDEBUG - ("MISSED HF. data_required=%d ISM.read=%d ISM.global=%d ISM.next=%d\n", - instance->data_required, instance->ISM.read, - instance->ISM.global_read, instance->ISM.next); - ai_limited_isr(instance, ME4600_IRQ_STATUS_BIT_AI_HF, - ctrl_status); - } - } - -#ifdef MEDEBUG_INFO - PINFO("STATUS_BIT_FSM=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FSM) ? "on" : "off"); - - PINFO("STATUS_BIT_EF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_CHANNEL) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_CHANNEL) ? " < HF" : - " > HF"); - PINFO("STATUS_BIT_FF_CHANNEL=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_CHANNEL) ? "not full" : - "full"); - - PINFO("STATUS_BIT_EF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_EF_DATA) ? "not empty" : - "empty"); - PINFO("STATUS_BIT_HF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_HF_DATA) ? " < HF" : " > HF"); - PINFO("STATUS_BIT_FF_DATA=%s.\n", - (ctrl_status & ME4600_AI_STATUS_BIT_FF_DATA) ? "not full" : - "full"); - - PINFO("CTRL_BIT_HF_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_HF_IRQ_RESET) ? "reset" : - "work"); - PINFO("CTRL_BIT_SC_IRQ=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ) ? "enable" : "disable"); - PINFO("CTRL_BIT_SC_RELOAD=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_RELOAD) ? "on" : "off"); - PINFO("CTRL_BIT_SC_IRQ_RESET=%s.\n", - (ctrl_status & ME4600_AI_CTRL_BIT_SC_IRQ_RESET) ? "reset" : - "work"); - PINFO("%ld END\n", jiffies); -#endif - - return IRQ_HANDLED; -} - -/** @brief Stop aqusation of data. Reset interrupts' laches. Clear data's FIFO. -* -* @param instance The subdevice instance (pointer). -*/ -inline void ai_stop_isr(me4600_ai_subdevice_t *instance) -{ /// @note This is soft time critical function! - register uint32_t tmp; - - spin_lock(instance->ctrl_reg_lock); - //Stop all. Reset interrupt laches. Reset data FIFO. - tmp = inl(instance->ctrl_reg); - tmp |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | ME4600_AI_CTRL_BIT_HF_IRQ_RESET - | ME4600_AI_CTRL_BIT_LE_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - tmp &= ~ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); -} - -/** @brief Copy data from fifo to circular buffer. -* -* @param instance The subdevice instance (pointer). -* @param count The number of requested data. -* -* @return On success: Number of copied values. -* @return On error: -ME_ERRNO_RING_BUFFER_OVERFLOW. -*/ -static inline int ai_read_data(me4600_ai_subdevice_t *instance, - const int count) -{ /// @note This is time critical function! - int c = count; - int empty_space; - int copied = 0; - int i, j; - - empty_space = me_circ_buf_space_to_end(&instance->circ_buf); - if (empty_space <= 0) { - PDEBUG("Circular buffer full.\n"); - return -ME_ERRNO_RING_BUFFER_OVERFLOW; - } - - if (empty_space < c) { //Copy first part. Max to end of buffer. - PDEBUG - ("Try to copy %d values from FIFO to circular buffer (pass 1).\n", - empty_space); - for (i = 0; i < empty_space; i++) { - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - } - instance->circ_buf.head &= instance->circ_buf.mask; - c -= empty_space; - copied = empty_space; - - empty_space = me_circ_buf_space_to_end(&instance->circ_buf); - } - - if (empty_space > 0) { - j = (empty_space < c) ? empty_space : c; - PDEBUG - ("Try to copy %d values from FIFO to circular buffer (pass 2).\n", - c); - for (i = 0; i < j; i++) { - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - } - instance->circ_buf.head &= instance->circ_buf.mask; - copied += j; - } - return copied; -} - -inline void ai_infinite_ISM(me4600_ai_subdevice_t *instance) -{ /// @note This is time critical function! - register volatile uint32_t ctrl_set, ctrl_reset, tmp; - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { // Only sample counter with reloadnig is working. Reset it. - PINFO - ("Only sample counter with reloadnig is working. Reset it.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - ctrl_reset = ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - } else if (instance->fifo_irq_threshold == instance->ISM.read) { //This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning. - PINFO - ("This is SC interrupt for large block. The whole section is done. Reset SC_IRQ an HF_IRQ and start everything again from beginning.\n"); - ctrl_set = - ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - } else if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF. - PINFO - ("This is HF interrupt for large block.The next interrupt should be from HF, also. Reset HF.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } else { //This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF! - PINFO - ("This is HF interrupt for large block.The next interrupt should be from SC. Don't reset HF!\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - ctrl_reset = 0xFFFFFFFF; - } - - //Reset interrupt latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - PINFO("ctrl=0x%x ctrl_set=0x%x ctrl_reset=0x%x\n", tmp, ctrl_set, - ctrl_reset); - tmp |= ctrl_set; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - if (ctrl_reset != 0xFFFFFFFF) { - outl(tmp & ctrl_reset, instance->ctrl_reg); - PDEBUG_REG("ctrl_reset outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp & ctrl_reset); - } - spin_unlock(instance->ctrl_reg_lock); - -} - -inline void ai_limited_ISM(me4600_ai_subdevice_t *instance, - uint32_t irq_status) -{ /// @note This is time critical function! - register volatile uint32_t ctrl_set, ctrl_reset = 0xFFFFFFFF, tmp; - - if (!instance->fifo_irq_threshold) { //No threshold provided. SC ends work. - PINFO("No threshold provided. SC ends work.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - if (instance->data_required > (ME4600_AI_FIFO_COUNT - 1 + instance->ISM.global_read)) { //HF need reseting. - ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } else //if(instance->fifo_irq_threshold) - { - if (irq_status & ME4600_IRQ_STATUS_BIT_AI_HF) { - PINFO("Threshold provided. Clear HF latch.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - - if (instance->fifo_irq_threshold >= (ME4600_AI_FIFO_MAX_SC + instance->ISM.read)) { //This is not the last one. HF need reseting. - PINFO - ("The next interrupt is HF. HF need be activating.\n"); - ctrl_reset = ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } - - if (irq_status & ME4600_IRQ_STATUS_BIT_SC) { - PINFO("Threshold provided. Restart SC.\n"); - ctrl_set = ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - ctrl_reset &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - - if (instance->fifo_irq_threshold >= ME4600_AI_FIFO_MAX_SC) { //This is not the last one. HF need to be activating. - PINFO - ("The next interrupt is HF. HF need to be activating.\n"); - ctrl_reset &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - } - } - } - - //Reset interrupt latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ctrl_set; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - if (ctrl_reset != 0xFFFFFFFF) { - outl(tmp & ctrl_reset, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp & ctrl_reset); - } - spin_unlock(instance->ctrl_reg_lock); - -} - -/** @brief Last chunck of datas. We must reschedule sample counter. -* @note Last chunck. -* Leaving SC_RELOAD doesn't do any harm, but in some bad case can make extra interrupts. -* @warning When threshold is wrongly set some IRQ are lost.(!!!) -*/ -inline void ai_reschedule_SC(me4600_ai_subdevice_t *instance) -{ - register uint32_t rest; - - if (instance->data_required <= instance->ISM.global_read) - return; - - rest = instance->data_required - instance->ISM.global_read; - if (rest < instance->fifo_irq_threshold) { //End of work soon .... - PDEBUG("Rescheduling SC from %d to %d.\n", - instance->fifo_irq_threshold, rest); - /// @note Write new value to SC <== DANGER! This is not safe solution! We can miss some inputs. - outl(rest, instance->sample_counter_reg); - PDEBUG_REG("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - rest); - instance->fifo_irq_threshold = rest; - - if (rest < ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next = rest; - } else { - instance->ISM.next = rest % ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += ME4600_AI_FIFO_HALF; - } - } - } -} - -/** Start the ISM. All must be reseted before enter to this function. */ -inline void ai_data_acquisition_logic(me4600_ai_subdevice_t *instance) -{ - register uint32_t tmp; - - if (!instance->data_required) { //This is infinite aqusition. - if (!instance->fifo_irq_threshold) { //No threshold provided. Set SC to 0.5*FIFO. Clear the SC's latch. - //Set the sample counter - outl(ME4600_AI_FIFO_HALF, instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - ME4600_AI_FIFO_HALF); - } else { //Threshold provided. Set SC to treshold. Clear the SC's latch. - //Set the sample counter - outl(instance->fifo_irq_threshold, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->fifo_irq_threshold); - } - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //Enable only sample counter's interrupt. Set reload bit. Clear the SC's latch. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - if (!instance->fifo_irq_threshold) { //No threshold provided. Set ISM.next to 0.5*FIFO. - instance->ISM.next = ME4600_AI_FIFO_HALF; - } else { //Threshold provided. Set ISM.next to treshold. - instance->ISM.next = - instance->fifo_irq_threshold; - } - } else { //Enable sample counter's and HF's interrupts. - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - - instance->ISM.next = - instance->fifo_irq_threshold % ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += ME4600_AI_FIFO_HALF; - } - } - } else { //This aqusition is limited to set number of data. - if (instance->fifo_irq_threshold >= instance->data_required) { //Stupid situation. - instance->fifo_irq_threshold = 0; - PDEBUG - ("Stupid situation: data_required(%d) < threshold(%d).\n", - instance->fifo_irq_threshold, - instance->data_required); - } - - if (!instance->fifo_irq_threshold) { //No threshold provided. Easy case: HF=read and SC=end. - //Set the sample counter to data_required. - outl(instance->data_required, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->data_required); - - //Reset the latches of sample counter and HF (if SC>FIFO). - //No SC reload! - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_RELOAD); - if (instance->data_required > - (ME4600_AI_FIFO_COUNT - 1)) { - tmp &= ~ME4600_AI_CTRL_BIT_HF_IRQ_RESET; - instance->ISM.next = - instance->data_required % - ME4600_AI_FIFO_HALF; - instance->ISM.next += ME4600_AI_FIFO_HALF; - - } else { - instance->ISM.next = instance->data_required; - } - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - - } else { //The most general case. We have concret numbe of required data and threshold. SC=TH - //Set the sample counter to threshold. - outl(instance->fifo_irq_threshold, - instance->sample_counter_reg); - PDEBUG_REG - ("sample_counter_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->sample_counter_reg - instance->reg_base, - instance->fifo_irq_threshold); - - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - //In this moment we are sure that SC will come more than once. - tmp |= ME4600_AI_CTRL_BIT_SC_RELOAD; - - if (instance->fifo_irq_threshold < ME4600_AI_FIFO_MAX_SC) { //The threshold is so small that we do need HF. - tmp &= ~ME4600_AI_CTRL_BIT_SC_IRQ_RESET; - instance->ISM.next = - instance->fifo_irq_threshold; - } else { //The threshold is large. The HF must be use. - tmp &= - ~(ME4600_AI_CTRL_BIT_SC_IRQ_RESET | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET); - instance->ISM.next = - instance->fifo_irq_threshold % - ME4600_AI_FIFO_HALF; - if (instance->ISM.next + ME4600_AI_FIFO_HALF < - ME4600_AI_FIFO_MAX_SC) { - instance->ISM.next += - ME4600_AI_FIFO_HALF; - } - } - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - tmp); - spin_unlock(instance->ctrl_reg_lock); - } - } -} - -static int ai_mux_toggler(me4600_ai_subdevice_t *instance) -{ - uint32_t tmp; - - PDEBUG("executed. idx=0\n"); - - outl(0, instance->scan_pre_timer_low_reg); - PDEBUG_REG("scan_pre_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_pre_timer_high_reg); - PDEBUG_REG("scan_pre_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_pre_timer_high_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_low_reg); - PDEBUG_REG("scan_timer_low_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_low_reg - instance->reg_base, 0); - outl(0, instance->scan_timer_high_reg); - PDEBUG_REG("scan_timer_high_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->scan_timer_high_reg - instance->reg_base, 0); - outl(65, instance->chan_timer_reg); - PDEBUG_REG("chan_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_timer_reg - instance->reg_base, 65); - outl(65, instance->chan_pre_timer_reg); - PDEBUG_REG("chan_pre_timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->chan_pre_timer_reg - instance->reg_base, 65); - - // Turn on internal reference. - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AI_CTRL_BIT_FULLSCALE; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Clear data and channel fifo. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Write channel entry. - outl(ME4600_AI_LIST_INPUT_DIFFERENTIAL | - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31, - instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - ME4600_AI_LIST_INPUT_DIFFERENTIAL | - ME4600_AI_LIST_RANGE_UNIPOLAR_2_5 | 31); - - // Start conversion. - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - udelay(10); - - // Clear data and channel fifo. - tmp &= - ~(ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - tmp |= ME4600_AI_CTRL_BIT_CHANNEL_FIFO | ME4600_AI_CTRL_BIT_DATA_FIFO; - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - // Write channel entry. - // ME4600_AI_LIST_INPUT_SINGLE_ENDED | ME4600_AI_LIST_RANGE_BIPOLAR_10 <= 0x0000 - outl(ME4600_AI_LIST_INPUT_SINGLE_ENDED | - ME4600_AI_LIST_RANGE_BIPOLAR_10, instance->channel_list_reg); - PDEBUG_REG("channel_list_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->channel_list_reg - instance->reg_base, - ME4600_AI_LIST_INPUT_SINGLE_ENDED | - ME4600_AI_LIST_RANGE_BIPOLAR_10); - - // Start conversion. - inl(instance->start_reg); - PDEBUG_REG("start_reg inl(0x%lX+0x%lX)\n", instance->reg_base, - instance->start_reg - instance->reg_base); - udelay(10); - - // Clear control register. - tmp &= (ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - - return ME_ERRNO_SUCCESS; -} - -/** @brief Copy rest of data from fifo to circular buffer. -* @note Helper for STOP command. After FSM is stopped. -* @note This is slow function that copy all remainig data from FIFO to buffer. -* -* @param instance The subdevice instance (pointer). -* -* @return On success: Number of copied values. -* @return On error: Negative error code -ME_ERRNO_RING_BUFFER_OVERFLOW. -*/ -static inline int ai_read_data_pooling(me4600_ai_subdevice_t *instance) -{ /// @note This is time critical function! - int empty_space; - int copied = 0; - int status = ME_ERRNO_SUCCESS; - - PDEBUG("Space left in circular buffer = %d.\n", - me_circ_buf_space(&instance->circ_buf)); - - while ((empty_space = me_circ_buf_space(&instance->circ_buf))) { - if (!(status = inl(instance->status_reg) & ME4600_AI_STATUS_BIT_EF_DATA)) { //No more data. status = ME_ERRNO_SUCCESS = 0 - break; - } - *(instance->circ_buf.buf + instance->circ_buf.head) = - (inw(instance->data_reg) ^ 0x8000); - instance->circ_buf.head++; - instance->circ_buf.head &= instance->circ_buf.mask; - } - -#ifdef MEDEBUG_ERROR - if (!status) - PDEBUG - ("Copied all remaining datas (%d) from FIFO to circular buffer.\n", - copied); - else { - PDEBUG("No more empty space in buffer.\n"); - PDEBUG("Copied %d datas from FIFO to circular buffer.\n", - copied); - PDEBUG("FIFO still not empty.\n"); - } -#endif - return (!status) ? copied : -ME_ERRNO_RING_BUFFER_OVERFLOW; -} - -static void me4600_ai_work_control_task(struct work_struct *work) -{ - me4600_ai_subdevice_t *instance; - uint32_t status; - uint32_t ctrl; - unsigned long cpu_flags = 0; - int reschedule = 0; - int signaling = 0; - - instance = - container_of((void *)work, me4600_ai_subdevice_t, ai_control_task); - PINFO("<%s: %ld> executed.\n", __func__, jiffies); - - status = inl(instance->status_reg); - PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->status_reg - instance->reg_base, status); - - switch (instance->status) { // Checking actual mode. - // Not configured for work. - case ai_status_none: - break; - - //This are stable modes. No need to do anything. (?) - case ai_status_single_configured: - case ai_status_stream_configured: - case ai_status_stream_fifo_error: - case ai_status_stream_buffer_error: - case ai_status_stream_error: - PERROR("Shouldn't be running!.\n"); - break; - - // Stream modes - case ai_status_stream_run_wait: - if (status & ME4600_AI_STATUS_BIT_FSM) { // ISM started.. - instance->status = ai_status_stream_run; - // Signal the end of wait for start. - signaling = 1; - // Wait now for stop. - reschedule = 1; - break; - - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts. Reset FIFO => Too late! - ai_stop_isr(instance); - - instance->status = ai_status_stream_end; - - // Signal the end. - signaling = 1; - } - } - break; - - case ai_status_stream_run: - // Wait for stop ISM. - reschedule = 1; - break; - - case ai_status_stream_end_wait: - if (!(status & ME4600_AI_STATUS_BIT_FSM)) { // ISM stoped. Overwrite ISR. - instance->status = ai_status_stream_end; - // Signal the end of wait for stop. - signaling = 1; - } else { - // Wait for stop ISM. - reschedule = 1; - } - break; - - case ai_status_stream_end: - //End work. - if (status & ME4600_AI_STATUS_BIT_FSM) { // Still working? Stop it! - PERROR - ("Status is 'ai_status_stream_end' but hardware is still working!\n"); - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - (ME4600_AI_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AI_CTRL_BIT_HF_IRQ_RESET | - ME4600_AI_CTRL_BIT_SC_IRQ_RESET); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(instance->ctrl_reg_lock, - cpu_flags); - } - break; - - default: - PERROR_CRITICAL("Status is in wrong state (%d)!\n", - instance->status); - instance->status = ai_status_stream_error; - // Signal the end. - signaling = 1; - break; - - } - - if (signaling) { //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } - - if (instance->ai_control_task_flag && reschedule) { // Reschedule task - queue_delayed_work(instance->me4600_workqueue, - &instance->ai_control_task, 1); - } else { - PINFO("<%s> Ending control task.\n", __func__); - } - -} --- a/drivers/staging/meilhaus/me4600_ai.h +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @file me4600_ai.h - * - * @brief Meilhaus ME-4000 analog input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_AI_H_ -#define _ME4600_AI_H_ - -#include "mesubdevice.h" -#include "meioctl.h" -#include "mecirc_buf.h" - -#ifdef __KERNEL__ - -#define ME4600_AI_MAX_DATA 0xFFFF - -#ifdef ME_SYNAPSE -# define ME4600_AI_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse -#else -# define ME4600_AI_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB -#endif -#define ME4600_AI_CIRC_BUF_SIZE PAGE_SIZE< - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "meids.h" -#include "me4600_reg.h" -#include "me4600_ao_reg.h" -#include "me4600_ao.h" - -/* Defines - */ - -static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range); - -static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count); - -static int me4600_ao_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); - -static int me4600_ao_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks); - -static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, - int *number); - -static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype); - -static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); - -static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count); - -#ifndef BOSCH -/// @note NORMAL BUILD -/// @author Krzysztof Gantzke (k.gantzke@meilhaus.de) -/* Includes - */ - -# include - -/* Defines - */ - -/** Remove subdevice. -*/ -static void me4600_ao_destructor(struct me_subdevice *subdevice); - -/** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. -*/ -static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags); - -/** Set output as single -*/ -static int me4600_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags); - -/** Pass to user actual value of output. -*/ -static int me4600_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags); - -/** Write to output requed value. -*/ -static int me4600_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags); - -/** Set output as streamed device. -*/ -static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags); - -/** Wait for / Check empty space in buffer. -*/ -static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags); - -/** Start streaming. -*/ -static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags); - -/** Check actual state. / Wait for end. -*/ -static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags); - -/** Stop streaming. -*/ -static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags); - -/** Write datas to buffor. -*/ -static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags); - -/** Interrupt handler. Copy from buffer to FIFO. -*/ -static irqreturn_t me4600_ao_isr(int irq, void *dev_id); -/** Copy data from circular buffer to fifo (fast) in wraparound mode. -*/ -inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from circular buffer to fifo (fast). -*/ -inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from circular buffer to fifo (slow). -*/ -inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from user space to circular buffer. -*/ -inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, - int *user_values); - -/** Stop presentation. Preserve FIFOs. -*/ -inline int ao_stop_immediately(me4600_ao_subdevice_t *instance); - -/** Task for asynchronical state verifying. -*/ -static void me4600_ao_work_control_task(struct work_struct *work); -/* Functions - */ - -static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t tmp; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - instance->status = ao_status_none; - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->timeout.delay = 0; - instance->timeout.start_time = jiffies; - - //Stop state machine. - err = ao_stop_immediately(instance); - - //Remove from synchronous start. - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= - ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - outl(tmp, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, tmp); - *instance->preload_flags &= - ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - spin_unlock(instance->preload_reg_lock); - - //Set single mode, dissable FIFO, dissable external trigger, set output to analog, block interrupt. - outl(ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_RESET_IRQ, - instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ME4600_AO_MODE_SINGLE | ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ); - - //Set output to 0V - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - instance->preloaded_count = 0; - instance->data_count = 0; - instance->single_value = 0x8000; - instance->single_value_in_fifo = 0x8000; - - //Set status to signal that device is unconfigured. - instance->status = ao_status_none; - - //Signal reset if user is on wait. - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t ctrl; - uint32_t sync; - unsigned long cpu_flags; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - // Checking parameters - if (flags) { - PERROR - ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - switch (trig_type) { - case ME_TRIG_TYPE_SW: - if (trig_edge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid trigger edge. Software trigger has not edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - switch (trig_edge) { - case ME_TRIG_EDGE_ANY: - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - break; - - default: - PERROR("Invalid trigger edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - break; - - default: - PERROR - ("Invalid trigger type. Trigger must be software or digital.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - if ((trig_chan != ME_TRIG_CHAN_DEFAULT) - && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { - PERROR("Invalid trigger channel specified.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } - - if (ref != ME_REF_AO_GROUND) { - PERROR - ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); - return ME_ERRNO_INVALID_REF; - } - - if (single_config != 0) { - PERROR - ("Invalid single config specified. Only one range for anlog outputs is available.\n"); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - - if (channel != 0) { - PERROR - ("Invalid channel number specified. Analog output have only one channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - //Subdevice running in stream mode! - if ((instance->status >= ao_status_stream_run_wait) - && (instance->status < ao_status_stream_end)) { - PERROR("Subdevice is busy.\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } -/// @note For single all calls (config and write) are erasing previous state! - - instance->status = ao_status_none; - - // Correct single mirrors - instance->single_value_in_fifo = instance->single_value; - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - // Set control register. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Set stop bit. Stop streaming mode. - ctrl = inl(instance->ctrl_reg); - //Reset all bits. - ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP; - - if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { - PINFO("External digital trigger.\n"); - - if (trig_edge == ME_TRIG_EDGE_ANY) { -// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - instance->ctrl_trg = - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - } else if (trig_edge == ME_TRIG_EDGE_FALLING) { -// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - } else if (trig_edge == ME_TRIG_EDGE_RISING) { - instance->ctrl_trg = 0x0; - } - } else if (trig_type == ME_TRIG_TYPE_SW) { - PDEBUG("Software trigger\n"); - instance->ctrl_trg = 0x0; - } - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - // Set preload/synchronization register. - spin_lock(instance->preload_reg_lock); - if (trig_type == ME_TRIG_TYPE_SW) { - *instance->preload_flags &= - ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); - } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) - { - *instance->preload_flags |= - ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx; - } - - if (trig_chan == ME_TRIG_CHAN_DEFAULT) { - *instance->preload_flags &= - ~(ME4600_AO_SYNC_HOLD << instance->ao_idx); - } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) - { - *instance->preload_flags |= - ME4600_AO_SYNC_HOLD << instance->ao_idx; - } - - //Reset hardware register - sync = inl(instance->preload_reg); - PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync); - sync &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); - sync |= ME4600_AO_SYNC_HOLD << instance->ao_idx; - - //Output configured in default (safe) mode. - outl(sync, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync); - spin_unlock(instance->preload_reg_lock); - - instance->status = ao_status_single_configured; - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - unsigned long j; - unsigned long delay = 0; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & ~ME_IO_SINGLE_NONBLOCKING) { - PERROR("Invalid flag specified. %d\n", flags); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if ((instance->status >= ao_status_stream_configured) - && (instance->status <= ao_status_stream_end)) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - ME_SUBDEVICE_ENTER; - if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger. - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - j = jiffies; - - //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_single_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if (instance->status == ao_status_none) { - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - - PDEBUG("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - - *value = - (!err) ? instance->single_value_in_fifo : instance-> - single_value; - } else { //Non-blocking mode - //Read value - *value = instance->single_value; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - unsigned long j; - unsigned long delay = 0x0; - - //Registry handling variables. - uint32_t sync_mask; - uint32_t mode; - uint32_t tmp; - uint32_t ctrl; - uint32_t status; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & - ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | - ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (value & ~ME4600_AO_MAX_DATA) { - PERROR("Invalid value provided.\n"); - return ME_ERRNO_VALUE_OUT_OF_RANGE; - } - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if ((instance->status == ao_status_none) - || (instance->status > ao_status_single_end)) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - ME_SUBDEVICE_ENTER; - -/// @note For single all calls (config and write) are erasing previous state! - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - // Correct single mirrors - instance->single_value_in_fifo = instance->single_value; - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - instance->single_value_in_fifo = value; - - ctrl = inl(instance->ctrl_reg); - - if (!instance->fifo) { //No FIFO - //Set the single mode. - ctrl &= ~ME4600_AO_CTRL_MODE_MASK; - - //Write value - PDEBUG("Write value\n"); - outl(value, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, value); - } else { // mix-mode - //Set speed - outl(ME4600_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); - PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->timer_reg - instance->reg_base, - (int)ME4600_AO_MIN_CHAN_TICKS); - instance->hardware_stop_delay = HZ / 10; //100ms - - status = inl(instance->status_reg); - - //Set the continous mode. - ctrl &= ~ME4600_AO_CTRL_MODE_MASK; - ctrl |= ME4600_AO_MODE_CONTINUOUS; - - //Prepare FIFO - if (!(ctrl & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. - PINFO("Enableing FIFO.\n"); - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= - ME4600_AO_CTRL_BIT_ENABLE_FIFO | - ME4600_AO_CTRL_BIT_RESET_IRQ; - } else { //Check if FIFO is empty - if (status & ME4600_AO_STATUS_BIT_EF) { //FIFO not empty - PINFO("Reseting FIFO.\n"); - ctrl &= - ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO | - ME4600_AO_CTRL_BIT_ENABLE_IRQ); - ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - - instance->reg_base, ctrl); - - ctrl |= - ME4600_AO_CTRL_BIT_ENABLE_FIFO | - ME4600_AO_CTRL_BIT_RESET_IRQ; - } else { //FIFO empty, only interrupt needs to be disabled! - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; - } - } - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Write output - 1 value to FIFO - if (instance->ao_idx & 0x1) { - outl(value <<= 16, instance->fifo_reg); - PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->fifo_reg - instance->reg_base, - value <<= 16); - } else { - outl(value, instance->fifo_reg); - PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->fifo_reg - instance->reg_base, - value); - } - } - - mode = *instance->preload_flags >> instance->ao_idx; - mode &= (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG); - - PINFO("Triggering mode: 0x%x\n", mode); - - spin_lock(instance->preload_reg_lock); - sync_mask = inl(instance->preload_reg); - PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync_mask); - switch (mode) { - case 0: //Individual software - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output. - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) { //Now we can set correct mode. This is exception. It is set to synchronous and triggered later. - sync_mask &= - ~(ME4600_AO_SYNC_EXT_TRIG << instance-> - ao_idx); - sync_mask |= - ME4600_AO_SYNC_HOLD << instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } else { // FIFO - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. - sync_mask &= - ~((ME4600_AO_SYNC_EXT_TRIG | - ME4600_AO_SYNC_HOLD) << instance-> - ao_idx); - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } - instance->single_value = value; - break; - - case ME4600_AO_SYNC_EXT_TRIG: //Individual hardware - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if (!instance->fifo) { // No FIFO - In this case resetting 'ME4600_AO_SYNC_HOLD' will trigger output. - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) { //Now we can set correct mode - sync_mask &= - ~(ME4600_AO_SYNC_EXT_TRIG << instance-> - ao_idx); - sync_mask |= - ME4600_AO_SYNC_HOLD << instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } else { // FIFO - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. - sync_mask &= - ~((ME4600_AO_SYNC_EXT_TRIG | - ME4600_AO_SYNC_HOLD) << instance-> - ao_idx); - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } - break; - - case ME4600_AO_SYNC_HOLD: //Synchronous software - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - -// if((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME4600_AO_SYNC_HOLD) - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG)) { //Now we can set correct mode - sync_mask |= - ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx; -// sync_mask &= ~(ME4600_AO_SYNC_EXT_TRIG << instance->ao_idx); - sync_mask |= ME4600_AO_SYNC_HOLD << instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - break; - - case (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG): //Synchronous hardware - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - if ((sync_mask & ((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG)) { //Now we can set correct mode - sync_mask |= - (ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << - instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - break; - } -// spin_unlock(instance->preload_reg_lock); // Moved down. - - //Activate ISM (remove 'stop' bits) - ctrl &= - ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); - ctrl |= instance->ctrl_trg; - ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - -/// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS! - - if (!instance->fifo) { //No FIFO - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs. - tmp = ~(*instance->preload_flags | 0xFFFF0000); - PINFO - ("Fired all software synchronous outputs. mask:0x%08x\n", - tmp); - tmp |= sync_mask & 0xFFFF0000; - // Add this channel to list - tmp &= ~(ME4600_AO_SYNC_HOLD << instance->ao_idx); - - //Fire - PINFO("Software trigger.\n"); - outl(tmp, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - tmp); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } else if (!mode) { // Add this channel to list - outl(sync_mask & - ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask & ~(ME4600_AO_SYNC_HOLD << - instance->ao_idx)); - - //Fire - PINFO("Software trigger.\n"); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - - } else { // mix-mode - begin - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs - //Add channel to start list - outl(sync_mask | - (ME4600_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask | (ME4600_AO_SYNC_HOLD << - instance->ao_idx)); - - //Fire - PINFO - ("Fired all software synchronous outputs by software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - 0x8000); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } else if (!mode) { //Trigger outputs -/* //Remove channel from start list //<== Unnecessary. Removed. - outl(sync_mask & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, tmp); -*/ - //Fire - PINFO("Software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - 0x8000); - -/* //Restore save settings //<== Unnecessary. Removed. - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask); -*/ - } - } - spin_unlock(instance->preload_reg_lock); - - j = jiffies; - instance->status = ao_status_single_run_wait; - - instance->timeout.delay = delay; - instance->timeout.start_time = j; - instance->ao_control_task_flag = 1; - queue_delayed_work(instance->me4600_workqueue, - &instance->ao_control_task, 1); - - if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_single_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if (((!delay) || ((jiffies - j) <= delay)) - && (instance->status != ao_status_single_end)) { - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - ao_stop_immediately(instance); - instance->status = ao_status_none; - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - if (instance->status == ao_status_single_end) { - PDEBUG("Timeout reached.\n"); - } else { - if ((jiffies - j) > delay) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - } - - ao_stop_immediately(instance); - } - - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->status = ao_status_single_end; - err = ME_ERRNO_TIMEOUT; - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t ctrl; - unsigned long cpu_flags; - uint64_t conv_ticks; - unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; - unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - conv_ticks = - (uint64_t) conv_start_ticks_low + - ((uint64_t) conv_start_ticks_high << 32); - - if (flags & - ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY | ME_IO_STREAM_CONFIG_WRAPAROUND - | ME_IO_STREAM_CONFIG_BIT_PATTERN)) { - PERROR("Invalid flags.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { - if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { - PERROR - ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE) - || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) { - PERROR - ("Hardware wraparound mode must be in infinite mode.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - } - - if (count != 1) { - PERROR("Only 1 entry in config list acceptable.\n"); - return ME_ERRNO_INVALID_CONFIG_LIST_COUNT; - } - - if (config_list[0].iChannel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (config_list[0].iStreamConfig != 0) { - PERROR("Only one range available.\n"); - return ME_ERRNO_INVALID_STREAM_CONFIG; - } - - if (config_list[0].iRef != ME_REF_AO_GROUND) { - PERROR("Output is referenced to ground.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((trigger->iAcqStartTicksLow != 0) - || (trigger->iAcqStartTicksHigh != 0)) { - PERROR - ("Invalid acquisition start trigger argument specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_ARG; - } - - if (config_list[0].iFlags) { - PERROR("Invalid config list flag.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - switch (trigger->iAcqStartTrigType) { - case ME_TRIG_TYPE_SW: - if (trigger->iAcqStartTrigEdge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - } - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_ANY: - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - break; - - default: - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - } - break; - - default: - PERROR("Invalid acquisition start trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - } - - if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) { - PERROR("Invalid scan start trigger type specified.\n"); - return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - } - - if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) { - PERROR("Invalid conv start trigger type specified.\n"); - return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - } - - if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS) - || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) { - PERROR("Invalid conv start trigger argument specified.\n"); - return ME_ERRNO_INVALID_CONV_START_ARG; - } - - if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) { - PERROR("Invalid acq start trigger argument specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_ARG; - } - - if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) { - PERROR("Invalid scan start trigger argument specified.\n"); - return ME_ERRNO_INVALID_SCAN_START_ARG; - } - - switch (trigger->iScanStopTrigType) { - case ME_TRIG_TYPE_NONE: - if (trigger->iScanStopCount != 0) { - PERROR("Invalid scan stop count specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_ARG; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iScanStopCount <= 0) { - PERROR("Invalid scan stop count specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_ARG; - } - } else { - PERROR("The continous mode has not 'scan' contects.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - break; - - default: - PERROR("Invalid scan stop trigger type specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; - } - - switch (trigger->iAcqStopTrigType) { - case ME_TRIG_TYPE_NONE: - if (trigger->iAcqStopCount != 0) { - PERROR("Invalid acq stop count specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_ARG; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iAcqStopCount <= 0) { - PERROR - ("The continous mode has not 'scan' contects.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_ARG; - } - } - break; - - default: - PERROR("Invalid acq stop trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - - switch (trigger->iAcqStartTrigChan) { - case ME_TRIG_CHAN_DEFAULT: - case ME_TRIG_CHAN_SYNCHRONOUS: - break; - - default: - PERROR("Invalid acq start trigger channel specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; - } - - ME_SUBDEVICE_ENTER; - - if ((flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) && !instance->bitpattern) { - PERROR("This subdevice not support output redirection.\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INVALID_FLAGS; - } - //Stop device - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - //Check if state machine is stopped. - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - //Reset control register. Block all actions. Disable IRQ. Disable FIFO. - ctrl = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //This is paranoic, but to be sure. - instance->preloaded_count = 0; - instance->data_count = 0; - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - /* Set mode. */ - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound - if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound - PINFO("Hardware wraparound.\n"); - ctrl |= ME4600_AO_MODE_WRAPAROUND; - instance->mode = ME4600_AO_HW_WRAP_MODE; - } else { //Software wraparound - PINFO("Software wraparound.\n"); - ctrl |= ME4600_AO_MODE_CONTINUOUS; - instance->mode = ME4600_AO_SW_WRAP_MODE; - } - } else { //Continous - PINFO("Continous.\n"); - ctrl |= ME4600_AO_MODE_CONTINUOUS; - instance->mode = ME4600_AO_CONTINOUS; - } - - //Set the trigger edge. - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger. - PINFO("External digital trigger.\n"); - instance->start_mode = ME4600_AO_EXT_TRIG; -/* - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; -*/ - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - PINFO("Set the trigger edge: rising.\n"); - instance->ctrl_trg = 0x0; - break; - - case ME_TRIG_EDGE_FALLING: - PINFO("Set the trigger edge: falling.\n"); -// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - instance->ctrl_trg = ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - break; - - case ME_TRIG_EDGE_ANY: - PINFO("Set the trigger edge: both edges.\n"); -// ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - instance->ctrl_trg = - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - break; - } - } else { - PINFO("Internal software trigger.\n"); - instance->start_mode = 0; - } - - //Set the stop mode and value. - if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data - instance->stop_mode = ME4600_AO_ACQ_STOP_MODE; - instance->stop_count = trigger->iAcqStopCount; - } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans' - instance->stop_mode = ME4600_AO_SCAN_STOP_MODE; - instance->stop_count = trigger->iScanStopCount; - } else { //Infinite - instance->stop_mode = ME4600_AO_INF_STOP_MODE; - instance->stop_count = 0; - } - - PINFO("Stop count: %d.\n", instance->stop_count); - - if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start - instance->start_mode |= ME4600_AO_SYNC_HOLD; - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered - PINFO("Synchronous start. Externaly trigger active.\n"); - instance->start_mode |= ME4600_AO_SYNC_EXT_TRIG; - } -#ifdef MEDEBUG_INFO - else { - PINFO - ("Synchronous start. Externaly trigger dissabled.\n"); - } -#endif - - } - //Set speed - outl(conv_ticks - 2, instance->timer_reg); - PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base, - instance->timer_reg - instance->reg_base, conv_ticks - 2); - instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME4600_AO_BASE_FREQUENCY; //<== MUST be with cast! - - //Conect outputs to analog or digital port. - if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) { - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO; - } - // Write the control word - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Set status. - instance->status = ao_status_stream_configured; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - long j; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (!instance->circ_buf.buf) { - PERROR("Circular buffer not exists.\n"); - return ME_ERRNO_INTERNAL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - ME_SUBDEVICE_ENTER; - - if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full. - *count = me_circ_buf_space(&instance->circ_buf); - } else { //The buffer is full. - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } else { //Max time. - t = LONG_MAX; - } - - *count = 0; - - j = jiffies; - - //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled. - wait_event_interruptible_timeout(instance->wait_queue, - ((me_circ_buf_space - (&instance->circ_buf)) - || !(inl(instance->status_reg) - & - ME4600_AO_STATUS_BIT_FSM)), - t); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PERROR("AO subdevice is not running.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } else if ((jiffies - j) >= t) { - PERROR("Wait on values timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } else { //Uff... all is good. Inform user about empty space. - *count = me_circ_buf_space(&instance->circ_buf); - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags = 0; - uint32_t status; - uint32_t ctrl; - uint32_t synch; - int count = 0; - int circ_buffer_count; - - unsigned long ref; - unsigned long delay = 0; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - PERROR("Invalid flags.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if ((start_mode != ME_START_MODE_BLOCKING) - && (start_mode != ME_START_MODE_NONBLOCKING)) { - PERROR("Invalid start mode specified.\n"); - return ME_ERRNO_INVALID_START_MODE; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - switch (instance->status) { //Checking actual mode. - case ao_status_stream_configured: - case ao_status_stream_end: - //Correct modes! - break; - - //The device is in wrong mode. - case ao_status_none: - case ao_status_single_configured: - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - PERROR - ("Subdevice must be preinitialize correctly for streaming.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - PDEBUG("Before restart broke stream 'STOP' must be caled.\n"); - return ME_STATUS_ERROR; - - case ao_status_stream_run_wait: - case ao_status_stream_run: - case ao_status_stream_end_wait: - PDEBUG("Stream is already working.\n"); - return ME_ERRNO_SUBDEVICE_BUSY; - - default: - instance->status = ao_status_stream_error; - PERROR_CRITICAL("Status is in wrong state!\n"); - return ME_ERRNO_INTERNAL; - - } - - ME_SUBDEVICE_ENTER; - - if (instance->mode == ME4600_AO_CONTINOUS) { //Continous - instance->circ_buf.tail += instance->preloaded_count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } - circ_buffer_count = me_circ_buf_values(&instance->circ_buf); - - if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer - ME_SUBDEVICE_EXIT; - PERROR("No values in buffer!\n"); - return ME_ERRNO_LACK_OF_RESOURCES; - } - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - //Set values for single_read() - instance->single_value = ME4600_AO_MAX_DATA + 1; - instance->single_value_in_fifo = ME4600_AO_MAX_DATA + 1; - - //Setting stop points - if (instance->stop_mode == ME4600_AO_SCAN_STOP_MODE) { - instance->stop_data_count = - instance->stop_count * circ_buffer_count; - } else { - instance->stop_data_count = instance->stop_count; - } - - if ((instance->stop_data_count != 0) - && (instance->stop_data_count < circ_buffer_count)) { - PERROR("More data in buffer than previously set limit!\n"); - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - //Check FIFO - if (!(ctrl & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. <= This should be done by user call with ME_WRITE_MODE_PRELOAD - PINFO("Enableing FIFO.\n"); - ctrl |= - ME4600_AO_CTRL_BIT_ENABLE_FIFO | - ME4600_AO_CTRL_BIT_RESET_IRQ; - - instance->preloaded_count = 0; - instance->data_count = 0; - } else { //Block IRQ - ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl | ME4600_AO_CTRL_BIT_RESET_IRQ); - - //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it. - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_EF)) { //FIFO empty - if (instance->stop_data_count == 0) { - count = ME4600_AO_FIFO_COUNT; - } else { - count = - (ME4600_AO_FIFO_COUNT < - instance-> - stop_data_count) ? ME4600_AO_FIFO_COUNT : - instance->stop_data_count; - } - - //Copy data - count = - ao_write_data(instance, count, instance->preloaded_count); - - if (count < 0) { //This should never happend! - PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - //Set pre-load features. - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - synch &= - ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - synch |= - (instance->start_mode & ~ME4600_AO_EXT_TRIG) << instance->ao_idx; - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); - - //Default count is '0' - if (instance->mode == ME4600_AO_CONTINOUS) { //Continous - instance->preloaded_count = 0; - instance->circ_buf.tail += count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } else { //Wraparound - instance->preloaded_count += count; - instance->data_count += count; - - //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode. - if ((instance->stop_mode == ME4600_AO_INF_STOP_MODE) - && (circ_buffer_count <= ME4600_AO_FIFO_COUNT)) { //Change to hardware wraparound - PDEBUG - ("Changeing mode from software wraparound to hardware wraparound.\n"); - //Copy all data - count = - ao_write_data(instance, circ_buffer_count, - instance->preloaded_count); - ctrl &= ~ME4600_AO_CTRL_MODE_MASK; - ctrl |= ME4600_AO_MODE_WRAPAROUND; - } - - if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. - instance->preloaded_count = 0; - } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! - PERROR_CRITICAL - ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - - //Set status to 'wait for start' - instance->status = ao_status_stream_run_wait; - - status = inl(instance->status_reg); - //Start state machine and interrupts - ctrl &= ~(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - if (instance->start_mode == ME4600_AO_EXT_TRIG) { // External trigger. - PINFO("External trigger.\n"); - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - } - if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half! - if ((ctrl & ME4600_AO_CTRL_MODE_MASK) == ME4600_AO_MODE_CONTINUOUS) { //Enable IRQ only when hardware_continous is set and FIFO is more than half - ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - } - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - //Trigger output - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - //Add channel to start list - outl(synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch | (ME4600_AO_SYNC_HOLD << instance->ao_idx)); - - //Fire - PINFO - ("Fired all software synchronous outputs by software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - - //Restore save settings - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); - } else if (!instance->start_mode) { //Trigger outputs -/* - //Remove channel from start list. // <== Unnecessary. Removed. - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - outl(synch & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch & ~(ME4600_AO_SYNC_HOLD << instance->ao_idx)); -*/ - //Fire - PINFO("Software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - -/* - //Restore save settings. // <== Unnecessary. Removed. - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); -*/ - } - // Set control task's timeout - ref = jiffies; - instance->timeout.delay = delay; - instance->timeout.start_time = ref; - - if (status & ME4600_AO_STATUS_BIT_HF) { //Less than half but not empty! - PINFO("Less than half.\n"); - if (instance->stop_data_count != 0) { - count = ME4600_AO_FIFO_COUNT / 2; - } else { - count = - ((ME4600_AO_FIFO_COUNT / 2) < - instance->stop_data_count) ? ME4600_AO_FIFO_COUNT / - 2 : instance->stop_data_count; - } - - //Copy data - count = - ao_write_data(instance, count, instance->preloaded_count); - - if (count < 0) { //This should never happend! - PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - if (instance->mode == ME4600_AO_CONTINOUS) { //Continous - instance->circ_buf.tail += count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } else { //Wraparound - instance->data_count += count; - instance->preloaded_count += count; - - if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. - instance->preloaded_count = 0; - } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! - PERROR_CRITICAL - ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_HF)) { //More than half! - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - } - //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt. - if ((instance->stop_mode != ME4600_AO_INF_STOP_MODE) - && (instance->mode == ME4600_AO_SW_WRAP_MODE) - && (circ_buffer_count <= (ME4600_AO_FIFO_COUNT / 2))) { //Put more data to FIFO - PINFO("Limited wraparound with less than HALF FIFO datas.\n"); - if (instance->preloaded_count) { //This should never happend! - PERROR_CRITICAL - ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet. - //Copy to buffer - if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend! - PERROR_CRITICAL - ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - instance->data_count += circ_buffer_count; - - if (!((status = inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy. - spin_lock_irqsave(&instance->subdevice_lock, - cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - break; - } - } - } - // Schedule control task. - instance->ao_control_task_flag = 1; - queue_delayed_work(instance->me4600_workqueue, - &instance->ao_control_task, 1); - - if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_stream_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if ((instance->status != ao_status_stream_run) - && (instance->status != ao_status_stream_end)) { - PDEBUG("Starting stream canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } else if ((delay) && ((jiffies - ref) >= delay)) { - if (instance->status != ao_status_stream_run) { - if (instance->status == ao_status_stream_end) { - PDEBUG("Timeout reached.\n"); - } else { - if ((jiffies - ref) > delay) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - } - ao_stop_immediately(instance); - } - - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->status = ao_status_stream_end; - err = ME_ERRNO_TIMEOUT; - } - } - } - - ME_SUBDEVICE_EXIT; - return err; -} - -static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) { - PERROR("Invalid wait argument specified.\n"); - *status = ME_STATUS_INVALID; - return ME_ERRNO_INVALID_WAIT; - } - - ME_SUBDEVICE_ENTER; - - switch (instance->status) { - case ao_status_single_configured: - case ao_status_single_end: - case ao_status_stream_configured: - case ao_status_stream_end: - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - *status = ME_STATUS_IDLE; - break; - - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - case ao_status_stream_run_wait: - case ao_status_stream_run: - case ao_status_stream_end_wait: - *status = ME_STATUS_BUSY; - break; - - case ao_status_none: - default: - *status = - (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ? - ME_STATUS_BUSY : ME_STATUS_IDLE; - break; - } - - if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - ((instance->status != - ao_status_single_run_wait) - && (instance->status != - ao_status_single_run) - && (instance->status != - ao_status_single_end_wait) - && (instance->status != - ao_status_stream_run_wait) - && (instance->status != - ao_status_stream_run) - && (instance->status != - ao_status_stream_end_wait)), - LONG_MAX); - - if (instance->status != ao_status_stream_end) { - PDEBUG("Wait for IDLE canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait for IDLE interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - - *status = ME_STATUS_IDLE; - } - - *values = me_circ_buf_space(&instance->circ_buf); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags) -{ // Stop work and empty buffer and FIFO - int err = ME_ERRNO_SUCCESS; - me4600_ao_subdevice_t *instance; - unsigned long cpu_flags; - volatile uint32_t ctrl; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((stop_mode != ME_STOP_MODE_IMMEDIATE) - && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { - PERROR("Invalid stop mode specified.\n"); - return ME_ERRNO_INVALID_STOP_MODE; - } - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (instance->status < ao_status_stream_configured) { - //There is nothing to stop! - PERROR("Subdevice not in streaming mode. %d\n", - instance->status); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - ME_SUBDEVICE_ENTER; - - //Mark as stopping. => Software stop. - instance->status = ao_status_stream_end_wait; - - if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now! - err = ao_stop_immediately(instance); - } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { - ctrl = inl(instance->ctrl_reg) & ME4600_AO_CTRL_MODE_MASK; - if (ctrl == ME4600_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - //Only runing process will interrupt this call. Events are signaled when status change. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_stream_end_wait), - LONG_MAX); - - if (instance->status != ao_status_stream_end) { - PDEBUG("Stopping stream canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Stopping stream interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - if (!flags) { //Reset FIFO - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - if (!flags) { //Reset software buffer - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - instance->preloaded_count = 0; - instance->data_count = 0; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me4600_ao_subdevice_t *instance; - unsigned long cpu_flags = 0; - uint32_t reg_copy; - - int copied_from_user = 0; - int left_to_copy_from_user = *count; - - int copied_values; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - //Checking arguments - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (*count <= 0) { - PERROR("Invalid count of values specified.\n"); - return ME_ERRNO_INVALID_VALUE_COUNT; - } - - if (values == NULL) { - PERROR("Invalid address of values specified.\n"); - return ME_ERRNO_INVALID_POINTER; - } - - if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode. - PERROR - ("Subdevice must be preinitialize correctly for streaming.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } -/// @note If no 'pre-load' is used. stream_start() will move data to FIFO. - switch (write_mode) { - case ME_WRITE_MODE_PRELOAD: - - //Device must be stopped. - if ((instance->status != ao_status_stream_configured) - && (instance->status != ao_status_stream_end)) { - PERROR - ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - break; - case ME_WRITE_MODE_NONBLOCKING: - case ME_WRITE_MODE_BLOCKING: - /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up! - /// @note Some other thread must empty buffer by starting engine. - break; - - default: - PERROR("Invalid write mode specified.\n"); - return ME_ERRNO_INVALID_WRITE_MODE; - } - - if (instance->mode & ME4600_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped. - if ((instance->status != ao_status_stream_configured) - && (instance->status != ao_status_stream_end)) { - PERROR - ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); - return ME_ERRNO_INVALID_WRITE_MODE; - } - } - - if ((instance->mode == ME4600_AO_HW_WRAP_MODE) && (write_mode != ME_WRITE_MODE_PRELOAD)) { // hardware wrap_around mode. - //This is transparent for user. - PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n"); - write_mode = ME_WRITE_MODE_PRELOAD; - } - - ME_SUBDEVICE_ENTER; - - if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - //Check FIFO - if (!(reg_copy & ME4600_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it. - reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - instance->preloaded_count = 0; - } - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } - - while (1) { - //Copy to buffer. This step is common for all modes. - copied_from_user = - ao_get_data_from_user(instance, left_to_copy_from_user, - values + (*count - - left_to_copy_from_user)); - left_to_copy_from_user -= copied_from_user; - - reg_copy = inl(instance->status_reg); - if ((instance->status == ao_status_stream_run) && !(reg_copy & ME4600_AO_STATUS_BIT_FSM)) { //BROKEN PIPE! The state machine is stoped but logical status show that should be working. - PERROR("Broken pipe in write.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - break; - } - - if ((instance->status == ao_status_stream_run) && (instance->mode == ME4600_AO_CONTINOUS) && (reg_copy & ME4600_AO_STATUS_BIT_HF)) { //Continous mode runing and data are below half! - - // Block interrupts. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - //reg_copy &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - reg_copy |= ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - //Fast copy - copied_values = - ao_write_data(instance, ME4600_AO_FIFO_COUNT / 2, - 0); - if (copied_values > 0) { - instance->circ_buf.tail += copied_values; - instance->circ_buf.tail &= - instance->circ_buf.mask; - continue; - } - // Activate interrupts. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - //reg_copy |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - reg_copy &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (copied_values == 0) { //This was checked and never should happend! - PERROR_CRITICAL("COPING FINISH WITH 0!\n"); - } - - if (copied_values < 0) { //This was checked and never should happend! - PERROR_CRITICAL - ("COPING FINISH WITH AN ERROR!\n"); - instance->status = ao_status_stream_fifo_error; - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - break; - } - } - - if (!left_to_copy_from_user) { //All datas were copied. - break; - } else { //Not all datas were copied. - if (instance->mode & ME4600_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size! - PERROR - ("Too much data for wraparound mode! Exceeded size of %ld.\n", - ME4600_AO_CIRC_BUF_COUNT - 1); - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - break; - } - - if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls - break; - } - - wait_event_interruptible(instance->wait_queue, - me_circ_buf_space(&instance-> - circ_buf)); - - if (signal_pending(current)) { - PERROR("Writing interrupted by signal.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - break; - } - - if (instance->status == ao_status_none) { //Reset - PERROR("Writing interrupted by reset.\n"); - err = ME_ERRNO_CANCELLED; - break; - } - } - } - - if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload - copied_values = - ao_write_data_pooling(instance, ME4600_AO_FIFO_COUNT, - instance->preloaded_count); - instance->preloaded_count += copied_values; - instance->data_count += copied_values; - - if ((instance->mode == ME4600_AO_HW_WRAP_MODE) - && (me_circ_buf_values(&instance->circ_buf) > - ME4600_AO_FIFO_COUNT)) { - PERROR - ("Too much data for hardware wraparound mode! Exceeded size of %d.\n", - ME4600_AO_FIFO_COUNT); - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } - } - - *count = *count - left_to_copy_from_user; - ME_SUBDEVICE_EXIT; - - return err; -} -static irqreturn_t me4600_ao_isr(int irq, void *dev_id) -{ - me4600_ao_subdevice_t *instance = dev_id; - uint32_t irq_status; - uint32_t ctrl; - uint32_t status; - int count = 0; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inl(instance->irq_status_reg); - if (!(irq_status & (ME4600_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) { - PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n", - jiffies, __func__, instance->ao_idx, irq_status); - return IRQ_NONE; - } - - if (!instance->circ_buf.buf) { - instance->status = ao_status_stream_error; - PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); - //Block interrupts. Stop machine. - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= - ME4600_AO_CTRL_BIT_RESET_IRQ | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Inform user - wake_up_interruptible_all(&instance->wait_queue); - return IRQ_HANDLED; - } - - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE? - PDEBUG("Interrupt come but ISM is not working!\n"); - //Block interrupts. Stop machine. - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= - ME4600_AO_CTRL_BIT_RESET_IRQ | ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - return IRQ_HANDLED; - } - //General procedure. Process more datas. - -#ifdef MEDEBUG_DEBUG - if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty! - PDEBUG("Circular buffer empty!\n"); - } -#endif - - //Check FIFO - if (status & ME4600_AO_STATUS_BIT_HF) { //OK less than half - - //Block interrupts - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - do { - //Calculate how many should be copied. - count = - (instance->stop_data_count) ? instance-> - stop_data_count - - instance->data_count : ME4600_AO_FIFO_COUNT / 2; - if (ME4600_AO_FIFO_COUNT / 2 < count) { - count = ME4600_AO_FIFO_COUNT / 2; - } - //Copy data - if (instance->mode == ME4600_AO_CONTINOUS) { //Continous - count = ao_write_data(instance, count, 0); - if (count > 0) { - instance->circ_buf.tail += count; - instance->circ_buf.tail &= - instance->circ_buf.mask; - instance->data_count += count; - - if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied. - break; - } - } - } else if ((instance->mode == ME4600_AO_SW_WRAP_MODE) && ((ctrl & ME4600_AO_CTRL_MODE_MASK) == ME4600_AO_MODE_CONTINUOUS)) { //Wraparound (software) - if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer. - count = - ao_write_data(instance, count, 0); - } else { //Copy in wraparound mode. - count = - ao_write_data_wraparound(instance, - count, - instance-> - preloaded_count); - } - - if (count > 0) { - instance->data_count += count; - instance->preloaded_count += count; - instance->preloaded_count %= - me_circ_buf_values(&instance-> - circ_buf); - - if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied. - break; - } - } - } - - if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work. - break; - } - } //Repeat if still is under half fifo - while ((status = - inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_HF); - - //Unblock interrupts - ctrl = inl(instance->ctrl_reg); - if (count >= 0) { //Copy was successful. - if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts. - PDEBUG("Finishing work. Interrupt disabled.\n"); - instance->status = ao_status_stream_end_wait; - } else if (count > 0) { //Normal work. Enable interrupt. - PDEBUG("Normal work. Enable interrupt.\n"); - ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - } else { //Normal work but there are no more data in buffer. Interrupt active but blocked. stream_write() will unblock it. - PDEBUG - ("No data in software buffer. Interrupt blocked.\n"); - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - } - } else { //Error during copy. - instance->status = ao_status_stream_fifo_error; - } - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - } else { //?? more than half - PDEBUG - ("Interrupt come but FIFO more than half full! Reset interrupt.\n"); - //Reset pending interrupt - ctrl = inl(instance->ctrl_reg); - ctrl |= ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - ctrl &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - } - - PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n", - me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail, - instance->circ_buf.head); - PINFO("ISR: Stop count: %d.\n", instance->stop_count); - PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count); - PINFO("ISR: Data count: %d.\n", instance->data_count); - - //Inform user - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -static void me4600_ao_destructor(struct me_subdevice *subdevice) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - instance->ao_control_task_flag = 0; - - // Reset subdevice to asure clean exit. - me4600_ao_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - - // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). - if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2); - } - - if (instance->fifo) { - if (instance->irq) { - free_irq(instance->irq, instance); - instance->irq = 0; - } - - if (instance->circ_buf.buf) { - free_pages((unsigned long)instance->circ_buf.buf, - ME4600_AO_CIRC_BUF_SIZE_ORDER); - } - instance->circ_buf.buf = NULL; - } - - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, - spinlock_t *preload_reg_lock, - uint32_t *preload_flags, - int ao_idx, - int fifo, - int irq, - struct workqueue_struct *me4600_wq) -{ - me4600_ao_subdevice_t *subdevice; - int err; - - PDEBUG("executed. idx=%d\n", ao_idx); - - // Allocate memory for subdevice instance. - subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_ao_subdevice_t)); - - // Initialize subdevice base class. - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->preload_reg_lock = preload_reg_lock; - subdevice->preload_flags = preload_flags; - - // Store analog output index. - subdevice->ao_idx = ao_idx; - - // Store if analog output has fifo. - subdevice->fifo = (ao_idx < fifo) ? 1 : 0; - - if (subdevice->fifo) { // Allocate and initialize circular buffer. - subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1; - - subdevice->circ_buf.buf = - (void *)__get_free_pages(GFP_KERNEL, - ME4600_AO_CIRC_BUF_SIZE_ORDER); - PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, - ME4600_AO_CIRC_BUF_SIZE); - - if (!subdevice->circ_buf.buf) { - PERROR - ("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - - memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE); - } else { // No FIFO. - subdevice->circ_buf.mask = 0; - subdevice->circ_buf.buf = NULL; - } - - subdevice->circ_buf.head = 0; - subdevice->circ_buf.tail = 0; - - subdevice->status = ao_status_none; - subdevice->ao_control_task_flag = 0; - subdevice->timeout.delay = 0; - subdevice->timeout.start_time = jiffies; - - // Initialize wait queue. - init_waitqueue_head(&subdevice->wait_queue); - - // Initialize single value to 0V. - subdevice->single_value = 0x8000; - subdevice->single_value_in_fifo = 0x8000; - - // Register interrupt service routine. - if (subdevice->fifo) { - subdevice->irq = irq; - if (request_irq(subdevice->irq, me4600_ao_isr, - IRQF_DISABLED | IRQF_SHARED, - ME4600_NAME, subdevice)) { - PERROR("Cannot get interrupt line.\n"); - PDEBUG("free circ_buf = %p size=%d", - subdevice->circ_buf.buf, - PAGE_SHIFT << ME4600_AO_CIRC_BUF_SIZE_ORDER); - free_pages((unsigned long)subdevice->circ_buf.buf, - ME4600_AO_CIRC_BUF_SIZE_ORDER); - me_subdevice_deinit((me_subdevice_t *) subdevice); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - } else { - subdevice->irq = 0; - } - - // Initialize registers. - subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; - subdevice->preload_reg = reg_base + ME4600_AO_SYNC_REG; - if (ao_idx == 0) { - subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bitpattern = 0; - } else if (ao_idx == 1) { - subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bitpattern = 0; - } else if (ao_idx == 2) { - subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bitpattern = 0; - } else if (ao_idx == 3) { - subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bitpattern = 1; - } else { - PERROR_CRITICAL("WRONG SUBDEVICE idx=%d!", ao_idx); - me_subdevice_deinit((me_subdevice_t *) subdevice); - if (subdevice->fifo) { - free_pages((unsigned long)subdevice->circ_buf.buf, - ME4600_AO_CIRC_BUF_SIZE_ORDER); - } - subdevice->circ_buf.buf = NULL; - kfree(subdevice); - return NULL; - } - - // Override base class methods. - subdevice->base.me_subdevice_destructor = me4600_ao_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_ao_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_ao_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me4600_ao_io_single_write; - subdevice->base.me_subdevice_io_stream_config = - me4600_ao_io_stream_config; - subdevice->base.me_subdevice_io_stream_new_values = - me4600_ao_io_stream_new_values; - subdevice->base.me_subdevice_io_stream_write = - me4600_ao_io_stream_write; - subdevice->base.me_subdevice_io_stream_start = - me4600_ao_io_stream_start; - subdevice->base.me_subdevice_io_stream_status = - me4600_ao_io_stream_status; - subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop; - subdevice->base.me_subdevice_query_number_channels = - me4600_ao_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_ao_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_ao_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me4600_ao_query_subdevice_caps_args; - subdevice->base.me_subdevice_query_range_by_min_max = - me4600_ao_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me4600_ao_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me4600_ao_query_range_info; - subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer; - - // Prepare work queue - subdevice->me4600_workqueue = me4600_wq; - -/* workqueue API changed in kernel 2.6.20 */ - INIT_DELAYED_WORK(&subdevice->ao_control_task, - me4600_ao_work_control_task); - - if (subdevice->fifo) { // Set speed for single operations. - outl(ME4600_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); - subdevice->hardware_stop_delay = HZ / 10; //100ms - } - - return subdevice; -} - -/** @brief Stop presentation. Preserve FIFOs. -* -* @param instance The subdevice instance (pointer). -*/ -inline int ao_stop_immediately(me4600_ao_subdevice_t *instance) -{ - unsigned long cpu_flags; - uint32_t ctrl; - int timeout; - int i; - - timeout = - (instance->hardware_stop_delay > - (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10; - for (i = 0; i <= timeout; i++) { - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { // Exit. - break; - } - //Still working! - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - return ME_ERRNO_INTERNAL; - } - return ME_ERRNO_SUCCESS; -} - -/** @brief Copy data from circular buffer to fifo (fast) in wraparound. -* @note This is time critical function. Checking is done at begining and end only. -* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied data. -* @return On error/success: 0. No datas were copied => no data in buffer. -* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. -*/ -inline int ao_write_data_wraparound(me4600_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is time critical function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int i = 1; - - if (count <= 0) { //Wrong count! - return 0; - } - - while (i < local_count) { - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - if (pos == instance->circ_buf.head) { - pos = instance->circ_buf.tail; - } - i++; - } - - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! - PERROR("FIFO was full before all datas were copied! idx=%d\n", - instance->ao_idx); - return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } else { //Add last value - value = *(instance->circ_buf.buf + pos); - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - } - - PINFO("WRAPAROUND LOADED %d values. idx=%d\n", local_count, - instance->ao_idx); - return local_count; -} - -/** @brief Copy data from software buffer to fifo (fast). -* @note This is time critical function. Checking is done at begining and end only. -* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied data. -* @return On error/success: 0. No datas were copied => no data in buffer. -* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. -*/ -inline int ao_write_data(me4600_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is time critical function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int max_count; - int i = 1; - - if (count <= 0) { //Wrong count! - return 0; - } - - max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; - if (max_count <= 0) { //No data to copy! - return 0; - } - - if (max_count < count) { - local_count = max_count; - } - - while (i < local_count) { - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - i++; - } - - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! - PERROR("FIFO was full before all datas were copied! idx=%d\n", - instance->ao_idx); - return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } else { //Add last value - value = *(instance->circ_buf.buf + pos); - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - } - - PINFO("FAST LOADED %d values. idx=%d\n", local_count, instance->ao_idx); - return local_count; -} - -/** @brief Copy data from software buffer to fifo (slow). -* @note This is slow function that copy all data from buffer to FIFO with full control. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied values. -* @return On error/success: 0. FIFO was full at begining. -* @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. -*/ -inline int ao_write_data_pooling(me4600_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is slow function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int i; - int max_count; - - if (count <= 0) { //Wrong count! - PERROR("SLOW LOADED: Wrong count! idx=%d\n", instance->ao_idx); - return 0; - } - - max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; - if (max_count <= 0) { //No data to copy! - PERROR("SLOW LOADED: No data to copy! idx=%d\n", - instance->ao_idx); - return 0; - } - - if (max_count < count) { - local_count = max_count; - } - - for (i = 0; i < local_count; i++) { - status = inl(instance->status_reg); - if (!(status & ME4600_AO_STATUS_BIT_FF)) { //FIFO is full! - return i; - } - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - } - - PINFO("SLOW LOADED %d values. idx=%d\n", local_count, instance->ao_idx); - return local_count; -} - -/** @brief Copy data from user space to circular buffer. -* @param instance The subdevice instance (pointer). -* @param count Number of datas in user space. -* @param user_values Buffer's pointer. -* -* @return On success: Number of copied values. -* @return On error: -ME_ERRNO_INTERNAL. -*/ -inline int ao_get_data_from_user(me4600_ao_subdevice_t *instance, int count, - int *user_values) -{ - int i, err; - int empty_space; - int copied; - int value; - - empty_space = me_circ_buf_space(&instance->circ_buf); - //We have only this space free. - copied = (count < empty_space) ? count : empty_space; - for (i = 0; i < copied; i++) { //Copy from user to buffer - if ((err = get_user(value, (int *)(user_values + i)))) { - PERROR - ("BUFFER LOADED: get_user(0x%p) return an error: %d. idx=%d\n", - user_values + i, err, instance->ao_idx); - return -ME_ERRNO_INTERNAL; - } - /// @note The analog output in me4600 series has size of 16 bits. - *(instance->circ_buf.buf + instance->circ_buf.head) = - (uint16_t) value; - instance->circ_buf.head++; - instance->circ_buf.head &= instance->circ_buf.mask; - } - - PINFO("BUFFER LOADED %d values. idx=%d\n", copied, instance->ao_idx); - return copied; -} - -/** @brief Checking actual hardware and logical state. -* @param instance The subdevice instance (pointer). -*/ -static void me4600_ao_work_control_task(struct work_struct *work) -{ - me4600_ao_subdevice_t *instance; - unsigned long cpu_flags = 0; - uint32_t status; - uint32_t ctrl; - uint32_t synch; - int reschedule = 0; - int signaling = 0; - - instance = - container_of((void *)work, me4600_ao_subdevice_t, ao_control_task); - PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, - instance->ao_idx); - - status = inl(instance->status_reg); - PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->status_reg - instance->reg_base, status); - - switch (instance->status) { // Checking actual mode. - - // Not configured for work. - case ao_status_none: - break; - - //This are stable modes. No need to do anything. (?) - case ao_status_single_configured: - case ao_status_stream_configured: - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - PERROR("Shouldn't be running!.\n"); - break; - - case ao_status_stream_end: - if (!instance->fifo) { - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - case ao_status_single_end: - if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop. - - // Wait for stop. - reschedule = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | ME4600_AO_CTRL_BIT_STOP - | ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); - ctrl &= - ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - break; - - // Single modes - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - - if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. - if (((instance->fifo) - && (!(status & ME4600_AO_STATUS_BIT_EF))) - || (!(instance->fifo))) { // Single is in end state. - PDEBUG("Single call has been complited.\n"); - - // Set correct value for single_read(); - instance->single_value = - instance->single_value_in_fifo; - - // Set status as 'ao_status_single_end' - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - // Wait for stop ISM. - reschedule = 1; - - break; - } - } - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); - /// Fix for timeout error. - ctrl &= - ~(ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); - if (instance->fifo) { //Disabling FIFO - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - spin_lock(instance->preload_reg_lock); - //Remove from synchronous start. Block triggering from this output. - synch = inl(instance->preload_reg); - synch &= - ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << - instance->ao_idx); - if (!(instance->fifo)) { // No FIFO - set to single safe mode - synch |= - ME4600_AO_SYNC_HOLD << instance->ao_idx; - } - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch); - spin_unlock(instance->preload_reg_lock); - - if (!(instance->fifo)) { // No FIFO - // Restore old settings. - PDEBUG("Write old value back to register.\n"); - outl(instance->single_value, - instance->single_reg); - PDEBUG_REG - ("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - instance->single_value); - } - // Set correct value for single_read(); - instance->single_value_in_fifo = instance->single_value; - - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - } - // Wait for stop. - reschedule = 1; - break; - - // Stream modes - case ao_status_stream_run_wait: - if (!instance->fifo) { - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (status & ME4600_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish. - instance->status = ao_status_stream_run; - - // Signal end of this step - signaling = 1; - } else { // State machine is not working. - if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already! - instance->status = ao_status_stream_end; - - // Signal the end. - signaling = 1; - // Wait for stop. - reschedule = 1; - break; - } - } - - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP | - ME4600_AO_CTRL_BIT_RESET_IRQ; - ctrl &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - spin_lock(instance->preload_reg_lock); - //Remove from synchronous start. Block triggering from this output. - synch = inl(instance->preload_reg); - synch &= - ~((ME4600_AO_SYNC_HOLD | ME4600_AO_SYNC_EXT_TRIG) << - instance->ao_idx); - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch); - spin_unlock(instance->preload_reg_lock); - - instance->status = ao_status_stream_end; - - // Signal the end. - signaling = 1; - } - // Wait for stop. - reschedule = 1; - break; - - case ao_status_stream_run: - if (!instance->fifo) { - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error. - // BROKEN PIPE! - if (!(status & ME4600_AO_STATUS_BIT_EF)) { // FIFO is empty. - if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. - if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown. - PDEBUG - ("ISM stoped. No data in FIFO. Buffer is not empty.\n"); - instance->status = - ao_status_stream_end; - } else { - PERROR - ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n"); - instance->status = - ao_status_stream_buffer_error; - } - } else { // Software buffer is empty. - PDEBUG - ("ISM stoped. No data in FIFO. Buffer is empty.\n"); - instance->status = ao_status_stream_end; - } - } else { // There are still datas in FIFO. - if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. - PERROR - ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n"); - } else { // Software buffer is empty. - PERROR - ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n"); - } - instance->status = ao_status_stream_fifo_error; - - } - - // Signal the failure. - signaling = 1; - break; - } - // Wait for stop. - reschedule = 1; - break; - - case ao_status_stream_end_wait: - if (!instance->fifo) { - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (!(status & ME4600_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish. - instance->status = ao_status_stream_end; - signaling = 1; - } - // State machine is working. - reschedule = 1; - break; - - default: - PERROR_CRITICAL("Status is in wrong state (%d)!\n", - instance->status); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - - } - - if (signaling) { //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } - - if (instance->ao_control_task_flag && reschedule) { // Reschedule task - queue_delayed_work(instance->me4600_workqueue, - &instance->ao_control_task, 1); - } else { - PINFO("<%s> Ending control task.\n", __func__); - } - -} -#else -/// @note SPECIAL BUILD FOR BOSCH -/// @author Guenter Gebhardt -static int me4600_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t tmp; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status); - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= ~(0x10001 << instance->ao_idx); - outl(tmp, instance->preload_reg); - *instance->preload_flags &= ~(0x1 << instance->ao_idx); - spin_unlock(instance->preload_reg_lock); - - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - - while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; - - outl(ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP, - instance->ctrl_reg); - - outl(0x8000, instance->single_reg); - - instance->single_value = 0x8000; - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - if (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - if (channel == 0) { - if (single_config == 0) { - if (ref == ME_REF_AO_GROUND) { - if (trig_chan == ME_TRIG_CHAN_DEFAULT) { - if (trig_type == ME_TRIG_TYPE_SW) { - tmp = inl(instance->ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - - spin_lock(instance-> - preload_reg_lock); - tmp = - inl(instance->preload_reg); - tmp &= - ~(0x10001 << instance-> - ao_idx); - outl(tmp, - instance->preload_reg); - *instance->preload_flags &= - ~(0x1 << instance->ao_idx); - spin_unlock(instance-> - preload_reg_lock); - } else if (trig_type == - ME_TRIG_TYPE_EXT_DIGITAL) { - if (trig_edge == - ME_TRIG_EDGE_RISING) { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - outl(tmp, - instance-> - ctrl_reg); - } else if (trig_edge == - ME_TRIG_EDGE_FALLING) - { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - outl(tmp, - instance-> - ctrl_reg); - } else if (trig_edge == - ME_TRIG_EDGE_ANY) { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - outl(tmp, - instance-> - ctrl_reg); - } else { - PERROR - ("Invalid trigger edge.\n"); - err = - ME_ERRNO_INVALID_TRIG_EDGE; - goto ERROR; - } - - spin_lock(instance-> - preload_reg_lock); - - tmp = - inl(instance->preload_reg); - tmp &= - ~(0x10001 << instance-> - ao_idx); - tmp |= 0x1 << instance->ao_idx; - outl(tmp, - instance->preload_reg); - *instance->preload_flags &= - ~(0x1 << instance->ao_idx); - spin_unlock(instance-> - preload_reg_lock); - } else { - PERROR - ("Invalid trigger type.\n"); - err = - ME_ERRNO_INVALID_TRIG_TYPE; - goto ERROR; - } - } else if (trig_chan == - ME_TRIG_CHAN_SYNCHRONOUS) { - if (trig_type == ME_TRIG_TYPE_SW) { - tmp = inl(instance->ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - - spin_lock(instance-> - preload_reg_lock); - tmp = - inl(instance->preload_reg); - tmp &= - ~(0x10001 << instance-> - ao_idx); - tmp |= 0x1 << instance->ao_idx; - outl(tmp, - instance->preload_reg); - *instance->preload_flags |= - 0x1 << instance->ao_idx; - spin_unlock(instance-> - preload_reg_lock); - } else if (trig_type == - ME_TRIG_TYPE_EXT_DIGITAL) { - if (trig_edge == - ME_TRIG_EDGE_RISING) { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - } else if (trig_edge == - ME_TRIG_EDGE_FALLING) - { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - outl(tmp, - instance-> - ctrl_reg); - } else if (trig_edge == - ME_TRIG_EDGE_ANY) { - tmp = - inl(instance-> - ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, - instance-> - ctrl_reg); - tmp = - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE - | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - outl(tmp, - instance-> - ctrl_reg); - } else { - PERROR - ("Invalid trigger edge.\n"); - err = - ME_ERRNO_INVALID_TRIG_EDGE; - goto ERROR; - } - - spin_lock(instance-> - preload_reg_lock); - - tmp = - inl(instance->preload_reg); - tmp |= - 0x10001 << instance->ao_idx; - outl(tmp, - instance->preload_reg); - *instance->preload_flags &= - ~(0x1 << instance->ao_idx); - spin_unlock(instance-> - preload_reg_lock); - } else { - PERROR - ("Invalid trigger type.\n"); - err = - ME_ERRNO_INVALID_TRIG_TYPE; - goto ERROR; - } - } else { - PERROR - ("Invalid trigger channel specified.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - } else { - PERROR("Invalid analog reference specified.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - } else { - PERROR("Invalid single config specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - goto ERROR; - } - } else { - PERROR("Invalid channel number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - -ERROR: - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - - if (tmp & 0x3) { - PERROR("Not in single mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } else { - *value = instance->single_value; - } - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long mask = 0; - unsigned long tmp; - unsigned long cpu_flags; - int i; - wait_queue_head_t queue; - unsigned long j; - unsigned long delay = 0; - - PDEBUG("executed.\n"); - - init_waitqueue_head(&queue); - - instance = (me4600_ao_subdevice_t *) subdevice; - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - tmp = inl(instance->ctrl_reg); - - if (tmp & 0x3) { - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - PERROR("Not in single mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - - if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { - outl(value, instance->single_reg); - instance->single_value = value; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - j = jiffies; - - while (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM) { - interruptible_sleep_on_timeout(&queue, 1); - - if (signal_pending(current)) { - PERROR - ("Wait on external trigger interrupted by signal.\n"); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (delay && ((jiffies - j) > delay)) { - PERROR("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) - == (0x10001 << instance->ao_idx)) { - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { - tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - outl(tmp, instance->ctrl_reg); - outl(value, instance->single_reg); - instance->single_value = value; - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - j = jiffies; - - while (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM) { - interruptible_sleep_on_timeout(&queue, - 1); - - if (signal_pending(current)) { - PERROR - ("Wait on external trigger interrupted by signal.\n"); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (delay && ((jiffies - j) > delay)) { - PERROR("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } - } else { - outl(value, instance->single_reg); - instance->single_value = value; - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) - == (0x1 << instance->ao_idx)) { - outl(value, instance->single_reg); - instance->single_value = value; - - PDEBUG("Synchronous SW, flags = 0x%X.\n", flags); - - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { - PDEBUG("Trigger synchronous SW.\n"); - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - - for (i = 0; i < ME4600_AO_MAX_SUBDEVICES; i++) { - if ((*instance->preload_flags & (0x1 << i))) { - if ((tmp & (0x10001 << i)) == - (0x1 << i)) { - mask |= 0x1 << i; - } - } - } - - tmp &= ~(mask); - - outl(tmp, instance->preload_reg); - spin_unlock(instance->preload_reg_lock); - } - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } else { - outl(value, instance->single_reg); - instance->single_value = value; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } - -ERROR: - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long ctrl; - unsigned long tmp; - unsigned long cpu_flags; - uint64_t conv_ticks; - unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; - unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - conv_ticks = - (uint64_t) conv_start_ticks_low + - ((uint64_t) conv_start_ticks_high << 32); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - if ((inl(instance->status_reg)) & ME4600_AO_STATUS_BIT_FSM) { - PERROR("Subdevice is busy.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - ctrl = inl(instance->ctrl_reg); - ctrl |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(ctrl, instance->ctrl_reg); - ctrl = ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(ctrl, instance->ctrl_reg); - - if (count != 1) { - PERROR("Invalid stream configuration list count specified.\n"); - err = ME_ERRNO_INVALID_CONFIG_LIST_COUNT; - goto ERROR; - } - - if (config_list[0].iChannel != 0) { - PERROR("Invalid channel number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - goto ERROR; - } - - if (config_list[0].iStreamConfig != 0) { - PERROR("Invalid stream config specified.\n"); - err = ME_ERRNO_INVALID_STREAM_CONFIG; - goto ERROR; - } - - if (config_list[0].iRef != ME_REF_AO_GROUND) { - PERROR("Invalid analog reference.\n"); - err = ME_ERRNO_INVALID_REF; - goto ERROR; - } - - if ((trigger->iAcqStartTicksLow != 0) - || (trigger->iAcqStartTicksHigh != 0)) { - PERROR - ("Invalid acquisition start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_ARG; - goto ERROR; - } - - switch (trigger->iAcqStartTrigType) { - - case ME_TRIG_TYPE_SW: - break; - - case ME_TRIG_TYPE_EXT_DIGITAL: - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - - switch (trigger->iAcqStartTrigEdge) { - - case ME_TRIG_EDGE_RISING: - break; - - case ME_TRIG_EDGE_FALLING: - ctrl |= ME4600_AO_CTRL_BIT_EX_TRIG_EDGE; - - break; - - case ME_TRIG_EDGE_ANY: - ctrl |= - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE | - ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - - break; - - default: - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - - err = ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - - goto ERROR; - - break; - } - - break; - - default: - PERROR("Invalid acquisition start trigger type specified.\n"); - - err = ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - - goto ERROR; - - break; - } - - switch (trigger->iScanStartTrigType) { - - case ME_TRIG_TYPE_FOLLOW: - break; - - default: - PERROR("Invalid scan start trigger type specified.\n"); - - err = ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - - goto ERROR; - - break; - } - - switch (trigger->iConvStartTrigType) { - - case ME_TRIG_TYPE_TIMER: - if ((conv_ticks < ME4600_AO_MIN_CHAN_TICKS) - || (conv_ticks > ME4600_AO_MAX_CHAN_TICKS)) { - PERROR - ("Invalid conv start trigger argument specified.\n"); - err = ME_ERRNO_INVALID_CONV_START_ARG; - goto ERROR; - } - - break; - - default: - PERROR("Invalid conv start trigger type specified.\n"); - - err = ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - - goto ERROR; - - break; - } - - /* Preset to hardware wraparound mode */ - instance->flags &= ~(ME4600_AO_FLAGS_SW_WRAP_MODE_MASK); - - switch (trigger->iScanStopTrigType) { - - case ME_TRIG_TYPE_NONE: - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - /* Set flags to indicate usage of software mode. */ - instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_INF; - instance->wrap_count = 0; - instance->wrap_remaining = 0; - } - - break; - - case ME_TRIG_TYPE_COUNT: - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iScanStopCount <= 0) { - PERROR("Invalid scan stop count specified.\n"); - err = ME_ERRNO_INVALID_SCAN_STOP_ARG; - goto ERROR; - } - - /* Set flags to indicate usage of software mode. */ - instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN; - instance->wrap_count = trigger->iScanStopCount; - instance->wrap_remaining = trigger->iScanStopCount; - } else { - PERROR("Invalid scan stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - - break; - - default: - PERROR("Invalid scan stop trigger type specified.\n"); - - err = ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; - - goto ERROR; - - break; - } - - switch (trigger->iAcqStopTrigType) { - - case ME_TRIG_TYPE_NONE: - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iAcqStopCount <= 0) { - PERROR("Invalid acq stop count specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_ARG; - goto ERROR; - } - - /* Set flags to indicate usage of software mode. */ - instance->flags |= ME4600_AO_FLAGS_SW_WRAP_MODE_FIN; - instance->wrap_count = trigger->iAcqStopCount; - instance->wrap_remaining = trigger->iAcqStopCount; - } else { - PERROR("Invalid acp stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - } - - break; - - default: - PERROR("Invalid acq stop trigger type specified.\n"); - err = ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - goto ERROR; - break; - } - - switch (trigger->iAcqStartTrigChan) { - - case ME_TRIG_CHAN_DEFAULT: - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= ~(0x10001 << instance->ao_idx); - outl(tmp, instance->preload_reg); - spin_unlock(instance->preload_reg_lock); - - break; - - case ME_TRIG_CHAN_SYNCHRONOUS: - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) { - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= ~(0x10001 << instance->ao_idx); - outl(tmp, instance->preload_reg); - tmp |= 0x1 << instance->ao_idx; - outl(tmp, instance->preload_reg); - spin_unlock(instance->preload_reg_lock); - } else { - ctrl &= ~(ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG); - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= ~(0x10001 << instance->ao_idx); - outl(tmp, instance->preload_reg); - tmp |= 0x10000 << instance->ao_idx; - outl(tmp, instance->preload_reg); - spin_unlock(instance->preload_reg_lock); - } - - break; - - default: - PERROR("Invalid acq start trigger channel specified.\n"); - err = ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; - goto ERROR; - - break; - } - - outl(conv_ticks - 2, instance->timer_reg); - - if (flags & ME_IO_STREAM_CONFIG_BIT_PATTERN) { - if (instance->ao_idx == 3) { - ctrl |= ME4600_AO_CTRL_BIT_ENABLE_DO; - } else { - err = ME_ERRNO_INVALID_FLAGS; - goto ERROR; - } - } else { - if (instance->ao_idx == 3) { - ctrl &= ~ME4600_AO_CTRL_BIT_ENABLE_DO; - } - } - - /* Set hardware mode. */ - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - ctrl |= ME4600_AO_CTRL_BIT_MODE_0; - } else { - ctrl |= ME4600_AO_CTRL_BIT_MODE_1; - } - - PDEBUG("Preload word = 0x%X.\n", inl(instance->preload_reg)); - - PDEBUG("Ctrl word = 0x%lX.\n", ctrl); - outl(ctrl, instance->ctrl_reg); // Write the control word - -ERROR: - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - long j; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - *count = 0; - - ME_SUBDEVICE_ENTER; - - if (t) { - j = jiffies; - wait_event_interruptible_timeout(instance->wait_queue, - ((me_circ_buf_space - (&instance->circ_buf)) - || !(inl(instance->status_reg) - & - ME4600_AO_STATUS_BIT_FSM)), - t); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PERROR("AO subdevice is not running.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - } else if ((jiffies - j) >= t) { - PERROR("Wait on values timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } else { - *count = me_circ_buf_space(&instance->circ_buf); - } - } else { - wait_event_interruptible(instance->wait_queue, - ((me_circ_buf_space - (&instance->circ_buf)) - || !(inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM))); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PERROR("AO subdevice is not running.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - } else { - *count = me_circ_buf_space(&instance->circ_buf); - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static void stop_immediately(me4600_ao_subdevice_t *instance) -{ - unsigned long cpu_flags; - uint32_t tmp; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - - while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); -} - -static int me4600_ao_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags = 0; - unsigned long ref; - unsigned long tmp; - unsigned long delay = 0; - wait_queue_head_t queue; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - init_waitqueue_head(&queue); - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - ME_SUBDEVICE_ENTER - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - tmp = inl(instance->ctrl_reg); - - switch (tmp & (ME4600_AO_CTRL_MASK_MODE)) { - - case 0: // Single mode - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - PERROR("Subdevice is configured in single mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - - case 1: // Wraparound mode - if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Normal wraparound with external trigger - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (start_mode == ME_START_MODE_BLOCKING) { - init_waitqueue_head(&queue); - - if (delay) { - ref = jiffies; - - while (! - (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending(current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (((jiffies - ref) >= delay)) { - PERROR - ("Timeout reached.\n"); - stop_immediately - (instance); - err = ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } else { - while (! - (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending(current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - } - } - } else if (start_mode == ME_START_MODE_NONBLOCKING) { - } else { - PERROR("Invalid start mode specified.\n"); - err = ME_ERRNO_INVALID_START_MODE; - goto ERROR; - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - tmp |= ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG; - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - - if (start_mode == ME_START_MODE_BLOCKING) { - init_waitqueue_head(&queue); - - if (delay) { - ref = jiffies; - - while (! - (inl - (instance-> - status_reg) & - ME4600_AO_STATUS_BIT_FSM)) - { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending - (current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (((jiffies - ref) >= - delay)) { - PERROR - ("Timeout reached.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } else { - while (! - (inl - (instance-> - status_reg) & - ME4600_AO_STATUS_BIT_FSM)) - { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending - (current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_SIGNAL; - goto ERROR; - } - } - } - } else if (start_mode == - ME_START_MODE_NONBLOCKING) { - } else { - PERROR - ("Invalid start mode specified.\n"); - err = ME_ERRNO_INVALID_START_MODE; - goto ERROR; - } - } else { - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - - outl(tmp, instance->ctrl_reg); - - if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - outl(0x8000, instance->single_reg); - instance->single_value = 0x8000; - } - - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } else { // Software start - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_IRQ | - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - - outl(tmp, instance->ctrl_reg); - - outl(0x8000, instance->single_reg); - instance->single_value = 0x8000; - - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - - break; - - case 2: // Continuous mode - if (tmp & ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG) { // Externally triggered - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - instance->wrap_remaining = instance->wrap_count; - instance->circ_buf.tail = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (start_mode == ME_START_MODE_BLOCKING) { - init_waitqueue_head(&queue); - - if (delay) { - ref = jiffies; - - while (! - (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending(current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (((jiffies - ref) >= delay)) { - PERROR - ("Timeout reached.\n"); - stop_immediately - (instance); - err = ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } else { - while (! - (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending(current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - } - } - } else if (start_mode == ME_START_MODE_NONBLOCKING) { - /* Do nothing */ - } else { - PERROR("Invalid start mode specified.\n"); - stop_immediately(instance); - err = ME_ERRNO_INVALID_START_MODE; - goto ERROR; - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x10000 << instance->ao_idx)) { // Synchronous with external trigger - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - tmp |= - ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG | - ME4600_AO_CTRL_BIT_ENABLE_IRQ; - tmp &= - ~(ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, instance->ctrl_reg); - instance->wrap_remaining = instance->wrap_count; - instance->circ_buf.tail = 0; - - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - - if (start_mode == ME_START_MODE_BLOCKING) { - init_waitqueue_head(&queue); - - if (delay) { - ref = jiffies; - - while (! - (inl - (instance-> - status_reg) & - ME4600_AO_STATUS_BIT_FSM)) - { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending - (current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_SIGNAL; - goto ERROR; - } - - if (((jiffies - ref) >= - delay)) { - PERROR - ("Timeout reached.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_TIMEOUT; - goto ERROR; - } - } - } else { - while (! - (inl - (instance-> - status_reg) & - ME4600_AO_STATUS_BIT_FSM)) - { - interruptible_sleep_on_timeout - (&queue, 1); - - if (signal_pending - (current)) { - PERROR - ("Wait on start of state machine interrupted.\n"); - stop_immediately - (instance); - err = - ME_ERRNO_SIGNAL; - goto ERROR; - } - } - } - } else if (start_mode == - ME_START_MODE_NONBLOCKING) { - } else { - PERROR - ("Invalid start mode specified.\n"); - stop_immediately(instance); - err = ME_ERRNO_INVALID_START_MODE; - goto ERROR; - } - } else { - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - tmp &= - ~(ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - outl(tmp, instance->ctrl_reg); - instance->wrap_remaining = instance->wrap_count; - instance->circ_buf.tail = 0; - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - } - } else if ((inl(instance->preload_reg) & (0x10001 << instance->ao_idx)) == (0x1 << instance->ao_idx)) { // Synchronous wraparound with sw trigger - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - instance->wrap_remaining = instance->wrap_count; - instance->circ_buf.tail = 0; - PDEBUG("CTRL Reg = 0x%X.\n", inl(instance->ctrl_reg)); - outl(tmp, instance->ctrl_reg); - - if (flags & ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - outl(0x8000, instance->single_reg); - instance->single_value = 0x8000; - } - - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } else { // Software start - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR("Conversion is already running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp &= - ~(ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP); - - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - outl(0x8000, instance->single_reg); - instance->single_value = 0x8000; - instance->wrap_remaining = instance->wrap_count; - instance->circ_buf.tail = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - - break; - - default: - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - PERROR("Invalid mode configured.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - -ERROR: - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - wait_queue_head_t queue; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - init_waitqueue_head(&queue); - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - ME_SUBDEVICE_ENTER; - - if (wait == ME_WAIT_NONE) { - *status = - (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ? - ME_STATUS_BUSY : ME_STATUS_IDLE; - *values = me_circ_buf_space(&instance->circ_buf); - } else if (wait == ME_WAIT_IDLE) { - while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) { - interruptible_sleep_on_timeout(&queue, 1); - - if (instance->flags & ME4600_AO_FLAGS_BROKEN_PIPE) { - PERROR("Output stream was interrupted.\n"); - *status = ME_STATUS_ERROR; - err = ME_ERRNO_SUCCESS; - goto ERROR; - } - - if (signal_pending(current)) { - PERROR - ("Wait on state machine interrupted by signal.\n"); - *status = ME_STATUS_INVALID; - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - } - - *status = ME_STATUS_IDLE; - - *values = me_circ_buf_space(&instance->circ_buf); - } else { - PERROR("Invalid wait argument specified.\n"); - *status = ME_STATUS_INVALID; - err = ME_ERRNO_INVALID_WAIT; - goto ERROR; - } - -ERROR: - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me4600_ao_subdevice_t *instance; - unsigned long cpu_flags; - unsigned long tmp; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - ME_SUBDEVICE_ENTER; - - if (stop_mode == ME_STOP_MODE_IMMEDIATE) { - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - tmp |= - ME4600_AO_CTRL_BIT_STOP | ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - - while (inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM) ; - - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_STOP; - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } else { - PERROR("Invalid stop mode specified.\n"); - err = ME_ERRNO_INVALID_STOP_MODE; - goto ERROR; - } - -ERROR: - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ao_io_stream_write(me_subdevice_t *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me4600_ao_subdevice_t *instance; - unsigned long tmp; - int i; - int value; - int cnt = *count; - int c; - int k; - int ret = 0; - unsigned long cpu_flags = 0; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - if (!instance->fifo) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - ME_SUBDEVICE_ENTER; - - if (*count <= 0) { - PERROR("Invalid count of values specified.\n"); - err = ME_ERRNO_INVALID_VALUE_COUNT; - goto ERROR; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - tmp = inl(instance->ctrl_reg); - - switch (tmp & 0x3) { - - case 1: // Wraparound mode - if (instance->bosch_fw) { // Bosch firmware - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (cnt != 7) { - PERROR - ("Invalid count of values specified. 7 expected.\n"); - err = ME_ERRNO_INVALID_VALUE_COUNT; - goto ERROR; - } - - for (i = 0; i < 7; i++) { - if (get_user(value, values)) { - PERROR - ("Can't copy value from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - if (i == 0) { - /* Maximum voltage */ - value <<= 16; - value |= - inl(instance->reg_base + - 0xD4) & 0xFFFF; - outl(value, instance->reg_base + 0xD4); - } else if (i == 1) { - /* Minimum voltage */ - value &= 0xFFFF; - value |= - inl(instance->reg_base + - 0xD4) & 0xFFFF0000; - outl(value, instance->reg_base + 0xD4); - } else if (i == 2) { - /* Delta up */ - value <<= 16; - value |= - inl(instance->reg_base + - 0xD8) & 0xFFFF; - outl(value, instance->reg_base + 0xD8); - } else if (i == 3) { - /* Delta down */ - value &= 0xFFFF; - value |= - inl(instance->reg_base + - 0xD8) & 0xFFFF0000; - outl(value, instance->reg_base + 0xD8); - } else if (i == 4) { - /* Start value */ - outl(value, instance->reg_base + 0xDC); - } else if (i == 5) { - /* Invert */ - if (value) { - value = inl(instance->ctrl_reg); - value |= 0x100; - outl(value, instance->ctrl_reg); - } else { - value = inl(instance->ctrl_reg); - value &= ~0x100; - outl(value, instance->ctrl_reg); - } - } else if (i == 6) { - /* Timer for positive ramp */ - outl(value, instance->reg_base + 0xE0); - } - - values++; - } - } else { // Normal firmware - PDEBUG("Write for wraparound mode.\n"); - - if (inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR - ("There is already a conversion running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp |= ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_FIFO; - outl(tmp, instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; - - if ((*count > ME4600_AO_FIFO_COUNT) || - ((instance-> - flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == - ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) { - tmp &= - ~(ME4600_AO_CTRL_BIT_MODE_0 | - ME4600_AO_CTRL_BIT_MODE_1); - tmp |= ME4600_AO_CTRL_BIT_MODE_1; - } - - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if ((*count <= ME4600_AO_FIFO_COUNT) && - ((instance-> - flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == - ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) { - for (i = 0; i < *count; i++) { - if (get_user(value, values + i)) { - PERROR - ("Cannot copy value from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - if (instance->ao_idx & 0x1) - value <<= 16; - - outl(value, instance->fifo_reg); - } - } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) && - ((instance-> - flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) - == ME4600_AO_FLAGS_SW_WRAP_MODE_INF)) { - for (i = 0; i < *count; i++) { - if (get_user(value, values + i)) { - PERROR - ("Cannot copy value from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - instance->circ_buf.buf[i] = value; /* Used to hold the values. */ - } - - instance->circ_buf.tail = 0; /* Used as the current read position. */ - instance->circ_buf.head = *count; /* Used as the buffer size. */ - - /* Preload the FIFO. */ - - for (i = 0; i < ME4600_AO_FIFO_COUNT; - i++, instance->circ_buf.tail++) { - if (instance->circ_buf.tail >= - instance->circ_buf.head) - instance->circ_buf.tail = 0; - - if (instance->ao_idx & 0x1) - outl(instance->circ_buf. - buf[instance->circ_buf. - tail] << 16, - instance->fifo_reg); - else - outl(instance->circ_buf. - buf[instance->circ_buf. - tail], - instance->fifo_reg); - } - } else if ((*count <= ME4600_AO_CIRC_BUF_COUNT) && - ((instance-> - flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) - == ME4600_AO_FLAGS_SW_WRAP_MODE_FIN)) { - unsigned int preload_count; - - for (i = 0; i < *count; i++) { - if (get_user(value, values + i)) { - PERROR - ("Cannot copy value from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - instance->circ_buf.buf[i] = value; /* Used to hold the values. */ - } - - instance->circ_buf.tail = 0; /* Used as the current read position. */ - instance->circ_buf.head = *count; /* Used as the buffer size. */ - - /* Try to preload the whole FIFO. */ - preload_count = ME4600_AO_FIFO_COUNT; - - if (preload_count > instance->wrap_count) - preload_count = instance->wrap_count; - - /* Preload the FIFO. */ - for (i = 0; i < preload_count; - i++, instance->circ_buf.tail++) { - if (instance->circ_buf.tail >= - instance->circ_buf.head) - instance->circ_buf.tail = 0; - - if (instance->ao_idx & 0x1) - outl(instance->circ_buf. - buf[instance->circ_buf. - tail] << 16, - instance->fifo_reg); - else - outl(instance->circ_buf. - buf[instance->circ_buf. - tail], - instance->fifo_reg); - } - - instance->wrap_remaining = - instance->wrap_count - preload_count; - } else { - PERROR("To many values written.\n"); - err = ME_ERRNO_INVALID_VALUE_COUNT; - goto ERROR; - } - } - - break; - - case 2: // Continuous mode - /* Check if in SW wrapround mode */ - if (instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) { - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - PERROR("Subdevice is configured SW wrapround mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - - switch (write_mode) { - - case ME_WRITE_MODE_BLOCKING: - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - PDEBUG("Write for blocking continuous mode.\n"); - - while (cnt > 0) { - wait_event_interruptible(instance->wait_queue, - (c = - me_circ_buf_space_to_end - (&instance-> - circ_buf))); - - if (instance-> - flags & ME4600_AO_FLAGS_BROKEN_PIPE) { - PERROR - ("Broken pipe in blocking write.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - goto ERROR; - } else if (signal_pending(current)) { - PERROR - ("Wait for free buffer interrupted from signal.\n"); - err = ME_ERRNO_SIGNAL; - goto ERROR; - } - - PDEBUG("Space to end = %d.\n", c); - - /* Only able to write size of free buffer or size of count */ - - if (cnt < c) - c = cnt; - k = sizeof(int) * c; - k -= copy_from_user(instance->circ_buf.buf + - instance->circ_buf.head, - values, k); - c = k / sizeof(int); - - PDEBUG("Copy %d values from user space.\n", c); - - if (!c) { - PERROR - ("Cannot copy values from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - instance->circ_buf.head = - (instance->circ_buf.head + - c) & (instance->circ_buf.mask); - - values += c; - cnt -= c; - ret += c; - - /* Values are now available so enable interrupts */ - spin_lock_irqsave(&instance->subdevice_lock, - cpu_flags); - - if (me_circ_buf_space(&instance->circ_buf)) { - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - } - - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - } - - *count = ret; - - break; - - case ME_WRITE_MODE_NONBLOCKING: - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - PDEBUG("Write for non blocking continuous mode.\n"); - - while (cnt > 0) { - if (instance-> - flags & ME4600_AO_FLAGS_BROKEN_PIPE) { - PERROR - ("ME4600:Broken pipe in nonblocking write.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - goto ERROR; - } - - c = me_circ_buf_space_to_end(&instance-> - circ_buf); - - if (!c) { - PDEBUG - ("Returning from nonblocking write.\n"); - break; - } - - PDEBUG("Space to end = %d.\n", c); - - /* Only able to write size of free buffer or size of count */ - - if (cnt < c) - c = cnt; - k = sizeof(int) * c; - k -= copy_from_user(instance->circ_buf.buf + - instance->circ_buf.head, - values, k); - c = k / sizeof(int); - - PDEBUG("Copy %d values from user space.\n", c); - - if (!c) { - PERROR - ("Cannot copy values from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - instance->circ_buf.head = - (instance->circ_buf.head + - c) & (instance->circ_buf.mask); - - values += c; - cnt -= c; - ret += c; - - /* Values are now available so enable interrupts */ - spin_lock_irqsave(&instance->subdevice_lock, - cpu_flags); - - if (me_circ_buf_space(&instance->circ_buf)) { - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - } - - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - } - - *count = ret; - - break; - - case ME_WRITE_MODE_PRELOAD: - PDEBUG("Write for preload continuous mode.\n"); - - if ((inl(instance->status_reg) & - ME4600_AO_STATUS_BIT_FSM)) { - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - PERROR - ("Can't Preload DAC FIFO while conversion is running.\n"); - err = ME_ERRNO_SUBDEVICE_BUSY; - goto ERROR; - } - - tmp = inl(instance->ctrl_reg); - - tmp |= - ME4600_AO_CTRL_BIT_STOP | - ME4600_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(tmp, instance->ctrl_reg); - tmp &= - ~(ME4600_AO_CTRL_BIT_ENABLE_FIFO | - ME4600_AO_CTRL_BIT_ENABLE_IRQ); - outl(tmp, instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_ENABLE_FIFO; - outl(tmp, instance->ctrl_reg); - - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - instance->flags &= ~ME4600_AO_FLAGS_BROKEN_PIPE; - - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - c = ME4600_AO_FIFO_COUNT; - - if (cnt < c) - c = cnt; - - for (i = 0; i < c; i++) { - if (get_user(value, values)) { - PERROR - ("Can't copy value from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - if (instance->ao_idx & 0x1) - value <<= 16; - - outl(value, instance->fifo_reg); - - values++; - } - - cnt -= c; - - ret += c; - - PDEBUG("Wrote %d values to fifo.\n", c); - - while (1) { - c = me_circ_buf_space_to_end(&instance-> - circ_buf); - - if (c == 0) - break; - - if (cnt < c) - c = cnt; - - if (c <= 0) - break; - - k = sizeof(int) * c; - - k -= copy_from_user(instance->circ_buf.buf + - instance->circ_buf.head, - values, k); - - c = k / sizeof(int); - - PDEBUG("Wrote %d values to circular buffer.\n", - c); - - if (!c) { - PERROR - ("Can't copy values from user space.\n"); - err = ME_ERRNO_INTERNAL; - goto ERROR; - } - - instance->circ_buf.head = - (instance->circ_buf.head + - c) & (instance->circ_buf.mask); - - values += c; - cnt -= c; - ret += c; - } - - *count = ret; - - break; - - default: - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - PERROR("Invalid write mode specified.\n"); - - err = ME_ERRNO_INVALID_WRITE_MODE; - - goto ERROR; - } - - break; - - default: // Single mode of invalid - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - PERROR("Subdevice is configured in single mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - goto ERROR; - } - -ERROR: - - ME_SUBDEVICE_EXIT; - - return err; -} - -static irqreturn_t me4600_ao_isr(int irq, void *dev_id) -{ - unsigned long tmp; - int value; - me4600_ao_subdevice_t *instance = dev_id; - int i; - int c = 0; - int c1 = 0; - - if (irq != instance->irq) { - PDEBUG("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - if (!((0x1 << (instance->ao_idx + 3)) & inl(instance->irq_status_reg))) { - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - tmp = inl(instance->status_reg); - - if (!(tmp & ME4600_AO_STATUS_BIT_EF) && - (tmp & ME4600_AO_STATUS_BIT_HF) && - (tmp & ME4600_AO_STATUS_BIT_HF)) { - c = ME4600_AO_FIFO_COUNT; - PDEBUG("Fifo empty.\n"); - } else if ((tmp & ME4600_AO_STATUS_BIT_EF) && - (tmp & ME4600_AO_STATUS_BIT_HF) && - (tmp & ME4600_AO_STATUS_BIT_HF)) { - c = ME4600_AO_FIFO_COUNT / 2; - PDEBUG("Fifo under half full.\n"); - } else { - c = 0; - PDEBUG("Fifo full.\n"); - } - - PDEBUG("Try to write 0x%04X values.\n", c); - - if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == - ME4600_AO_FLAGS_SW_WRAP_MODE_INF) { - while (c) { - c1 = c; - - if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */ - c1 = (instance->circ_buf.head - - instance->circ_buf.tail); - - /* Write the values to the FIFO */ - for (i = 0; i < c1; i++, instance->circ_buf.tail++, c--) { - if (instance->ao_idx & 0x1) - outl(instance->circ_buf. - buf[instance->circ_buf.tail] << 16, - instance->fifo_reg); - else - outl(instance->circ_buf. - buf[instance->circ_buf.tail], - instance->fifo_reg); - } - - if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */ - instance->circ_buf.tail = 0; - } - - spin_lock(&instance->subdevice_lock); - - tmp = inl(instance->ctrl_reg); - tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(tmp, instance->ctrl_reg); - tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(tmp, instance->ctrl_reg); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PERROR("Broken pipe.\n"); - instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - } - - spin_unlock(&instance->subdevice_lock); - } else if ((instance->flags & ME4600_AO_FLAGS_SW_WRAP_MODE_MASK) == - ME4600_AO_FLAGS_SW_WRAP_MODE_FIN) { - while (c && instance->wrap_remaining) { - c1 = c; - - if (c1 > (instance->circ_buf.head - instance->circ_buf.tail)) /* Only up to the end of the buffer */ - c1 = (instance->circ_buf.head - - instance->circ_buf.tail); - - if (c1 > instance->wrap_remaining) /* Only up to count of user defined number of values */ - c1 = instance->wrap_remaining; - - /* Write the values to the FIFO */ - for (i = 0; i < c1; - i++, instance->circ_buf.tail++, c--, - instance->wrap_remaining--) { - if (instance->ao_idx & 0x1) - outl(instance->circ_buf. - buf[instance->circ_buf.tail] << 16, - instance->fifo_reg); - else - outl(instance->circ_buf. - buf[instance->circ_buf.tail], - instance->fifo_reg); - } - - if (instance->circ_buf.tail >= instance->circ_buf.head) /* Start from beginning */ - instance->circ_buf.tail = 0; - } - - spin_lock(&instance->subdevice_lock); - - tmp = inl(instance->ctrl_reg); - - if (!instance->wrap_remaining) { - PDEBUG("Finite SW wraparound done.\n"); - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - } - - tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; - - outl(tmp, instance->ctrl_reg); - tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(tmp, instance->ctrl_reg); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PERROR("Broken pipe.\n"); - instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - } - - spin_unlock(&instance->subdevice_lock); - - } else { /* Regular continuous mode */ - - while (1) { - c1 = me_circ_buf_values_to_end(&instance->circ_buf); - PDEBUG("Values to end = %d.\n", c1); - - if (c1 > c) - c1 = c; - - if (c1 <= 0) { - PDEBUG("Work done or buffer empty.\n"); - break; - } - - if (instance->ao_idx & 0x1) { - for (i = 0; i < c1; i++) { - value = - *(instance->circ_buf.buf + - instance->circ_buf.tail + - i) << 16; - outl(value, instance->fifo_reg); - } - } else - outsl(instance->fifo_reg, - instance->circ_buf.buf + - instance->circ_buf.tail, c1); - - instance->circ_buf.tail = - (instance->circ_buf.tail + - c1) & (instance->circ_buf.mask); - - PDEBUG("%d values wrote to port 0x%04X.\n", c1, - instance->fifo_reg); - - c -= c1; - } - - spin_lock(&instance->subdevice_lock); - - tmp = inl(instance->ctrl_reg); - - if (!me_circ_buf_values(&instance->circ_buf)) { - PDEBUG - ("Disable Interrupt because no values left in buffer.\n"); - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - } - - tmp |= ME4600_AO_CTRL_BIT_RESET_IRQ; - - outl(tmp, instance->ctrl_reg); - tmp &= ~ME4600_AO_CTRL_BIT_RESET_IRQ; - outl(tmp, instance->ctrl_reg); - - if (!(inl(instance->status_reg) & ME4600_AO_STATUS_BIT_FSM)) { - PDEBUG("Broken pipe in me4600_ao_isr.\n"); - instance->flags |= ME4600_AO_FLAGS_BROKEN_PIPE; - tmp &= ~ME4600_AO_CTRL_BIT_ENABLE_IRQ; - outl(tmp, instance->ctrl_reg); - } - - spin_unlock(&instance->subdevice_lock); - - wake_up_interruptible(&instance->wait_queue); - } - - return IRQ_HANDLED; -} - -static void me4600_ao_destructor(struct me_subdevice *subdevice) -{ - me4600_ao_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me4600_ao_subdevice_t *) subdevice; - - free_irq(instance->irq, instance); - kfree(instance->circ_buf.buf); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, - spinlock_t *preload_reg_lock, - uint32_t *preload_flags, - int ao_idx, int fifo, int irq) -{ - me4600_ao_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me4600_ao_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_ao_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->preload_reg_lock = preload_reg_lock; - subdevice->preload_flags = preload_flags; - - /* Allocate and initialize circular buffer */ - subdevice->circ_buf.mask = ME4600_AO_CIRC_BUF_COUNT - 1; - subdevice->circ_buf.buf = kmalloc(ME4600_AO_CIRC_BUF_SIZE, GFP_KERNEL); - - if (!subdevice->circ_buf.buf) { - PERROR("Cannot initialize subdevice base class instance.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - kfree(subdevice); - return NULL; - } - - memset(subdevice->circ_buf.buf, 0, ME4600_AO_CIRC_BUF_SIZE); - - subdevice->circ_buf.head = 0; - subdevice->circ_buf.tail = 0; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Initialize single value to 0V */ - subdevice->single_value = 0x8000; - - /* Store analog output index */ - subdevice->ao_idx = ao_idx; - - /* Store if analog output has fifo */ - subdevice->fifo = fifo; - - /* Initialize registers */ - - if (ao_idx == 0) { - subdevice->ctrl_reg = reg_base + ME4600_AO_00_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_00_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_00_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_00_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_00_TIMER_REG; - subdevice->reg_base = reg_base; - - if (inl(subdevice->reg_base + ME4600_AO_BOSCH_REG) == 0x20000) { - PINFO("Bosch firmware in use for channel 0.\n"); - subdevice->bosch_fw = 1; - } else { - subdevice->bosch_fw = 0; - } - } else if (ao_idx == 1) { - subdevice->ctrl_reg = reg_base + ME4600_AO_01_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_01_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_01_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_01_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_01_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bosch_fw = 0; - } else if (ao_idx == 2) { - subdevice->ctrl_reg = reg_base + ME4600_AO_02_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_02_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_02_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_02_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_02_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bosch_fw = 0; - } else { - subdevice->ctrl_reg = reg_base + ME4600_AO_03_CTRL_REG; - subdevice->status_reg = reg_base + ME4600_AO_03_STATUS_REG; - subdevice->fifo_reg = reg_base + ME4600_AO_03_FIFO_REG; - subdevice->single_reg = reg_base + ME4600_AO_03_SINGLE_REG; - subdevice->timer_reg = reg_base + ME4600_AO_03_TIMER_REG; - subdevice->reg_base = reg_base; - subdevice->bosch_fw = 0; - } - - subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; - subdevice->preload_reg = reg_base + ME4600_AO_LOADSETREG_XX; - - /* Register interrupt service routine */ - subdevice->irq = irq; - - if (request_irq - (subdevice->irq, me4600_ao_isr, IRQF_DISABLED | IRQF_SHARED, - ME4600_NAME, subdevice)) { - PERROR("Cannot get interrupt line.\n"); - me_subdevice_deinit((me_subdevice_t *) subdevice); - kfree(subdevice->circ_buf.buf); - kfree(subdevice); - return NULL; - } - - /* Override base class methods. */ - subdevice->base.me_subdevice_destructor = me4600_ao_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_ao_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_ao_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_ao_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me4600_ao_io_single_write; - subdevice->base.me_subdevice_io_stream_config = - me4600_ao_io_stream_config; - subdevice->base.me_subdevice_io_stream_new_values = - me4600_ao_io_stream_new_values; - subdevice->base.me_subdevice_io_stream_write = - me4600_ao_io_stream_write; - subdevice->base.me_subdevice_io_stream_start = - me4600_ao_io_stream_start; - subdevice->base.me_subdevice_io_stream_status = - me4600_ao_io_stream_status; - subdevice->base.me_subdevice_io_stream_stop = me4600_ao_io_stream_stop; - subdevice->base.me_subdevice_query_number_channels = - me4600_ao_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_ao_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_ao_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me4600_ao_query_subdevice_caps_args; - subdevice->base.me_subdevice_query_range_by_min_max = - me4600_ao_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me4600_ao_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me4600_ao_query_range_info; - subdevice->base.me_subdevice_query_timer = me4600_ao_query_timer; - - return subdevice; -} - -#endif // BOSCH - -/* Common functions -*/ - -static int me4600_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((*max - *min) < 0) { - PERROR("Invalid minimum and maximum values specified.\n"); - return ME_ERRNO_INVALID_MIN_MAX; - } - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - if ((*max <= (ME4600_AO_MAX_RANGE + 1000)) - && (*min >= ME4600_AO_MIN_RANGE)) { - *min = ME4600_AO_MIN_RANGE; - *max = ME4600_AO_MAX_RANGE; - *maxdata = ME4600_AO_MAX_DATA; - *range = 0; - } else { - PERROR("No matching range available.\n"); - return ME_ERRNO_NO_RANGE; - } - } else { - PERROR("Invalid physical unit specified.\n"); - return ME_ERRNO_INVALID_UNIT; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - *count = 1; - } else { - *count = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (range == 0) { - *unit = ME_UNIT_VOLT; - *min = ME4600_AO_MIN_RANGE; - *max = ME4600_AO_MAX_RANGE; - *maxdata = ME4600_AO_MAX_DATA; - } else { - PERROR("Invalid range number specified.\n"); - return ME_ERRNO_INVALID_RANGE; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((timer != ME_TIMER_ACQ_START) && (timer != ME_TIMER_CONV_START)) { - PERROR("Invalid timer specified.\n"); - return ME_ERRNO_INVALID_TIMER; - } - - if (instance->fifo) { //Streaming device. - *base_frequency = ME4600_AO_BASE_FREQUENCY; - if (timer == ME_TIMER_ACQ_START) { - *min_ticks = ME4600_AO_MIN_ACQ_TICKS; - *max_ticks = ME4600_AO_MAX_ACQ_TICKS; - } else if (timer == ME_TIMER_CONV_START) { - *min_ticks = ME4600_AO_MIN_CHAN_TICKS; - *max_ticks = ME4600_AO_MAX_CHAN_TICKS; - } - } else { //Not streaming device! - *base_frequency = 0; - *min_ticks = 0; - *max_ticks = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - me4600_ao_subdevice_t *instance; - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *number = 1; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - me4600_ao_subdevice_t *instance; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *type = ME_TYPE_AO; - *subtype = (instance->fifo) ? ME_SUBTYPE_STREAMING : ME_SUBTYPE_SINGLE; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - me4600_ao_subdevice_t *instance; - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *caps = - ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO : - ME_CAPS_NONE); - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count) -{ - me4600_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me4600_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (count != 1) { - PERROR("Invalid capability argument count.\n"); - return ME_ERRNO_INVALID_CAP_ARG_COUNT; - } - - switch (cap) { - case ME_CAP_AI_FIFO_SIZE: - args[0] = (instance->fifo) ? ME4600_AO_FIFO_COUNT : 0; - break; - - case ME_CAP_AI_BUFFER_SIZE: - args[0] = - (instance->circ_buf.buf) ? ME4600_AO_CIRC_BUF_COUNT : 0; - break; - - default: - PERROR("Invalid capability.\n"); - err = ME_ERRNO_INVALID_CAP; - args[0] = 0; - } - - return err; -} --- a/drivers/staging/meilhaus/me4600_ao.h +++ /dev/null @@ -1,259 +0,0 @@ -/** - * @file me4600_ao.h - * - * @brief Meilhaus ME-4000 analog output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_AO_H_ -# define _ME4600_AO_H_ - -# include -# include "mesubdevice.h" -# include "mecirc_buf.h" -# include "meioctl.h" - -# ifdef __KERNEL__ - -# ifdef BOSCH -# undef ME_SYNAPSE -# ifndef _CBUFF_32b_t -# define _CBUFF_32b_t -# endif //_CBUFF_32b_t -# endif //BOSCH - -# define ME4600_AO_MAX_SUBDEVICES 4 -# define ME4600_AO_FIFO_COUNT 4096 - -# define ME4600_AO_BASE_FREQUENCY 33000000LL - -# define ME4600_AO_MIN_ACQ_TICKS 0LL -# define ME4600_AO_MAX_ACQ_TICKS 0LL - -# define ME4600_AO_MIN_CHAN_TICKS 66LL -# define ME4600_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL - -# define ME4600_AO_MIN_RANGE -10000000 -# define ME4600_AO_MAX_RANGE 9999694 - -# define ME4600_AO_MAX_DATA 0xFFFF - -# ifdef ME_SYNAPSE -# define ME4600_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse -# else -# define ME4600_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB -# endif -# define ME4600_AO_CIRC_BUF_SIZE PAGE_SIZE< Now problems are reported in status. - -typedef enum ME4600_AO_STATUS { - ao_status_none = 0, - ao_status_single_configured, - ao_status_single_run_wait, - ao_status_single_run, - ao_status_single_end_wait, - ao_status_single_end, - ao_status_stream_configured, - ao_status_stream_run_wait, - ao_status_stream_run, - ao_status_stream_end_wait, - ao_status_stream_end, - ao_status_stream_fifo_error, - ao_status_stream_buffer_error, - ao_status_stream_error, - ao_status_last -} ME4600_AO_STATUS; - -typedef struct me4600_ao_timeout { - unsigned long start_time; - unsigned long delay; -} me4600_ao_timeout_t; - - /** - * @brief The ME-4600 analog output subdevice class. - */ -typedef struct me4600_ao_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - unsigned int ao_idx; /**< The index of this analog output on this device. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *preload_reg_lock; /**< Spin lock to protect preload_reg from concurrent access. */ - - uint32_t *preload_flags; - - /* Hardware feautres */ - unsigned int irq; /**< The interrupt request number assigned by the PCI BIOS. */ - int fifo; /**< If set this device has a FIFO. */ - int bitpattern; /**< If set this device use bitpattern. */ - - int single_value; /**< Mirror of the output value in single mode. */ - int single_value_in_fifo; /**< Mirror of the value written in single mode. */ - uint32_t ctrl_trg; /**< Mirror of the trigger settings. */ - - volatile int mode; /**< Flags used for storing SW wraparound setup*/ - int stop_mode; /**< The user defined stop condition flag. */ - unsigned int start_mode; - unsigned int stop_count; /**< The user defined dates presentation end count. */ - unsigned int stop_data_count; /**< The stop presentation count. */ - unsigned int data_count; /**< The real presentation count. */ - unsigned int preloaded_count; /**< The next data addres in buffer. <= for wraparound mode. */ - int hardware_stop_delay; /**< The time that stop can take. This is only to not show hardware bug to user. */ - - volatile enum ME4600_AO_STATUS status; /**< The current stream status flag. */ - me4600_ao_timeout_t timeout; /**< The timeout for start in blocking and non-blocking mode. */ - - /* Registers *//**< All registers are 32 bits long. */ - unsigned long ctrl_reg; - unsigned long status_reg; - unsigned long fifo_reg; - unsigned long single_reg; - unsigned long timer_reg; - unsigned long irq_status_reg; - unsigned long preload_reg; - unsigned long reg_base; - - /* Software buffer */ - me_circ_buf_t circ_buf; /**< Circular buffer holding measurment data. 32 bit long */ - wait_queue_head_t wait_queue; /**< Wait queue to put on tasks waiting for data to arrive. */ - - struct workqueue_struct *me4600_workqueue; - struct delayed_work ao_control_task; - - volatile int ao_control_task_flag; /**< Flag controling reexecuting of control task */ - -} me4600_ao_subdevice_t; - - /** - * @brief The constructor to generate a ME-4600 analog output subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. - * @param preload_flags Pointer to spin lock protecting the hold&trigger register from concurrent access. - * @param ao_idx Subdevice number. - * @param fifo Flag set if subdevice has hardware FIFO. - * @param irq IRQ number. - * @param me4600_wq Queue for asynchronous task (1 queue for all subdevice on 1 board). - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me4600_ao_subdevice_t *me4600_ao_constructor(uint32_t reg_base, - spinlock_t * preload_reg_lock, - uint32_t * preload_flags, - int ao_idx, - int fifo, - int irq, - struct workqueue_struct - *me4600_wq); - -# endif //BOSCH -# endif //__KERNEL__ -#endif // ~_ME4600_AO_H_ --- a/drivers/staging/meilhaus/me4600_ao_reg.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @file me4600_ao_reg.h - * - * @brief ME-4000 analog output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_AO_REG_H_ -#define _ME4600_AO_REG_H_ - -#ifdef __KERNEL__ - -#define ME4600_AO_00_CTRL_REG 0x00 // R/W -#define ME4600_AO_00_STATUS_REG 0x04 // R/_ -#define ME4600_AO_00_FIFO_REG 0x08 // _/W -#define ME4600_AO_00_SINGLE_REG 0x0C // R/W -#define ME4600_AO_00_TIMER_REG 0x10 // _/W - -#define ME4600_AO_01_CTRL_REG 0x18 // R/W -#define ME4600_AO_01_STATUS_REG 0x1C // R/_ -#define ME4600_AO_01_FIFO_REG 0x20 // _/W -#define ME4600_AO_01_SINGLE_REG 0x24 // R/W -#define ME4600_AO_01_TIMER_REG 0x28 // _/W - -#define ME4600_AO_02_CTRL_REG 0x30 // R/W -#define ME4600_AO_02_STATUS_REG 0x34 // R/_ -#define ME4600_AO_02_FIFO_REG 0x38 // _/W -#define ME4600_AO_02_SINGLE_REG 0x3C // R/W -#define ME4600_AO_02_TIMER_REG 0x40 // _/W - -#define ME4600_AO_03_CTRL_REG 0x48 // R/W -#define ME4600_AO_03_STATUS_REG 0x4C // R/_ -#define ME4600_AO_03_FIFO_REG 0x50 // _/W -#define ME4600_AO_03_SINGLE_REG 0x54 // R/W -#define ME4600_AO_03_TIMER_REG 0x58 // _/W - -#define ME4600_AO_DEMUX_ADJUST_REG 0xBC // -/W -#define ME4600_AO_DEMUX_ADJUST_VALUE 0x4C - -#ifdef BOSCH -# define ME4600_AO_BOSCH_REG 0xC4 - -# define ME4600_AO_LOADSETREG_XX 0xB4 // R/W - -# define ME4600_AO_CTRL_BIT_MODE_0 0x001 -# define ME4600_AO_CTRL_BIT_MODE_1 0x002 -# define ME4600_AO_CTRL_MASK_MODE 0x003 - -#else //~BOSCH - -#define ME4600_AO_SYNC_REG 0xB4 // R/W ///ME4600_AO_SYNC_REG <==> ME4600_AO_PRELOAD_REG <==> ME4600_AO_LOADSETREG_XX - -# define ME4600_AO_MODE_SINGLE 0x00000000 -# define ME4600_AO_MODE_WRAPAROUND 0x00000001 -# define ME4600_AO_MODE_CONTINUOUS 0x00000002 -# define ME4600_AO_CTRL_MODE_MASK (ME4600_AO_MODE_WRAPAROUND | ME4600_AO_MODE_CONTINUOUS) -#endif //BOSCH - -#define ME4600_AO_CTRL_BIT_MODE_WRAPAROUND ME4600_AO_MODE_WRAPAROUND -#define ME4600_AO_CTRL_BIT_MODE_CONTINOUS ME4600_AO_MODE_CONTINUOUS -#define ME4600_AO_CTRL_BIT_STOP 0x00000004 -#define ME4600_AO_CTRL_BIT_ENABLE_FIFO 0x00000008 -#define ME4600_AO_CTRL_BIT_ENABLE_EX_TRIG 0x00000010 -#define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE 0x00000020 -#define ME4600_AO_CTRL_BIT_IMMEDIATE_STOP 0x00000080 -#define ME4600_AO_CTRL_BIT_ENABLE_DO 0x00000100 -#define ME4600_AO_CTRL_BIT_ENABLE_IRQ 0x00000200 -#define ME4600_AO_CTRL_BIT_RESET_IRQ 0x00000400 -#define ME4600_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x00000800 -/* -#define ME4600_AO_SYNC_HOLD_0 0x00000001 -#define ME4600_AO_SYNC_HOLD_1 0x00000002 -#define ME4600_AO_SYNC_HOLD_2 0x00000004 -#define ME4600_AO_SYNC_HOLD_3 0x00000008 -*/ -#define ME4600_AO_SYNC_HOLD 0x00000001 - -/* -#define ME4600_AO_SYNC_EXT_TRIG_0 0x00010000 -#define ME4600_AO_SYNC_EXT_TRIG_1 0x00020000 -#define ME4600_AO_SYNC_EXT_TRIG_2 0x00040000 -#define ME4600_AO_SYNC_EXT_TRIG_3 0x00080000 -*/ -#define ME4600_AO_SYNC_EXT_TRIG 0x00010000 - -#define ME4600_AO_EXT_TRIG 0x80000000 - -#define ME4600_AO_STATUS_BIT_FSM 0x00000001 -#define ME4600_AO_STATUS_BIT_FF 0x00000002 -#define ME4600_AO_STATUS_BIT_HF 0x00000004 -#define ME4600_AO_STATUS_BIT_EF 0x00000008 - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_device.c +++ /dev/null @@ -1,371 +0,0 @@ -/** - * @file me4600_device.c - * - * @brief ME-4600 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "me4600_device.h" -#include "meplx_reg.h" - -#include "mefirmware.h" - -#include "mesubdevice.h" -#include "me4600_do.h" -#include "me4600_di.h" -#include "me4600_dio.h" -#include "me8254.h" -#include "me4600_ai.h" -#include "me4600_ao.h" -#include "me4600_ext_irq.h" - -/** - * @brief Global variable. - * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). - */ -static struct workqueue_struct *me4600_workqueue; - -#ifdef BOSCH -me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw) -#else //~BOSCH -me_device_t *me4600_pci_constructor(struct pci_dev *pci_device) -#endif //BOSCH -{ - me4600_device_t *me4600_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me4600_device = kmalloc(sizeof(me4600_device_t), GFP_KERNEL); - - if (!me4600_device) { - PERROR("Cannot get memory for ME-4600 device instance.\n"); - return NULL; - } - - memset(me4600_device, 0, sizeof(me4600_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me4600_device, pci_device); - - if (err) { - kfree(me4600_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - // Download the xilinx firmware. - if (me4600_device->base.info.pci.device_id == PCI_DEVICE_ID_MEILHAUS_ME4610) { //Jekyll <=> me4610 - err = - me_xilinx_download(me4600_device->base.info.pci. - reg_bases[1], - me4600_device->base.info.pci. - reg_bases[5], &pci_device->dev, - "me4610.bin"); - } else { // General me4600 firmware -#ifdef BOSCH - err = - me_xilinx_download(me4600_device->base.info.pci. - reg_bases[1], - me4600_device->base.info.pci. - reg_bases[5], &pci_device->dev, - (me_bosch_fw) ? "me4600_bosch.bin" : - "me4600.bin"); -#else //~BOSCH - err = - me_xilinx_download(me4600_device->base.info.pci. - reg_bases[1], - me4600_device->base.info.pci. - reg_bases[5], &pci_device->dev, - "me4600.bin"); -#endif - } - - if (err) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot download firmware.\n"); - return NULL; - } - // Get the index in the device version information table. - version_idx = - me4600_versions_get_device_index(me4600_device->base.info.pci. - device_id); - - // Initialize spin locks. - spin_lock_init(&me4600_device->preload_reg_lock); - - me4600_device->preload_flags = 0; - - spin_lock_init(&me4600_device->dio_lock); - spin_lock_init(&me4600_device->ai_ctrl_lock); - spin_lock_init(&me4600_device->ctr_ctrl_reg_lock); - spin_lock_init(&me4600_device->ctr_clk_src_reg_lock); - - // Create digital input instances. - for (i = 0; i < me4600_versions[version_idx].di_subdevices; i++) { - subdevice = - (me_subdevice_t *) me4600_di_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - &me4600_device-> - dio_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create digital output instances. - for (i = 0; i < me4600_versions[version_idx].do_subdevices; i++) { - subdevice = - (me_subdevice_t *) me4600_do_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - &me4600_device-> - dio_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create digital input/output instances. - for (i = 0; i < me4600_versions[version_idx].dio_subdevices; i++) { - subdevice = - (me_subdevice_t *) me4600_dio_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - me4600_versions - [version_idx]. - do_subdevices + - me4600_versions - [version_idx]. - di_subdevices + i, - &me4600_device-> - dio_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create analog input instances. - for (i = 0; i < me4600_versions[version_idx].ai_subdevices; i++) { - subdevice = - (me_subdevice_t *) me4600_ai_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - me4600_versions - [version_idx]. - ai_channels, - me4600_versions - [version_idx]. - ai_ranges, - me4600_versions - [version_idx]. - ai_isolated, - me4600_versions - [version_idx]. - ai_sh, - me4600_device-> - base.irq, - &me4600_device-> - ai_ctrl_lock, - me4600_workqueue); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create analog output instances. - for (i = 0; i < me4600_versions[version_idx].ao_subdevices; i++) { -#ifdef BOSCH - subdevice = - (me_subdevice_t *) me4600_ao_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - &me4600_device-> - preload_reg_lock, - &me4600_device-> - preload_flags, i, - me4600_versions - [version_idx]. - ao_fifo, - me4600_device-> - base.irq); -#else //~BOSCH - subdevice = - (me_subdevice_t *) me4600_ao_constructor(me4600_device-> - base.info.pci. - reg_bases[2], - &me4600_device-> - preload_reg_lock, - &me4600_device-> - preload_flags, i, - me4600_versions - [version_idx]. - ao_fifo, - me4600_device-> - base.irq, - me4600_workqueue); -#endif - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create counter instances. - for (i = 0; i < me4600_versions[version_idx].ctr_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8254_constructor(me4600_device->base. - info.pci.device_id, - me4600_device->base. - info.pci.reg_bases[3], - 0, i, - &me4600_device-> - ctr_ctrl_reg_lock, - &me4600_device-> - ctr_clk_src_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - // Create external interrupt instances. - for (i = 0; i < me4600_versions[version_idx].ext_irq_subdevices; i++) { - subdevice = - (me_subdevice_t *) - me4600_ext_irq_constructor(me4600_device->base.info.pci. - reg_bases[2], - me4600_device->base.irq, - &me4600_device->ai_ctrl_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me4600_device); - kfree(me4600_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me4600_device->base.slist, - subdevice); - } - - return (me_device_t *) me4600_device; -} -EXPORT_SYMBOL(me4600_pci_constructor); - -// Init and exit of module. - -static int __init me4600_init(void) -{ - PDEBUG("executed.\n"); - -#ifndef BOSCH - me4600_workqueue = create_singlethread_workqueue("me4600"); -#endif - return 0; -} - -static void __exit me4600_exit(void) -{ - PDEBUG("executed.\n"); - -#ifndef BOSCH - flush_workqueue(me4600_workqueue); - destroy_workqueue(me4600_workqueue); -#endif -} - -module_init(me4600_init); -module_exit(me4600_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for ME-46xx Devices"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-46xx Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me4600_device.h +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @file me4600_device.h - * - * @brief ME-4600 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_DEVICE_H -#define _ME4600_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-4600 device capabilities. - */ -typedef struct me4600_version { - uint16_t device_id; - unsigned int do_subdevices; - unsigned int di_subdevices; - unsigned int dio_subdevices; - unsigned int ctr_subdevices; - unsigned int ai_subdevices; - unsigned int ai_channels; - unsigned int ai_ranges; - unsigned int ai_isolated; - unsigned int ai_sh; - unsigned int ao_subdevices; - unsigned int ao_fifo; //How many devices have FIFO - unsigned int ext_irq_subdevices; -} me4600_version_t; - -/** - * @brief ME-4600 device capabilities. - */ -static me4600_version_t me4600_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME4610, 0, 0, 4, 3, 1, 16, 1, 0, 0, 0, 0, 1}, - - {PCI_DEVICE_ID_MEILHAUS_ME4650, 0, 0, 4, 0, 1, 16, 4, 0, 0, 0, 0, 1}, - - {PCI_DEVICE_ID_MEILHAUS_ME4660, 0, 0, 4, 3, 1, 16, 4, 0, 0, 2, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4660I, 1, 1, 2, 3, 1, 16, 4, 1, 0, 2, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4660S, 0, 0, 4, 3, 1, 16, 4, 0, 1, 2, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4660IS, 1, 1, 2, 3, 1, 16, 4, 1, 1, 2, 0, 1}, - - {PCI_DEVICE_ID_MEILHAUS_ME4670, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4670I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4670S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 0, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4670IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 0, 1}, - - {PCI_DEVICE_ID_MEILHAUS_ME4680, 0, 0, 4, 3, 1, 32, 4, 0, 0, 4, 4, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4680I, 1, 1, 2, 3, 1, 32, 4, 1, 0, 4, 4, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4680S, 0, 0, 4, 3, 1, 32, 4, 0, 1, 4, 4, 1}, - {PCI_DEVICE_ID_MEILHAUS_ME4680IS, 1, 1, 2, 3, 1, 32, 4, 1, 1, 4, 4, 1}, - - {0}, -}; - -#define ME4600_DEVICE_VERSIONS (ARRAY_SIZE(me4600_versions) - 1) /**< Returns the number of entries in #me4600_versions. */ - -/** - * @brief Returns the index of the device entry in #me4600_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me4600_versions. - */ -static inline unsigned int me4600_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME4600_DEVICE_VERSIONS; i++) - if (me4600_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-4600 device class structure. - */ -typedef struct me4600_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t preload_reg_lock; /**< Guards the preload register of the anaolog output devices. */ - unsigned int preload_flags; /**< Used in conjunction with #preload_reg_lock. */ - spinlock_t dio_lock; /**< Locks the control register of the digital input/output subdevices. */ - spinlock_t ai_ctrl_lock; /**< Locks the control register of the analog input subdevice. */ - spinlock_t ctr_ctrl_reg_lock; /**< Locks the counter control register. */ - spinlock_t ctr_clk_src_reg_lock; /**< Not used on this device but needed for the me8254 subdevice constructor call. */ -} me4600_device_t; - -/** - * @brief The ME-4600 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * @param me_bosch_fw If set the device shall use the bosch firmware. (Only for special BOSCH build) - * - * @return On succes a new ME-4600 device instance. \n - * NULL on error. - */ - -#ifdef BOSCH -/** - * @brief The ME-4600 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * @param me_bosch_fw If set the device shall use the bosch firmware. - * - * @return On succes a new ME-4600 device instance. \n - * NULL on error. - */ -me_device_t *me4600_pci_constructor(struct pci_dev *pci_device, int me_bosch_fw) - __attribute__ ((weak)); -#else //~BOSCH -/** - * @brief The ME-4600 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-4600 device instance. \n - * NULL on error. - */ -me_device_t *me4600_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); -#endif - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_di.c +++ /dev/null @@ -1,256 +0,0 @@ -/** - * @file me4600_di.c - * - * @brief ME-4000 digital input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me4600_dio_reg.h" -#include "me4600_di.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me4600_di_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me4600_di_subdevice_t *instance; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_di_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inl(instance->ctrl_reg); - mode &= ~(ME4600_DIO_CTRL_BIT_MODE_2 | ME4600_DIO_CTRL_BIT_MODE_3); //0xFFF3 - outl(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - - outl(0, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_di_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me4600_di_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me4600_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - } else { - PERROR("Invalid port direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_di_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me4600_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inl(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inl(instance->port_reg) & 0xFF; - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_di_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me4600_di_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me4600_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base, - spinlock_t *ctrl_reg_lock) -{ - me4600_di_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me4600_di_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_di_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the subdevice index */ - subdevice->port_reg = reg_base + ME4600_DIO_PORT_1_REG; - subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_di_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_di_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_di_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me4600_di_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_di_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_di_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me4600_di.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file me4600_di.h - * - * @brief ME-4000 digital input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_DI_H_ -#define _ME4600_DI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me4600_di_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me4600_di_subdevice_t; - -/** - * @brief The constructor to generate a ME-4000 digital input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me4600_di_subdevice_t *me4600_di_constructor(uint32_t reg_base, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_dio.c +++ /dev/null @@ -1,510 +0,0 @@ -/** - * @file me4600_dio.c - * - * @brief ME-4000 digital input/output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me4600_dio_reg.h" -#include "me4600_dio.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me4600_dio_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me4600_dio_subdevice_t *instance; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_dio_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - /* Set port to input mode */ - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inl(instance->ctrl_reg); - mode &= - ~((ME4600_DIO_CTRL_BIT_MODE_0 | ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - outl(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - - outl(0, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_dio_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - uint32_t size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - uint32_t mask; - - PDEBUG("executed.\n"); - - instance = (me4600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inl(instance->ctrl_reg); - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - mode &= - ~((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - mode &= - ~((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - mode |= - ME4600_DIO_CTRL_BIT_MODE_0 << (instance-> - dio_idx * 2); - } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) { - mask = - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> - dio_idx * - 2); - mask |= - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1; - mask |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - mode &= ~mask; - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1; - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - mode |= ME4600_DIO_CTRL_BIT_FUNCTION_1; - mode |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else if (single_config == - ME_SINGLE_CONFIG_DIO_DEMUX32) { - mask = - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> - dio_idx * - 2); - mask |= - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1; - mask |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - mode &= ~mask; - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0; - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - mode |= ME4600_DIO_CTRL_BIT_FUNCTION_0; - mode |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else if (single_config == - ME_SINGLE_CONFIG_DIO_BIT_PATTERN) { - mask = - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << (instance-> - dio_idx * - 2); - mask |= - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1; - mask |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - mode &= ~mask; - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= - (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2); - mode |= - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 << - instance->dio_idx; - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outl(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_dio_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inl(instance-> - ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - if ((mode == - (ME4600_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = - inl(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inl(instance-> - ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - if ((mode == - (ME4600_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = inl(instance->port_reg) & 0xFF; - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_dio_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me4600_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - uint32_t byte; - - PDEBUG("executed.\n"); - - instance = (me4600_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inl(instance-> - ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME4600_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - byte = inl(instance->port_reg) & 0xFF; - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outl(byte, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inl(instance-> - ctrl_reg) & ((ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME4600_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - outl(value, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_dio_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me4600_dio_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me4600_dio_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_DIR_BYTE; - return ME_ERRNO_SUCCESS; -} - -me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t *ctrl_reg_lock) -{ - me4600_dio_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me4600_dio_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_dio_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save digital i/o index */ - subdevice->dio_idx = dio_idx; - - /* Save the subdevice index */ - subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; - subdevice->port_reg = reg_base + ME4600_DIO_PORT_REG + (dio_idx * 4); -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_dio_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_dio_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_dio_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me4600_dio_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me4600_dio_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_dio_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_dio_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me4600_dio.h +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @file me4600_dio.h - * - * @brief ME-4000 digital input/output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_DIO_H_ -#define _ME4600_DIO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me4600_dio_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - unsigned int dio_idx; /**< The index of the digital i/o on the device. */ - - /* Registers */ - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me4600_dio_subdevice_t; - -/** - * @brief The constructor to generate a ME-4000 digital input/ouput subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param dio_idx The index of the digital i/o port on the device. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me4600_dio_subdevice_t *me4600_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_dio_reg.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file me4600_dio_reg.h - * - * @brief ME-4000 digital input/output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_DIO_REG_H_ -#define _ME4600_DIO_REG_H_ - -#ifdef __KERNEL__ - -#define ME4600_DIO_PORT_0_REG 0xA0 /**< Port 0 register. */ -#define ME4600_DIO_PORT_1_REG 0xA4 /**< Port 1 register. */ -#define ME4600_DIO_PORT_2_REG 0xA8 /**< Port 2 register. */ -#define ME4600_DIO_PORT_3_REG 0xAC /**< Port 3 register. */ - -#define ME4600_DIO_DIR_REG 0xB0 /**< Direction register. */ -#define ME4600_DIO_PORT_REG ME4600_DIO_PORT_0_REG /**< Base for port's register. */ - -#define ME4600_DIO_CTRL_REG 0xB8 /**< Control register. */ -/** Port A - DO */ -#define ME4600_DIO_CTRL_BIT_MODE_0 0x0001 -#define ME4600_DIO_CTRL_BIT_MODE_1 0x0002 -/** Port B - DI */ -#define ME4600_DIO_CTRL_BIT_MODE_2 0x0004 -#define ME4600_DIO_CTRL_BIT_MODE_3 0x0008 -/** Port C - DIO */ -#define ME4600_DIO_CTRL_BIT_MODE_4 0x0010 -#define ME4600_DIO_CTRL_BIT_MODE_5 0x0020 -/** Port D - DIO */ -#define ME4600_DIO_CTRL_BIT_MODE_6 0x0040 -#define ME4600_DIO_CTRL_BIT_MODE_7 0x0080 - -#define ME4600_DIO_CTRL_BIT_FUNCTION_0 0x0100 -#define ME4600_DIO_CTRL_BIT_FUNCTION_1 0x0200 - -#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_0 0x0400 -#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_1 0x0800 -#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_2 0x1000 -#define ME4600_DIO_CTRL_BIT_FIFO_HIGH_3 0x2000 - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_do.c +++ /dev/null @@ -1,433 +0,0 @@ -/** - * @file me4600_do.c - * - * @brief ME-4000 digital output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me4600_dio_reg.h" -#include "me4600_do.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me4600_do_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me4600_do_subdevice_t *instance; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - /* Set port to output mode */ - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inl(instance->ctrl_reg); - mode &= ~ME4600_DIO_CTRL_BIT_MODE_1; //0xFFFD - mode |= ME4600_DIO_CTRL_BIT_MODE_0; //0x1 - outl(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - - outl(0, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me4600_do_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me4600_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - int size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - - PDEBUG("executed.\n"); - - instance = (me4600_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inl(instance->ctrl_reg); - - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1); - mode |= (ME4600_DIO_CTRL_BIT_MODE_0); - } else if (single_config == ME_SINGLE_CONFIG_DIO_MUX32M) { - mode &= ~(ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1 | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_1); - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_1 - | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else if (single_config == - ME_SINGLE_CONFIG_DIO_DEMUX32) { - mode &= - ~(ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1 | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_0); - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_0 - | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else if (single_config == - ME_SINGLE_CONFIG_DIO_BIT_PATTERN) { - mode &= - ~(ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FUNCTION_0 | - ME4600_DIO_CTRL_BIT_FUNCTION_1 | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - - if (ref == ME_REF_DIO_FIFO_LOW) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1); - } else if (ref == ME_REF_DIO_FIFO_HIGH) { - mode |= (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1 | - ME4600_DIO_CTRL_BIT_FIFO_HIGH_0); - } else { - PERROR - ("Invalid port reference specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid port direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outl(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_do_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me4600_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = - inl(instance-> - ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1); - - if (mode == ME4600_DIO_CTRL_BIT_MODE_0) { - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = - inl(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inl(instance->port_reg) & 0xFF; - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - } else { - PERROR("Port not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_do_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me4600_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t byte; - uint32_t mode; - - PDEBUG("executed.\n"); - - instance = (me4600_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = - inl(instance-> - ctrl_reg) & (ME4600_DIO_CTRL_BIT_MODE_0 | - ME4600_DIO_CTRL_BIT_MODE_1); - - if (mode == ME4600_DIO_CTRL_BIT_MODE_0) { - switch (flags) { - - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - byte = inl(instance->port_reg) & 0xFF; - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outl(byte, instance->port_reg); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - outl(value, instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - } else { - PERROR("Port not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_do_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me4600_do_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me4600_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base, - spinlock_t *ctrl_reg_lock) -{ - me4600_do_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me4600_do_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_do_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the subdevice index */ - subdevice->ctrl_reg = reg_base + ME4600_DIO_CTRL_REG; - subdevice->port_reg = reg_base + ME4600_DIO_PORT_0_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_do_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me4600_do_io_single_config; - subdevice->base.me_subdevice_io_single_read = me4600_do_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me4600_do_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me4600_do_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_do_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_do_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me4600_do.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @file me4600_do.h - * - * @brief ME-4000 digital output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_DO_H_ -#define _ME4600_DO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me4600_do_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me4600_do_subdevice_t; - -/** - * @brief The constructor to generate a ME-4000 digital output subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me4600_do_subdevice_t *me4600_do_constructor(uint32_t reg_base, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_ext_irq.c +++ /dev/null @@ -1,457 +0,0 @@ -/** - * @file me4600_ext_irq.c - * - * @brief ME-4000 external interrupt subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "meids.h" -#include "me4600_reg.h" -#include "me4600_ai_reg.h" -#include "me4600_ext_irq_reg.h" -#include "me4600_ext_irq.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me4600_ext_irq_io_irq_start(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me4600_ext_irq_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - uint32_t tmp; - - PDEBUG("executed.\n"); - - instance = (me4600_ext_irq_subdevice_t *) subdevice; - - if (flags & ~ME_IO_IRQ_START_DIO_BIT) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((irq_edge != ME_IRQ_EDGE_RISING) - && (irq_edge != ME_IRQ_EDGE_FALLING) - && (irq_edge != ME_IRQ_EDGE_ANY) - ) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - - if (irq_source != ME_IRQ_SOURCE_DIO_LINE) { - PERROR("Invalid irq source specified.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - tmp = 0x0; //inl(instance->ext_irq_config_reg); - - if (irq_edge == ME_IRQ_EDGE_RISING) { - //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; - //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_RISING; - } else if (irq_edge == ME_IRQ_EDGE_FALLING) { - //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; - //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_FALLING; - tmp = ME4600_EXT_IRQ_CONFIG_MASK_FALLING; - } else if (irq_edge == ME_IRQ_EDGE_ANY) { - //tmp &= ~ME4600_EXT_IRQ_CONFIG_MASK; - //tmp |= ME4600_EXT_IRQ_CONFIG_MASK_ANY; - tmp = ME4600_EXT_IRQ_CONFIG_MASK_ANY; - } - - outl(tmp, instance->ext_irq_config_reg); - PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ext_irq_config_reg - instance->reg_base, tmp); - - spin_lock_irqsave(instance->ctrl_reg_lock, cpu_flags); - tmp = inl(instance->ctrl_reg); - tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - tmp |= ME4600_AI_CTRL_BIT_EX_IRQ; - outl(tmp, instance->ctrl_reg); - spin_unlock_irqrestore(instance->ctrl_reg_lock, cpu_flags); - instance->rised = 0; - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ext_irq_io_irq_wait(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me4600_ext_irq_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me4600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - (instance->rised != - 0), t); - - if (t == 0) { - PERROR - ("Wait on external interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on external interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - instance->rised = 0; - *irq_count = instance->count; - *value = instance->value; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ext_irq_io_irq_stop(me_subdevice_t *subdevice, - struct file *filep, - int channel, int flags) -{ - me4600_ext_irq_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - uint32_t tmp; - - PDEBUG("executed.\n"); - - instance = (me4600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); - instance->rised = -1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me4600_ext_irq_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me4600_ext_irq_subdevice_t *instance; - unsigned long cpu_flags; - uint32_t tmp; - - PDEBUG("executed.\n"); - - instance = (me4600_ext_irq_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->ctrl_reg_lock); - tmp = inl(instance->ctrl_reg); - tmp &= ~(ME4600_AI_CTRL_BIT_EX_IRQ | ME4600_AI_CTRL_BIT_EX_IRQ_RESET); - outl(tmp, instance->ctrl_reg); - PDEBUG_REG("ctrl_regv outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->ctrl_reg_lock); - instance->rised = -1; - instance->count = 0; - outl(ME4600_EXT_IRQ_CONFIG_MASK_ANY, instance->ext_irq_config_reg); - PDEBUG_REG("ext_irq_config_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ext_irq_config_reg - instance->reg_base, - ME4600_EXT_IRQ_CONFIG_MASK_ANY); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static void me4600_ext_irq_destructor(struct me_subdevice *subdevice) -{ - me4600_ext_irq_subdevice_t *instance; - - PDEBUG("executed.\n"); - instance = (me4600_ext_irq_subdevice_t *) subdevice; - me_subdevice_deinit(&instance->base); - free_irq(instance->irq, instance); - kfree(instance); -} - -static int me4600_ext_irq_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 1; - return ME_ERRNO_SUCCESS; -} - -static int me4600_ext_irq_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_EXT_IRQ; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me4600_ext_irq_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = - ME_CAPS_EXT_IRQ_EDGE_RISING | ME_CAPS_EXT_IRQ_EDGE_FALLING | - ME_CAPS_EXT_IRQ_EDGE_ANY; - return ME_ERRNO_SUCCESS; -} - -static irqreturn_t me4600_ext_irq_isr(int irq, void *dev_id) -{ - me4600_ext_irq_subdevice_t *instance; - uint32_t ctrl; - uint32_t irq_status; - - instance = (me4600_ext_irq_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inl(instance->irq_status_reg); - if (!(irq_status & ME4600_IRQ_STATUS_BIT_EX)) { - PINFO("%ld Shared interrupt. %s(): irq_status_reg=0x%04X\n", - jiffies, __func__, irq_status); - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - spin_lock(&instance->subdevice_lock); - instance->rised = 1; - instance->value = inl(instance->ext_irq_value_reg); - instance->count++; - - spin_lock(instance->ctrl_reg_lock); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME4600_AI_CTRL_BIT_EX_IRQ_RESET; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - ctrl &= ~ME4600_AI_CTRL_BIT_EX_IRQ_RESET; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->ctrl_reg_lock); - - spin_unlock(&instance->subdevice_lock); - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base, - int irq, - spinlock_t * - ctrl_reg_lock) -{ - me4600_ext_irq_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me4600_ext_irq_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me4600_ext_irq_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Register interrupt */ - subdevice->irq = irq; - - if (request_irq(subdevice->irq, me4600_ext_irq_isr, - IRQF_DISABLED | IRQF_SHARED, - ME4600_NAME, subdevice)) { - PERROR("Cannot register interrupt.\n"); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - /* Initialize registers */ - subdevice->irq_status_reg = reg_base + ME4600_IRQ_STATUS_REG; - subdevice->ctrl_reg = reg_base + ME4600_AI_CTRL_REG; - subdevice->ext_irq_config_reg = reg_base + ME4600_EXT_IRQ_CONFIG_REG; - subdevice->ext_irq_value_reg = reg_base + ME4600_EXT_IRQ_VALUE_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Override base class methods. */ - subdevice->base.me_subdevice_destructor = me4600_ext_irq_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me4600_ext_irq_io_reset_subdevice; - subdevice->base.me_subdevice_io_irq_start = me4600_ext_irq_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me4600_ext_irq_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me4600_ext_irq_io_irq_stop; - subdevice->base.me_subdevice_query_number_channels = - me4600_ext_irq_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me4600_ext_irq_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me4600_ext_irq_query_subdevice_caps; - - subdevice->rised = 0; - subdevice->count = 0; - - return subdevice; -} --- a/drivers/staging/meilhaus/me4600_ext_irq.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file me4600_ext_irq.h - * - * @brief Meilhaus ME-4000 external interrupt subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_EXT_IRQ_H_ -#define _ME4600_EXT_IRQ_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The subdevice class. - */ -typedef struct me4600_ext_irq_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - - wait_queue_head_t wait_queue; - - int irq; - - int rised; - int value; - int count; - - unsigned long ctrl_reg; - unsigned long irq_status_reg; - unsigned long ext_irq_config_reg; - unsigned long ext_irq_value_reg; -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me4600_ext_irq_subdevice_t; - -/** - * @brief The constructor to generate a external interrupt subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param irq The interrupt number assigned by the PCI BIOS. - * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me4600_ext_irq_subdevice_t *me4600_ext_irq_constructor(uint32_t reg_base, - int irq, - spinlock_t * - ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_ext_irq_reg.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file me4600_ext_irq_reg.h - * - * @brief ME-4000 external interrupt subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_EXT_IRQ_REG_H_ -#define _ME4600_EXT_IRQ_REG_H_ - -#ifdef __KERNEL__ - -#define ME4600_EXT_IRQ_CONFIG_REG 0xCC // R/_ -#define ME4600_EXT_IRQ_VALUE_REG 0xD0 // R/_ - -#define ME4600_EXT_IRQ_CONFIG_MASK_RISING 0x0 -#define ME4600_EXT_IRQ_CONFIG_MASK_FALLING 0x1 -#define ME4600_EXT_IRQ_CONFIG_MASK_ANY 0x3 -#define ME4600_EXT_IRQ_CONFIG_MASK 0x3 - -#endif -#endif --- a/drivers/staging/meilhaus/me4600_reg.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file me4600_reg.h - * - * @brief ME-4000 register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME4600_REG_H_ -#define _ME4600_REG_H_ - -#ifdef __KERNEL__ - -#define ME4600_IRQ_STATUS_REG 0x9C // R/_ - -#define ME4600_IRQ_STATUS_BIT_EX 0x01 -#define ME4600_IRQ_STATUS_BIT_LE 0x02 -#define ME4600_IRQ_STATUS_BIT_AI_HF 0x04 -#define ME4600_IRQ_STATUS_BIT_AO_0_HF 0x08 -#define ME4600_IRQ_STATUS_BIT_AO_1_HF 0x10 -#define ME4600_IRQ_STATUS_BIT_AO_2_HF 0x20 -#define ME4600_IRQ_STATUS_BIT_AO_3_HF 0x40 -#define ME4600_IRQ_STATUS_BIT_SC 0x80 - -#define ME4600_IRQ_STATUS_BIT_AO_HF ME4600_IRQ_STATUS_BIT_AO_0_HF - -#endif -#endif --- a/drivers/staging/meilhaus/me6000_ao.c +++ /dev/null @@ -1,3709 +0,0 @@ -/** - * @file me6000_ao.c - * - * @brief ME-6000 analog output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* Includes - */ -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "meids.h" -#include "me6000_reg.h" -#include "me6000_ao_reg.h" -#include "me6000_ao.h" - -/* Defines - */ - -static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range); - -static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count); - -static int me6000_ao_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); - -static int me6000_ao_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks); - -static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, - int *number); - -static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype); - -static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); - -static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count); - -/** Remove subdevice. */ -static void me6000_ao_destructor(struct me_subdevice *subdevice); - -/** Reset subdevice. Stop all actions. Reset registry. Disable FIFO. Set output to 0V and status to 'none'. */ -static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags); - -/** Set output as single */ -static int me6000_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags); - -/** Pass to user actual value of output. */ -static int me6000_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags); - -/** Write to output requed value. */ -static int me6000_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags); - -/** Set output as streamed device. */ -static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags); - -/** Wait for / Check empty space in buffer. */ -static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags); - -/** Start streaming. */ -static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags); - -/** Check actual state. / Wait for end. */ -static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags); - -/** Stop streaming. */ -static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags); - -/** Write datas to buffor. */ -static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags); - -/** Interrupt handler. Copy from buffer to FIFO. */ -static irqreturn_t me6000_ao_isr(int irq, void *dev_id); - -/** Copy data from circular buffer to fifo (fast) in wraparound mode. */ -inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from circular buffer to fifo (fast).*/ -inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from circular buffer to fifo (slow).*/ -inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, - int start_pos); - -/** Copy data from user space to circular buffer. */ -inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, - int *user_values); - -/** Stop presentation. Preserve FIFOs. */ -inline int ao_stop_immediately(me6000_ao_subdevice_t *instance); - -/** Function for checking timeout in non-blocking mode. */ -static void me6000_ao_work_control_task(struct work_struct *work); - -/* Functions - */ - -static int me6000_ao_io_reset_subdevice(me_subdevice_t *subdevice, - struct file *filep, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t tmp; - uint32_t ctrl; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - instance->status = ao_status_none; - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->timeout.delay = 0; - instance->timeout.start_time = jiffies; - - //Stop state machine. - err = ao_stop_immediately(instance); - - //Remove from synchronous start. - spin_lock(instance->preload_reg_lock); - tmp = inl(instance->preload_reg); - tmp &= - ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - outl(tmp, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, tmp); - *instance->preload_flags &= - ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - - //Reset triggering flag - *instance->triggering_flags &= ~(0x1 << instance->ao_idx); - spin_unlock(instance->preload_reg_lock); - - if (instance->fifo) { - //Set single mode, dissable FIFO, dissable external trigger, block interrupt. - ctrl = ME6000_AO_MODE_SINGLE; - - //Block ISM. - ctrl |= - (ME6000_AO_CTRL_BIT_STOP | - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - //Set speed - outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); - //Reset interrupt latch - inl(instance->irq_reset_reg); - } - - instance->hardware_stop_delay = HZ / 10; //100ms - - //Set output to 0V - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - instance->preloaded_count = 0; - instance->data_count = 0; - instance->single_value = 0x8000; - instance->single_value_in_fifo = 0x8000; - - //Set status to signal that device is unconfigured. - instance->status = ao_status_none; - //Signal reset if user is on wait. - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t ctrl; - uint32_t sync; - unsigned long cpu_flags; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. ID=%d\n", instance->ao_idx); - - // Checking parameters - if (flags) { - PERROR - ("Invalid flag specified. Must be ME_IO_SINGLE_CONFIG_NO_FLAGS.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (instance->fifo) { //Stream hardware (with or without fifo) - if ((trig_edge == ME_TRIG_TYPE_SW) - && (trig_edge != ME_TRIG_EDGE_NONE)) { - PERROR - ("Invalid trigger edge. Software trigger has not edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - - if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { - switch (trig_edge) { - case ME_TRIG_EDGE_ANY: - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - break; - - default: - PERROR("Invalid trigger edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - } - - if ((trig_type != ME_TRIG_TYPE_SW) - && (trig_type != ME_TRIG_TYPE_EXT_DIGITAL)) { - PERROR - ("Invalid trigger type. Trigger must be software or digital.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - } else { //Single - if (trig_edge != ME_TRIG_EDGE_NONE) { - PERROR - ("Invalid trigger edge. Single output trigger hasn't own edge.\n"); - return ME_ERRNO_INVALID_TRIG_EDGE; - } - - if (trig_type != ME_TRIG_TYPE_SW) { - PERROR - ("Invalid trigger type. Trigger must be software.\n"); - return ME_ERRNO_INVALID_TRIG_TYPE; - } - - } - - if ((trig_chan != ME_TRIG_CHAN_DEFAULT) - && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) { - PERROR("Invalid trigger channel specified.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } -/* - if ((trig_type == ME_TRIG_TYPE_EXT_DIGITAL) && (trig_chan != ME_TRIG_CHAN_SYNCHRONOUS)) - { - PERROR("Invalid trigger channel specified. Must be synchronous when digital is choose.\n"); - return ME_ERRNO_INVALID_TRIG_CHAN; - } -*/ - if (ref != ME_REF_AO_GROUND) { - PERROR - ("Invalid reference. Analog outputs have to have got REF_AO_GROUND.\n"); - return ME_ERRNO_INVALID_REF; - } - - if (single_config != 0) { - PERROR - ("Invalid single config specified. Only one range for anlog outputs is available.\n"); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - - if (channel != 0) { - PERROR - ("Invalid channel number specified. Analog output have only one channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - //Subdevice running in stream mode! - if ((instance->status >= ao_status_stream_run_wait) - && (instance->status < ao_status_stream_end)) { - PERROR("Subdevice is busy.\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } -/// @note For single all calls (config and write) are erasing previous state! - - instance->status = ao_status_none; - - // Correct single mirrors - instance->single_value_in_fifo = instance->single_value; - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - - if (instance->fifo) { // Set control register. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Set stop bit. Stop streaming mode (If running.). - ctrl = inl(instance->ctrl_reg); - //Reset all bits. - ctrl = - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; - if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) { - PINFO("External digital trigger.\n"); - - if (trig_edge == ME_TRIG_EDGE_ANY) { -// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - instance->ctrl_trg = - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - } else if (trig_edge == ME_TRIG_EDGE_FALLING) { -// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; - instance->ctrl_trg = - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; - } else if (trig_edge == ME_TRIG_EDGE_RISING) { - instance->ctrl_trg = 0x0; - } - } else if (trig_type == ME_TRIG_TYPE_SW) { - PDEBUG("SOFTWARE TRIGGER\n"); - instance->ctrl_trg = 0x0; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } else { - PDEBUG("SOFTWARE TRIGGER\n"); - } - - // Set preload/synchronization register. - spin_lock(instance->preload_reg_lock); - - if (trig_type == ME_TRIG_TYPE_SW) { - *instance->preload_flags &= - ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx); - } else //if (trig_type == ME_TRIG_TYPE_EXT_DIGITAL) - { - *instance->preload_flags |= - ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx; - } - - if (trig_chan == ME_TRIG_CHAN_DEFAULT) { - *instance->preload_flags &= - ~(ME6000_AO_SYNC_HOLD << instance->ao_idx); - } else //if (trig_chan == ME_TRIG_CHAN_SYNCHRONOUS) - { - *instance->preload_flags |= - ME6000_AO_SYNC_HOLD << instance->ao_idx; - } - - //Reset hardware register - sync = inl(instance->preload_reg); - PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync); - sync &= ~(ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx); - sync |= ME6000_AO_SYNC_HOLD << instance->ao_idx; - - //Output configured in default mode (safe one) - outl(sync, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync); - spin_unlock(instance->preload_reg_lock); - - instance->status = ao_status_single_configured; - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - unsigned long j; - unsigned long delay = 0; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & ~ME_IO_SINGLE_NONBLOCKING) { - PERROR("Invalid flag specified. %d\n", flags); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((instance->status >= ao_status_stream_configured) - && (instance->status <= ao_status_stream_end)) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - ME_SUBDEVICE_ENTER; - if ((!flags) && (instance->status == ao_status_single_run_wait)) { //Blocking mode. Wait for trigger. - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - j = jiffies; - - //Only runing process will interrupt this call. Events are signaled when status change. This procedure has own timeout. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_single_run_wait), - (delay) ? delay : LONG_MAX); - - if (instance->status == ao_status_none) { - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - PDEBUG("Timeout reached.\n"); - err = ME_ERRNO_TIMEOUT; - } - - *value = - (!err) ? instance->single_value_in_fifo : instance-> - single_value; - } else { //Non-blocking mode - //Read value - *value = instance->single_value; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags; - unsigned long j; - unsigned long delay = 0; - - uint32_t sync_mask; - uint32_t mode; - - uint32_t tmp; - -/// Workaround for mix-mode - begin - uint32_t ctrl = 0x0; - uint32_t status; -/// Workaround for mix-mode - end - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & - ~(ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS | - ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((instance->status == ao_status_none) - || (instance->status > ao_status_single_end)) { - PERROR("Subdevice not configured to work in single mode!\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - if (channel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (value & ~ME6000_AO_MAX_DATA) { - PERROR("Invalid value provided.\n"); - return ME_ERRNO_VALUE_OUT_OF_RANGE; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - ME_SUBDEVICE_ENTER; - -/// @note For single all calls (config and write) are erasing previous state! - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - // Correct single mirrors - instance->single_value_in_fifo = instance->single_value; - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - - if (delay == 0) - delay = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - - instance->single_value_in_fifo = value; - - if (instance->fifo) { - ctrl = inl(instance->ctrl_reg); - } - - if (instance->fifo & ME6000_AO_HAS_FIFO) { /// Workaround for mix-mode - begin - //Set speed - outl(ME6000_AO_MIN_CHAN_TICKS - 1, instance->timer_reg); - PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->timer_reg - instance->reg_base, - (int)ME6000_AO_MIN_CHAN_TICKS); - instance->hardware_stop_delay = HZ / 10; //100ms - - status = inl(instance->status_reg); - - //Set the continous mode. - ctrl &= ~ME6000_AO_CTRL_MODE_MASK; - ctrl |= ME6000_AO_MODE_CONTINUOUS; - - //Prepare FIFO - if (!(ctrl & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. - PINFO("Enableing FIFO.\n"); - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; - } else { //Check if FIFO is empty - if (status & ME6000_AO_STATUS_BIT_EF) { //FIFO not empty - PINFO("Reseting FIFO.\n"); - ctrl &= - ~(ME6000_AO_CTRL_BIT_ENABLE_FIFO | - ME6000_AO_CTRL_BIT_ENABLE_IRQ); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - - instance->reg_base, ctrl); - - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; - } else { //FIFO empty, only interrupt needs to be disabled! - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - } - } - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - //Write output - 1 value to FIFO - if (instance->ao_idx & 0x1) { - outl(value <<= 16, instance->fifo_reg); - PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->fifo_reg - instance->reg_base, - value <<= 16); - } else { - outl(value, instance->fifo_reg); - PDEBUG_REG("fifo_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->fifo_reg - instance->reg_base, - value); - } - /// Workaround for mix-mode - end - } else { //No FIFO - always in single mode - //Write value - PDEBUG("Write value\n"); - outl(value, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, value); - } - - mode = *instance->preload_flags >> instance->ao_idx; - mode &= (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG); - - PINFO("Triggering mode: 0x%08x\n", mode); - - spin_lock(instance->preload_reg_lock); - sync_mask = inl(instance->preload_reg); - PDEBUG_REG("preload_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, sync_mask); - switch (mode) { - case 0: //0x00000000: Individual software - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. - sync_mask &= - ~((ME6000_AO_SYNC_EXT_TRIG | - ME6000_AO_SYNC_HOLD) << instance-> - ao_idx); - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } else { // No FIFO - Single mode: In this case resetting 'ME6000_AO_SYNC_HOLD' will trigger output. - if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != ME6000_AO_SYNC_HOLD) { //Now we can set correct mode. This is exception. It is set to synchronous and triggered later. - sync_mask &= - ~(ME6000_AO_SYNC_EXT_TRIG << instance-> - ao_idx); - sync_mask |= - ME6000_AO_SYNC_HOLD << instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } - instance->single_value = value; - break; - - case ME6000_AO_SYNC_EXT_TRIG: //0x00010000: Individual hardware - PDEBUG("DIGITAL TRIGGER\n"); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode - if ((sync_mask & ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance->ao_idx)) != 0x0) { //Now we can set correct mode. - sync_mask &= - ~((ME6000_AO_SYNC_EXT_TRIG | - ME6000_AO_SYNC_HOLD) << instance-> - ao_idx); - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } else { // No FIFO - Single mode - if ((sync_mask & - ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << - instance->ao_idx)) != ME6000_AO_SYNC_HOLD) { - //Now we can set correct mode - sync_mask &= - ~(ME6000_AO_SYNC_EXT_TRIG << instance-> - ao_idx); - sync_mask |= - ME6000_AO_SYNC_HOLD << instance->ao_idx; - - outl(sync_mask, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - } - break; - - case ME6000_AO_SYNC_HOLD: //0x00000001: Synchronous software - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if ((sync_mask & - ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << - instance->ao_idx)) != - (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) { - //Now we can set correct mode - sync_mask |= - ME6000_AO_SYNC_EXT_TRIG << instance->ao_idx; - sync_mask |= ME6000_AO_SYNC_HOLD << instance->ao_idx; - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - //Set triggering flag - *instance->triggering_flags |= 0x1 << instance->ao_idx; - break; - - case (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG): //0x00010001: Synchronous hardware - PDEBUG("DIGITAL TRIGGER\n"); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - - if ((sync_mask & - ((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << - instance->ao_idx)) != - (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG)) { - //Now we can set correct mode - sync_mask |= - (ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << - instance->ao_idx; - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - } - //Set triggering flag - *instance->triggering_flags |= 0x1 << instance->ao_idx; - break; - } -// spin_unlock(instance->preload_reg_lock); // Moved down. - - if (instance->fifo) { //Activate ISM (remove 'stop' bits) - ctrl &= - ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); - ctrl |= instance->ctrl_trg; - ctrl &= - ~(ME6000_AO_CTRL_BIT_STOP | - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - } - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - -/// @note When flag 'ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS' is set than output is triggered. ALWAYS! - - PINFO("<%s> start mode= 0x%08x %s\n", __func__, mode, - (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" : - ""); - if (instance->fifo & ME6000_AO_HAS_FIFO) { // FIFO - Continous mode - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs - //Add channel to start list - outl(sync_mask | - (ME6000_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask | (ME6000_AO_SYNC_HOLD << - instance->ao_idx)); - - //Fire - PINFO - ("Fired all software synchronous outputs by software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - 0x8000); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - - } else if (!mode) { //Trigger outputs -/* //Remove channel from start list - outl(sync_mask & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx)); -*/ - //Fire - PINFO("Software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - 0x8000); - -/* //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, sync_mask); -*/ - } -/// @note This is mix-mode case. For now I do not have possibility to trigger first 4 channels (continous mode) and other (single) ones at once. -/// @note Because triggering is not working it can not be add to synchronous list. First 4 channels don't need this information, anyway. - *instance->triggering_flags &= 0xFFFFFFF0; - } else { // No FIFO - Single mode - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Fired all software synchronous outputs. - tmp = ~(*instance->preload_flags | 0xFFFF0000); - PINFO - ("Fired all software synchronous outputs. mask:0x%08x\n", - tmp); - tmp |= sync_mask & 0xFFFF0000; - // Add this channel to list - tmp &= ~(ME6000_AO_SYNC_HOLD << instance->ao_idx); - - //Fire - PINFO("Software trigger.\n"); - outl(tmp, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - tmp); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - - //Set all as triggered. - *instance->triggering_flags = 0x0; - } else if (!mode) { // Add this channel to list - outl(sync_mask & - ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask & ~(ME6000_AO_SYNC_HOLD << - instance->ao_idx)); - - //Fire - PINFO("Software trigger.\n"); - - //Restore save settings - outl(sync_mask, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - sync_mask); - - //Set all as triggered. - *instance->triggering_flags = 0x0; - } - - } - spin_unlock(instance->preload_reg_lock); - - instance->status = ao_status_single_run_wait; - - instance->timeout.delay = delay; - instance->timeout.start_time = jiffies; - instance->ao_control_task_flag = 1; - queue_delayed_work(instance->me6000_workqueue, - &instance->ao_control_task, 1); - - if (!(flags & ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING)) { - j = jiffies; - - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_single_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if (instance->status != ao_status_single_end) { - PDEBUG("Single canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - ao_stop_immediately(instance); - instance->status = ao_status_none; - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - j) >= delay)) { - if (instance->status == ao_status_single_end) { - PDEBUG("Timeout reached.\n"); - } else if ((jiffies - j) > delay) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - ao_stop_immediately(instance); - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - ao_stop_immediately(instance); - } - - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->status = ao_status_single_end; - err = ME_ERRNO_TIMEOUT; - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_stream_config(me_subdevice_t *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t ctrl; - unsigned long cpu_flags; - uint64_t conv_ticks; - unsigned int conv_start_ticks_low = trigger->iConvStartTicksLow; - unsigned int conv_start_ticks_high = trigger->iConvStartTicksHigh; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - conv_ticks = - (uint64_t) conv_start_ticks_low + - ((uint64_t) conv_start_ticks_high << 32); - - if (flags & - ~(ME_IO_STREAM_CONFIG_HARDWARE_ONLY | - ME_IO_STREAM_CONFIG_WRAPAROUND)) { - PERROR("Invalid flags.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { - if (!(flags & ME_IO_STREAM_CONFIG_WRAPAROUND)) { - PERROR - ("Hardware ME_IO_STREAM_CONFIG_HARDWARE_ONLY has to be with ME_IO_STREAM_CONFIG_WRAPAROUND.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((trigger->iAcqStopTrigType != ME_TRIG_TYPE_NONE) - || (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE)) { - PERROR - ("Hardware wraparound mode must be in infinite mode.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - } - - if (count != 1) { - PERROR("Only 1 entry in config list acceptable.\n"); - return ME_ERRNO_INVALID_CONFIG_LIST_COUNT; - } - - if (config_list[0].iChannel != 0) { - PERROR("Invalid channel number specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (config_list[0].iStreamConfig != 0) { - PERROR("Only one range available.\n"); - return ME_ERRNO_INVALID_STREAM_CONFIG; - } - - if (config_list[0].iRef != ME_REF_AO_GROUND) { - PERROR("Output is referenced to ground.\n"); - return ME_ERRNO_INVALID_REF; - } - - if ((trigger->iAcqStartTicksLow != 0) - || (trigger->iAcqStartTicksHigh != 0)) { - PERROR - ("Invalid acquisition start trigger argument specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_ARG; - } - - if (config_list[0].iFlags) { - PERROR("Invalid config list flag.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((trigger->iAcqStartTrigType != ME_TRIG_TYPE_SW) - && (trigger->iAcqStartTrigType != ME_TRIG_TYPE_EXT_DIGITAL)) { - PERROR("Invalid acquisition start trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE; - } - - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - case ME_TRIG_EDGE_FALLING: - case ME_TRIG_EDGE_ANY: - break; - - default: - PERROR - ("Invalid acquisition start trigger edge specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - } - } - - if ((trigger->iAcqStartTrigType == ME_TRIG_TYPE_SW) - && (trigger->iAcqStartTrigEdge != ME_TRIG_TYPE_NONE)) { - PERROR("Invalid acquisition start trigger edge specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE; - } - - if (trigger->iScanStartTrigType != ME_TRIG_TYPE_FOLLOW) { - PERROR("Invalid scan start trigger type specified.\n"); - return ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE; - } - - if (trigger->iConvStartTrigType != ME_TRIG_TYPE_TIMER) { - PERROR("Invalid conv start trigger type specified.\n"); - return ME_ERRNO_INVALID_CONV_START_TRIG_TYPE; - } - - if ((conv_ticks < ME6000_AO_MIN_CHAN_TICKS) - || (conv_ticks > ME6000_AO_MAX_CHAN_TICKS)) { - PERROR("Invalid conv start trigger argument specified.\n"); - return ME_ERRNO_INVALID_CONV_START_ARG; - } - - if (trigger->iAcqStartTicksLow || trigger->iAcqStartTicksHigh) { - PERROR("Invalid acq start trigger argument specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_ARG; - } - - if (trigger->iScanStartTicksLow || trigger->iScanStartTicksHigh) { - PERROR("Invalid scan start trigger argument specified.\n"); - return ME_ERRNO_INVALID_SCAN_START_ARG; - } - - switch (trigger->iScanStopTrigType) { - case ME_TRIG_TYPE_NONE: - if (trigger->iScanStopCount != 0) { - PERROR("Invalid scan stop count specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_ARG; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iScanStopCount <= 0) { - PERROR("Invalid scan stop count specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_ARG; - } - } else { - PERROR("The continous mode has not 'scan' contects.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - break; - - default: - PERROR("Invalid scan stop trigger type specified.\n"); - return ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE; - } - - switch (trigger->iAcqStopTrigType) { - case ME_TRIG_TYPE_NONE: - if (trigger->iAcqStopCount != 0) { - PERROR("Invalid acq stop count specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_ARG; - } - break; - - case ME_TRIG_TYPE_COUNT: - if (trigger->iScanStopTrigType != ME_TRIG_TYPE_NONE) { - PERROR("Invalid acq stop trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { - if (trigger->iAcqStopCount <= 0) { - PERROR - ("The continous mode has not 'scan' contects.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_ARG; - } - } -// else -// { -// PERROR("Invalid acq stop trigger type specified.\n"); -// return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; -// } - - break; - - default: - PERROR("Invalid acq stop trigger type specified.\n"); - return ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE; - } - - switch (trigger->iAcqStartTrigChan) { - case ME_TRIG_CHAN_DEFAULT: - case ME_TRIG_CHAN_SYNCHRONOUS: - break; - - default: - PERROR("Invalid acq start trigger channel specified.\n"); - return ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN; - } - - ME_SUBDEVICE_ENTER; - - //Stop device - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - //Check if state machine is stopped. - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - //Reset control register. Block all actions. Disable IRQ. Disable FIFO. - ctrl = ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - //This is paranoic, but to be sure. - instance->preloaded_count = 0; - instance->data_count = 0; - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - - /* Set mode. */ - if (flags & ME_IO_STREAM_CONFIG_WRAPAROUND) { //Wraparound - if (flags & ME_IO_STREAM_CONFIG_HARDWARE_ONLY) { //Hardware wraparound - PINFO("Hardware wraparound.\n"); - ctrl |= ME6000_AO_MODE_WRAPAROUND; - instance->mode = ME6000_AO_HW_WRAP_MODE; - } else { //Software wraparound - PINFO("Software wraparound.\n"); - ctrl |= ME6000_AO_MODE_CONTINUOUS; - instance->mode = ME6000_AO_SW_WRAP_MODE; - } - } else { //Continous - PINFO("Continous.\n"); - ctrl |= ME6000_AO_MODE_CONTINUOUS; - instance->mode = ME6000_AO_CONTINOUS; - } - - //Set the trigger edge. - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Set the trigger type and edge for external trigger. - PINFO("External digital trigger.\n"); - instance->start_mode = ME6000_AO_EXT_TRIG; - - switch (trigger->iAcqStartTrigEdge) { - case ME_TRIG_EDGE_RISING: - PINFO("Set the trigger edge: rising.\n"); - instance->ctrl_trg = 0x0; - break; - - case ME_TRIG_EDGE_FALLING: - PINFO("Set the trigger edge: falling.\n"); -// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; - instance->ctrl_trg = ME6000_AO_CTRL_BIT_EX_TRIG_EDGE; - break; - - case ME_TRIG_EDGE_ANY: - PINFO("Set the trigger edge: both edges.\n"); -// ctrl |= ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - instance->ctrl_trg = - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH; - break; - } - } else { - PINFO("Internal software trigger.\n"); - instance->start_mode = 0; - } - - //Set the stop mode and value. - if (trigger->iAcqStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of data - instance->stop_mode = ME6000_AO_ACQ_STOP_MODE; - instance->stop_count = trigger->iAcqStopCount; - } else if (trigger->iScanStopTrigType == ME_TRIG_TYPE_COUNT) { //Amount of 'scans' - instance->stop_mode = ME6000_AO_SCAN_STOP_MODE; - instance->stop_count = trigger->iScanStopCount; - } else { //Infinite - instance->stop_mode = ME6000_AO_INF_STOP_MODE; - instance->stop_count = 0; - } - - PINFO("Stop count: %d.\n", instance->stop_count); - - if (trigger->iAcqStartTrigChan == ME_TRIG_CHAN_SYNCHRONOUS) { //Synchronous start - instance->start_mode |= ME6000_AO_SYNC_HOLD; - if (trigger->iAcqStartTrigType == ME_TRIG_TYPE_EXT_DIGITAL) { //Externaly triggered - PINFO("Synchronous start. Externaly trigger active.\n"); - instance->start_mode |= ME6000_AO_SYNC_EXT_TRIG; - } -#ifdef MEDEBUG_INFO - else { - PINFO - ("Synchronous start. Externaly trigger dissabled.\n"); - } -#endif - - } - //Set speed - outl(conv_ticks - 2, instance->timer_reg); - PDEBUG_REG("timer_reg outl(0x%lX+0x%lX)=0x%llx\n", instance->reg_base, - instance->timer_reg - instance->reg_base, conv_ticks - 2); - instance->hardware_stop_delay = (int)(conv_ticks * HZ) / ME6000_AO_BASE_FREQUENCY; //<== MUST be with cast! - - // Write the control word - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Set status. - instance->status = ao_status_stream_configured; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_stream_new_values(me_subdevice_t *subdevice, - struct file *filep, - int time_out, int *count, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - long j; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (!instance->circ_buf.buf) { - PERROR("Circular buffer not exists.\n"); - return ME_ERRNO_INTERNAL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - ME_SUBDEVICE_ENTER; - - if (me_circ_buf_space(&instance->circ_buf)) { //The buffer is NOT full. - *count = me_circ_buf_space(&instance->circ_buf); - } else { //The buffer is full. - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } else { //Max time. - t = LONG_MAX; - } - - *count = 0; - - j = jiffies; - - //Only runing process will interrupt this call. Interrupts are when FIFO HF is signaled. - wait_event_interruptible_timeout(instance->wait_queue, - ((me_circ_buf_space - (&instance->circ_buf)) - || !(inl(instance->status_reg) - & - ME6000_AO_STATUS_BIT_FSM)), - t); - - if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) { - PERROR("AO subdevice is not running.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - } else if (signal_pending(current)) { - PERROR("Wait on values interrupted from signal.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } else if ((jiffies - j) >= t) { - PERROR("Wait on values timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } else { //Uff... all is good. Inform user about empty space. - *count = me_circ_buf_space(&instance->circ_buf); - } - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_stream_start(me_subdevice_t *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long cpu_flags = 0; - uint32_t status; - uint32_t ctrl; - uint32_t synch; - int count = 0; - int circ_buffer_count; - - unsigned long ref; - unsigned long delay = 0; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags & ~ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS) { - PERROR("Invalid flags.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid timeout specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if ((start_mode != ME_START_MODE_BLOCKING) - && (start_mode != ME_START_MODE_NONBLOCKING)) { - PERROR("Invalid start mode specified.\n"); - return ME_ERRNO_INVALID_START_MODE; - } - - if (time_out) { - delay = (time_out * HZ) / 1000; - if (delay == 0) - delay = 1; - } - - switch (instance->status) { //Checking actual mode. - case ao_status_stream_configured: - case ao_status_stream_end: - //Correct modes! - break; - - //The device is in wrong mode. - case ao_status_none: - case ao_status_single_configured: - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - PERROR - ("Subdevice must be preinitialize correctly for streaming.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - PDEBUG("Before restart broke stream 'STOP' must be caled.\n"); - return ME_STATUS_ERROR; - - case ao_status_stream_run_wait: - case ao_status_stream_run: - case ao_status_stream_end_wait: - PDEBUG("Stream is already working.\n"); - return ME_ERRNO_SUBDEVICE_BUSY; - - default: - instance->status = ao_status_stream_error; - PERROR_CRITICAL("Status is in wrong state!\n"); - return ME_ERRNO_INTERNAL; - - } - - ME_SUBDEVICE_ENTER; - - if (instance->mode == ME6000_AO_CONTINOUS) { //Continous - instance->circ_buf.tail += instance->preloaded_count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } - circ_buffer_count = me_circ_buf_values(&instance->circ_buf); - - if (!circ_buffer_count && !instance->preloaded_count) { //No values in buffer - ME_SUBDEVICE_EXIT; - PERROR("No values in buffer!\n"); - return ME_ERRNO_LACK_OF_RESOURCES; - } - - //Cancel control task - PDEBUG("Cancel control task. idx=%d\n", instance->ao_idx); - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - - //Stop device - err = ao_stop_immediately(instance); - if (err) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUBDEVICE_BUSY; - } - //Set values for single_read() - instance->single_value = ME6000_AO_MAX_DATA + 1; - instance->single_value_in_fifo = ME6000_AO_MAX_DATA + 1; - - //Setting stop points - if (instance->stop_mode == ME6000_AO_SCAN_STOP_MODE) { - instance->stop_data_count = - instance->stop_count * circ_buffer_count; - } else { - instance->stop_data_count = instance->stop_count; - } - - if ((instance->stop_data_count != 0) - && (instance->stop_data_count < circ_buffer_count)) { - PERROR("More data in buffer than previously set limit!\n"); - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - //Check FIFO - if (!(ctrl & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO wasn't enabeled. Do it. <= This should be done by user call with ME_WRITE_MODE_PRELOAD - PINFO("Enableing FIFO.\n"); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - - instance->preloaded_count = 0; - instance->data_count = 0; - } else { //Block IRQ - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - //Fill FIFO <= Generaly this should be done by user pre-load call but this is second place to do it. - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_EF)) { //FIFO empty - if (instance->stop_data_count != 0) { - count = ME6000_AO_FIFO_COUNT; - } else { - count = - (ME6000_AO_FIFO_COUNT < - instance-> - stop_data_count) ? ME6000_AO_FIFO_COUNT : - instance->stop_data_count; - } - - //Copy data - count = - ao_write_data(instance, count, instance->preloaded_count); - - if (count < 0) { //This should never happend! - PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - //Set pre-load features. - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - synch &= - ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - synch |= - (instance->start_mode & ~ME6000_AO_EXT_TRIG) << instance->ao_idx; - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); - - //Default count is '0' - if (instance->mode == ME6000_AO_CONTINOUS) { //Continous - instance->preloaded_count = 0; - instance->circ_buf.tail += count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } else { //Wraparound - instance->preloaded_count += count; - instance->data_count += count; - - //Special case: Infinite wraparound with less than FIFO datas always should runs in hardware mode. - if ((instance->stop_mode == ME6000_AO_INF_STOP_MODE) - && (circ_buffer_count <= ME6000_AO_FIFO_COUNT)) { //Change to hardware wraparound - PDEBUG - ("Changeing mode from software wraparound to hardware wraparound.\n"); - //Copy all data - count = - ao_write_data(instance, circ_buffer_count, - instance->preloaded_count); - ctrl &= ~ME6000_AO_CTRL_MODE_MASK; - ctrl |= ME6000_AO_MODE_WRAPAROUND; - } - - if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. - instance->preloaded_count = 0; - } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! - PERROR_CRITICAL - ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - - //Set status to 'wait for start' - instance->status = ao_status_stream_run_wait; - - status = inl(instance->status_reg); - //Start state machine and interrupts - PINFO("<%s:%d> Start state machine.\n", __func__, __LINE__); - ctrl &= ~(ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP); - if (instance->start_mode == ME6000_AO_EXT_TRIG) { - PDEBUG("DIGITAL TRIGGER\n"); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG; - } - if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half! - if ((ctrl & ME6000_AO_CTRL_MODE_MASK) == ME6000_AO_MODE_CONTINUOUS) { //Enable IRQ only when hardware_continous is set and FIFO is more than half - PINFO("<%s:%d> Start interrupts.\n", __func__, - __LINE__); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; - } - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - //Trigger output - PINFO("<%s> start mode= 0x%x %s\n", __func__, instance->start_mode, - (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) ? "SYNCHRONOUS" : - ""); - if (flags & ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS) { //Trigger outputs - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - //Add channel to start list - outl(synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx), - instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch | (ME6000_AO_SYNC_HOLD << instance->ao_idx)); - - //Fire - PINFO - ("Fired all software synchronous outputs by software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - - //Restore save settings - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); - } else if (!instance->start_mode) { //Trigger outputs -/* - spin_lock(instance->preload_reg_lock); - synch = inl(instance->preload_reg); - //Remove channel from start list - outl(synch & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx), instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch & ~(ME6000_AO_SYNC_HOLD << instance->ao_idx)); -*/ - //Fire - PINFO("Software trigger.\n"); - outl(0x8000, instance->single_reg); - PDEBUG_REG("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, 0x8000); - -/* - //Restore save settings - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, instance->preload_reg - instance->reg_base, synch); - spin_unlock(instance->preload_reg_lock); -*/ - } - // Set control task's timeout - instance->timeout.delay = delay; - instance->timeout.start_time = jiffies; - - if (status & ME6000_AO_STATUS_BIT_HF) { //Less than half but not empty! - PINFO("Less than half.\n"); - if (instance->stop_data_count == 0) { - count = ME6000_AO_FIFO_COUNT / 2; - } else { - count = - ((ME6000_AO_FIFO_COUNT / 2) < - instance->stop_data_count) ? ME6000_AO_FIFO_COUNT / - 2 : instance->stop_data_count; - } - - //Copy data - count = - ao_write_data(instance, count, instance->preloaded_count); - - if (count < 0) { //This should never happend! - PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - if (instance->mode == ME6000_AO_CONTINOUS) { //Continous - instance->circ_buf.tail += count; - instance->circ_buf.tail &= instance->circ_buf.mask; - } else { //Wraparound - instance->data_count += count; - instance->preloaded_count += count; - - if (instance->preloaded_count == me_circ_buf_values(&instance->circ_buf)) { //Reset position indicator. - instance->preloaded_count = 0; - } else if (instance->preloaded_count > me_circ_buf_values(&instance->circ_buf)) { //This should never happend! - PERROR_CRITICAL - ("PRELOADED MORE VALUES THAN ARE IN BUFFER!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - } - - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_HF)) { //More than half! - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - PINFO("<%s:%d> Start interrupts.\n", __func__, - __LINE__); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - } - } - //Special case: Limited wraparound with less than HALF FIFO datas need work around to generate first interrupt. - if ((instance->stop_mode != ME6000_AO_INF_STOP_MODE) - && (instance->mode == ME6000_AO_SW_WRAP_MODE) - && (circ_buffer_count <= (ME6000_AO_FIFO_COUNT / 2))) { //Put more data to FIFO - PINFO("Limited wraparound with less than HALF FIFO datas.\n"); - if (instance->preloaded_count) { //This should never happend! - PERROR_CRITICAL - ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - - while (instance->stop_data_count > instance->data_count) { //Maximum data not set jet. - //Copy to buffer - if (circ_buffer_count != ao_write_data(instance, circ_buffer_count, 0)) { //This should never happend! - PERROR_CRITICAL - ("ERROR WHEN LOADING VALUES FOR WRAPAROUND!\n"); - ME_SUBDEVICE_EXIT; - return ME_ERRNO_INTERNAL; - } - instance->data_count += circ_buffer_count; - - if (!((status = inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF)) { //FIFO is more than half. Enable IRQ and end copy. - //Reset interrupt latch - inl(instance->irq_reset_reg); - - spin_lock_irqsave(&instance->subdevice_lock, - cpu_flags); - PINFO("<%s:%d> Start interrupts.\n", - __func__, __LINE__); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - break; - } - } - } - // Schedule control task - instance->ao_control_task_flag = 1; - queue_delayed_work(instance->me6000_workqueue, - &instance->ao_control_task, 1); - - if (start_mode == ME_START_MODE_BLOCKING) { //Wait for start. - ref = jiffies; - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_stream_run_wait), - (delay) ? delay + - 1 : LONG_MAX); - - if ((instance->status != ao_status_stream_run) - && (instance->status != ao_status_stream_end)) { - PDEBUG("Starting stream canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait on start of state machine interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - - if ((delay) && ((jiffies - ref) >= delay)) { - if (instance->status != ao_status_stream_run) { - if (instance->status == ao_status_stream_end) { - PDEBUG("Timeout reached.\n"); - } else if ((jiffies - ref) > delay) { - PERROR - ("Timeout reached. Not handled by control task!\n"); - ao_stop_immediately(instance); - } else { - PERROR - ("Timeout reached. Signal come but status is strange: %d\n", - instance->status); - ao_stop_immediately(instance); - } - - instance->ao_control_task_flag = 0; - cancel_delayed_work(&instance->ao_control_task); - instance->status = ao_status_stream_end; - err = ME_ERRNO_TIMEOUT; - } - } - } - - ME_SUBDEVICE_EXIT; - return err; -} - -static int me6000_ao_io_stream_status(me_subdevice_t *subdevice, - struct file *filep, - int wait, - int *status, int *values, int flags) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((wait != ME_WAIT_NONE) && (wait != ME_WAIT_IDLE)) { - PERROR("Invalid wait argument specified.\n"); - *status = ME_STATUS_INVALID; - return ME_ERRNO_INVALID_WAIT; - } - - ME_SUBDEVICE_ENTER; - - switch (instance->status) { - case ao_status_single_configured: - case ao_status_single_end: - case ao_status_stream_configured: - case ao_status_stream_end: - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - *status = ME_STATUS_IDLE; - break; - - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - case ao_status_stream_run_wait: - case ao_status_stream_run: - case ao_status_stream_end_wait: - *status = ME_STATUS_BUSY; - break; - - case ao_status_none: - default: - *status = - (inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM) ? - ME_STATUS_BUSY : ME_STATUS_IDLE; - break; - } - - if ((wait == ME_WAIT_IDLE) && (*status == ME_STATUS_BUSY)) { - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - ((instance->status != - ao_status_single_run_wait) - && (instance->status != - ao_status_single_run) - && (instance->status != - ao_status_single_end_wait) - && (instance->status != - ao_status_stream_run_wait) - && (instance->status != - ao_status_stream_run) - && (instance->status != - ao_status_stream_end_wait)), - LONG_MAX); - - if (instance->status != ao_status_stream_end) { - PDEBUG("Wait for IDLE canceled. %d\n", - instance->status); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Wait for IDLE interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - - *status = ME_STATUS_IDLE; - } - - *values = me_circ_buf_space(&instance->circ_buf); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_stream_stop(me_subdevice_t *subdevice, - struct file *filep, - int stop_mode, int flags) -{ /// @note Stop work and empty buffer and FIFO - int err = ME_ERRNO_SUCCESS; - me6000_ao_subdevice_t *instance; - unsigned long cpu_flags; - volatile uint32_t ctrl; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (flags & ~ME_IO_STREAM_STOP_PRESERVE_BUFFERS) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((stop_mode != ME_STOP_MODE_IMMEDIATE) - && (stop_mode != ME_STOP_MODE_LAST_VALUE)) { - PERROR("Invalid stop mode specified.\n"); - return ME_ERRNO_INVALID_STOP_MODE; - } - - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (instance->status < ao_status_stream_configured) { - //There is nothing to stop! - PERROR("Subdevice not in streaming mode. %d\n", - instance->status); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - ME_SUBDEVICE_ENTER; - - //Mark as stopping. => Software stop. - instance->status = ao_status_stream_end_wait; - - if (stop_mode == ME_STOP_MODE_IMMEDIATE) { //Stopped now! - err = ao_stop_immediately(instance); - } else if (stop_mode == ME_STOP_MODE_LAST_VALUE) { - ctrl = inl(instance->ctrl_reg) & ME6000_AO_CTRL_MODE_MASK; - if (ctrl == ME6000_AO_MODE_WRAPAROUND) { //Hardware wraparound => Hardware stop. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME6000_AO_CTRL_BIT_STOP; - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - } - //Only runing process will interrupt this call. Events are signaled when status change. Extra timeout add for safe reason. - wait_event_interruptible_timeout(instance->wait_queue, - (instance->status != - ao_status_stream_end_wait), - LONG_MAX); - - if (instance->status != ao_status_stream_end) { - PDEBUG("Stopping stream canceled.\n"); - err = ME_ERRNO_CANCELLED; - } - - if (signal_pending(current)) { - PERROR("Stopping stream interrupted.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - } - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - if (!flags) { //Reset FIFO - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO; - } - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - if (!flags) { //Reset software buffer - instance->circ_buf.head = 0; - instance->circ_buf.tail = 0; - instance->preloaded_count = 0; - instance->data_count = 0; - } - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_ao_io_stream_write(me_subdevice_t *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me6000_ao_subdevice_t *instance; - unsigned long cpu_flags = 0; - uint32_t reg_copy; - - int copied_from_user = 0; - int left_to_copy_from_user = *count; - - int copied_values; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - //Checking arguments - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { - PERROR("Not a streaming ao.\n"); - return ME_ERRNO_NOT_SUPPORTED; - } - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (*count <= 0) { - PERROR("Invalid count of values specified.\n"); - return ME_ERRNO_INVALID_VALUE_COUNT; - } - - if (values == NULL) { - PERROR("Invalid address of values specified.\n"); - return ME_ERRNO_INVALID_POINTER; - } - - if ((instance->status == ao_status_none) || (instance->status == ao_status_single_configured)) { //The device is in single mode. - PERROR - ("Subdevice must be preinitialize correctly for streaming.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - - switch (write_mode) { - case ME_WRITE_MODE_PRELOAD: - - //Device must be stopped. - if ((instance->status != ao_status_stream_configured) - && (instance->status != ao_status_stream_end)) { - PERROR - ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; - } - break; - case ME_WRITE_MODE_NONBLOCKING: - case ME_WRITE_MODE_BLOCKING: - /// @note In blocking mode: When device is not runing and there is not enought space call will blocked up! - /// @note Some other thread must empty buffer by strating engine. - break; - - default: - PERROR("Invalid write mode specified.\n"); - return ME_ERRNO_INVALID_WRITE_MODE; - } - - if (instance->mode & ME6000_AO_WRAP_MODE) { //Wraparound mode. Device must be stopped. - if ((instance->status != ao_status_stream_configured) - && (instance->status != ao_status_stream_end)) { - PERROR - ("Subdevice mustn't be runing when 'pre-load' mode is used.\n"); - return ME_ERRNO_INVALID_WRITE_MODE; - } - } - - if ((instance->mode == ME6000_AO_HW_WRAP_MODE) - && (write_mode != ME_WRITE_MODE_PRELOAD)) { -/* - PERROR("Only 'pre-load' write is acceptable in hardware wraparound mode.\n"); - return ME_ERRNO_PREVIOUS_CONFIG; -*/ - //This is transparent for user. - PDEBUG("Changing write_mode to ME_WRITE_MODE_PRELOAD.\n"); - write_mode = ME_WRITE_MODE_PRELOAD; - } - - ME_SUBDEVICE_ENTER; - - if (write_mode == ME_WRITE_MODE_PRELOAD) { //Init enviroment - preload - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - //Check FIFO - if (!(reg_copy & ME6000_AO_CTRL_BIT_ENABLE_FIFO)) { //FIFO not active. Enable it. - reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_FIFO; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - instance->preloaded_count = 0; - } - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - } - - while (1) { - //Copy to buffer. This step is common for all modes. - copied_from_user = - ao_get_data_from_user(instance, left_to_copy_from_user, - values + (*count - - left_to_copy_from_user)); - left_to_copy_from_user -= copied_from_user; - - reg_copy = inl(instance->status_reg); - if ((instance->status == ao_status_stream_run) && !(reg_copy & ME6000_AO_STATUS_BIT_FSM)) { //BROKEN PIPE! The state machine is stoped but logical status show that should be working. - PERROR("Broken pipe in write.\n"); - err = ME_ERRNO_SUBDEVICE_NOT_RUNNING; - break; - } - - if ((instance->status == ao_status_stream_run) && (instance->mode == ME6000_AO_CONTINOUS) && (reg_copy & ME6000_AO_STATUS_BIT_HF)) { //Continous mode runing and data are below half! - - // Block interrupts. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - reg_copy &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - //Fast copy - copied_values = - ao_write_data(instance, ME6000_AO_FIFO_COUNT / 2, - 0); - if (copied_values > 0) { - instance->circ_buf.tail += copied_values; - instance->circ_buf.tail &= - instance->circ_buf.mask; - continue; - } - //Reset interrupt latch - inl(instance->irq_reset_reg); - - // Activate interrupts. - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - reg_copy = inl(instance->ctrl_reg); - reg_copy |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(reg_copy, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - reg_copy); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (copied_values == 0) { //This was checked and never should happend! - PERROR_CRITICAL("COPY FINISH WITH 0!\n"); - } - - if (copied_values < 0) { //This was checked and never should happend! - PERROR_CRITICAL("COPY FINISH WITH ERROR!\n"); - instance->status = ao_status_stream_fifo_error; - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - break; - } - } - - if (!left_to_copy_from_user) { //All datas were copied. - break; - } else { //Not all datas were copied. - if (instance->mode & ME6000_AO_WRAP_MODE) { //Error too much datas! Wraparound is limited in size! - PERROR - ("Too much data for wraparound mode! Exceeded size of %ld.\n", - ME6000_AO_CIRC_BUF_COUNT - 1); - err = ME_ERRNO_RING_BUFFER_OVERFLOW; - break; - } - - if (write_mode != ME_WRITE_MODE_BLOCKING) { //Non blocking calls - break; - } - - wait_event_interruptible(instance->wait_queue, - me_circ_buf_space(&instance-> - circ_buf)); - - if (signal_pending(current)) { - PERROR("Writing interrupted by signal.\n"); - instance->status = ao_status_none; - ao_stop_immediately(instance); - err = ME_ERRNO_SIGNAL; - break; - } - - if (instance->status == ao_status_none) { //Reset - PERROR("Writing interrupted by reset.\n"); - err = ME_ERRNO_CANCELLED; - break; - } - } - } - - if (write_mode == ME_WRITE_MODE_PRELOAD) { //Copy data to FIFO - preload - copied_values = - ao_write_data_pooling(instance, ME6000_AO_FIFO_COUNT, - instance->preloaded_count); - instance->preloaded_count += copied_values; - instance->data_count += copied_values; - - if ((instance->mode == ME6000_AO_HW_WRAP_MODE) - && (me_circ_buf_values(&instance->circ_buf) > - ME6000_AO_FIFO_COUNT)) { - PERROR - ("Too much data for hardware wraparound mode! Exceeded size of %d.\n", - ME6000_AO_FIFO_COUNT); - err = ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } - } - - *count = *count - left_to_copy_from_user; - ME_SUBDEVICE_EXIT; - - return err; -} - -static irqreturn_t me6000_ao_isr(int irq, void *dev_id) -{ - me6000_ao_subdevice_t *instance = dev_id; - uint32_t irq_status; - uint32_t ctrl; - uint32_t status; - int count = 0; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inl(instance->irq_status_reg); - if (!(irq_status & (ME6000_IRQ_STATUS_BIT_AO_HF << instance->ao_idx))) { - PINFO("%ld Shared interrupt. %s(): ID=%d: status_reg=0x%04X\n", - jiffies, __func__, instance->ao_idx, irq_status); - return IRQ_NONE; - } - - if (!instance->circ_buf.buf) { - instance->status = ao_status_stream_error; - PERROR_CRITICAL("CIRCULAR BUFFER NOT EXISTS!\n"); - //Block interrupts. Stop machine. - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | ME6000_AO_CTRL_BIT_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Inform user - wake_up_interruptible_all(&instance->wait_queue); - return IRQ_HANDLED; - } - - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_FSM)) { //Too late. Not working! END? BROKEN PIPE? - /// @note Error checking was moved to separate task. - PDEBUG("Interrupt come but ISM is not working!\n"); - //Block interrupts. Stop machine. - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - ctrl |= - ME6000_AO_CTRL_BIT_STOP | ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - /// @note User notification was also moved to separate task. - return IRQ_HANDLED; - } - //General procedure. Process more datas. - -#ifdef MEDEBUG_DEBUG - if (!me_circ_buf_values(&instance->circ_buf)) { //Buffer is empty! - PDEBUG("Circular buffer empty!\n"); - } -#endif - - //Check FIFO - if (status & ME6000_AO_STATUS_BIT_HF) { //OK less than half - - //Block interrupts - ctrl = inl(instance->ctrl_reg); - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_IRQ; - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - - do { - //Calculate how many should be copied. - count = - (instance->stop_data_count) ? instance-> - stop_data_count - - instance->data_count : ME6000_AO_FIFO_COUNT / 2; - if (ME6000_AO_FIFO_COUNT / 2 < count) { - count = ME6000_AO_FIFO_COUNT / 2; - } - //Copy data - if (instance->mode == ME6000_AO_CONTINOUS) { //Continous - count = ao_write_data(instance, count, 0); - if (count > 0) { - instance->circ_buf.tail += count; - instance->circ_buf.tail &= - instance->circ_buf.mask; - instance->data_count += count; - - if ((instance->status == ao_status_stream_end_wait) && !me_circ_buf_values(&instance->circ_buf)) { //Stoping. Whole buffer was copied. - break; - } - } - } else if ((instance->mode == ME6000_AO_SW_WRAP_MODE) && ((ctrl & ME6000_AO_CTRL_MODE_MASK) == ME6000_AO_MODE_CONTINUOUS)) { //Wraparound (software) - if (instance->status == ao_status_stream_end_wait) { //We stoping => Copy to the end of the buffer. - count = - ao_write_data(instance, count, 0); - } else { //Copy in wraparound mode. - count = - ao_write_data_wraparound(instance, - count, - instance-> - preloaded_count); - } - - if (count > 0) { - instance->data_count += count; - instance->preloaded_count += count; - instance->preloaded_count %= - me_circ_buf_values(&instance-> - circ_buf); - - if ((instance->status == ao_status_stream_end_wait) && !instance->preloaded_count) { //Stoping. Whole buffer was copied. - break; - } - } - } - - if ((count <= 0) || (instance->stop_data_count && (instance->stop_data_count <= instance->data_count))) { //End of work. - break; - } - } //Repeat if still is under half fifo - while ((status = - inl(instance->status_reg)) & ME6000_AO_STATUS_BIT_HF); - - //Unblock interrupts - ctrl = inl(instance->ctrl_reg); - if (count >= 0) { //Copy was successful. - if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. No more interrupts. - PDEBUG("Finishing work. Interrupt disabled.\n"); - instance->status = ao_status_stream_end_wait; - } else if (count > 0) { //Normal work. Enable interrupt. - PDEBUG("Normal work. Enable interrupt.\n"); - ctrl |= ME6000_AO_CTRL_BIT_ENABLE_IRQ; - } else { //Normal work but there are no more data in buffer. Interrupt blocked. stream_write() will unblock it. - PDEBUG - ("No data in software buffer. Interrupt blocked.\n"); - } - } else { //Error during copy. - instance->status = ao_status_stream_fifo_error; - } - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - } else { //?? more than half - PDEBUG - ("Interrupt come but FIFO more than half full! Reset interrupt.\n"); - } - - PINFO("ISR: Buffer count: %d.(T:%d H:%d)\n", - me_circ_buf_values(&instance->circ_buf), instance->circ_buf.tail, - instance->circ_buf.head); - PINFO("ISR: Stop count: %d.\n", instance->stop_count); - PINFO("ISR: Stop data count: %d.\n", instance->stop_data_count); - PINFO("ISR: Data count: %d.\n", instance->data_count); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - //Inform user - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -static void me6000_ao_destructor(struct me_subdevice *subdevice) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - instance->ao_control_task_flag = 0; - - // Reset subdevice to asure clean exit. - me6000_ao_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - - // Remove any tasks from work queue. This is paranoic because it was done allready in reset(). - if (!cancel_delayed_work(&instance->ao_control_task)) { //Wait 2 ticks to be sure that control task is removed from queue. - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(2); - } - - if (instance->fifo & ME6000_AO_HAS_FIFO) { - if (instance->irq) { - free_irq(instance->irq, instance); - instance->irq = 0; - } - - if (instance->circ_buf.buf) { - PDEBUG("free circ_buf = %p size=%d", - instance->circ_buf.buf, - PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER); - free_pages((unsigned long)instance->circ_buf.buf, - ME6000_AO_CIRC_BUF_SIZE_ORDER); - } - instance->circ_buf.buf = NULL; - } - - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -me6000_ao_subdevice_t *me6000_ao_constructor(uint32_t reg_base, - spinlock_t *preload_reg_lock, - uint32_t *preload_flags, - uint32_t *triggering_flags, - int ao_idx, - int fifo, - int irq, - int high_range, - struct workqueue_struct *me6000_wq) -{ - me6000_ao_subdevice_t *subdevice; - int err; - - PDEBUG("executed ID=%d.\n", ao_idx); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me6000_ao_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me6000_ao_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->preload_reg_lock = preload_reg_lock; - subdevice->preload_flags = preload_flags; - subdevice->triggering_flags = triggering_flags; - - /* Store analog output index */ - subdevice->ao_idx = ao_idx; - - /* Store if analog output has fifo */ - subdevice->fifo = fifo; - - if (subdevice->fifo & ME6000_AO_HAS_FIFO) { - /* Allocate and initialize circular buffer */ - subdevice->circ_buf.mask = ME6000_AO_CIRC_BUF_COUNT - 1; - subdevice->circ_buf.buf = - (void *)__get_free_pages(GFP_KERNEL, - ME6000_AO_CIRC_BUF_SIZE_ORDER); - PDEBUG("circ_buf = %p size=%ld\n", subdevice->circ_buf.buf, - ME6000_AO_CIRC_BUF_SIZE); - - if (!subdevice->circ_buf.buf) { - PERROR - ("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - - memset(subdevice->circ_buf.buf, 0, ME6000_AO_CIRC_BUF_SIZE); - } else { - subdevice->circ_buf.mask = 0; - subdevice->circ_buf.buf = NULL; - } - subdevice->circ_buf.head = 0; - subdevice->circ_buf.tail = 0; - - subdevice->status = ao_status_none; - subdevice->ao_control_task_flag = 0; - subdevice->timeout.delay = 0; - subdevice->timeout.start_time = jiffies; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Initialize single value to 0V */ - subdevice->single_value = 0x8000; - subdevice->single_value_in_fifo = 0x8000; - - /* Initialize range boarders */ - if (high_range) { - subdevice->min = ME6000_AO_MIN_RANGE_HIGH; - subdevice->max = ME6000_AO_MAX_RANGE_HIGH; - } else { - subdevice->min = ME6000_AO_MIN_RANGE; - subdevice->max = ME6000_AO_MAX_RANGE; - } - - /* Register interrupt service routine */ - - if (subdevice->fifo & ME6000_AO_HAS_FIFO) { - subdevice->irq = irq; - if (request_irq(subdevice->irq, me6000_ao_isr, - IRQF_DISABLED | IRQF_SHARED, - ME6000_NAME, subdevice)) { - PERROR("Cannot get interrupt line.\n"); - PDEBUG("free circ_buf = %p size=%d", - subdevice->circ_buf.buf, - PAGE_SHIFT << ME6000_AO_CIRC_BUF_SIZE_ORDER); - free_pages((unsigned long)subdevice->circ_buf.buf, - ME6000_AO_CIRC_BUF_SIZE_ORDER); - subdevice->circ_buf.buf = NULL; - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - } else { - subdevice->irq = 0; - } - - /* Initialize registers */ - // Only streamed subdevices support interrupts. For the rest this register has no meaning. - subdevice->irq_status_reg = reg_base + ME6000_AO_IRQ_STATUS_REG; - subdevice->preload_reg = reg_base + ME6000_AO_PRELOAD_REG; - - if (ao_idx == 0) { - subdevice->ctrl_reg = reg_base + ME6000_AO_00_CTRL_REG; - subdevice->status_reg = reg_base + ME6000_AO_00_STATUS_REG; - subdevice->fifo_reg = reg_base + ME6000_AO_00_FIFO_REG; - subdevice->timer_reg = reg_base + ME6000_AO_00_TIMER_REG; - subdevice->irq_reset_reg = - reg_base + ME6000_AO_00_IRQ_RESET_REG; - subdevice->single_reg = reg_base + ME6000_AO_00_SINGLE_REG; - } else if (ao_idx == 1) { - subdevice->ctrl_reg = reg_base + ME6000_AO_01_CTRL_REG; - subdevice->status_reg = reg_base + ME6000_AO_01_STATUS_REG; - subdevice->fifo_reg = reg_base + ME6000_AO_01_FIFO_REG; - subdevice->timer_reg = reg_base + ME6000_AO_01_TIMER_REG; - subdevice->irq_reset_reg = - reg_base + ME6000_AO_01_IRQ_RESET_REG; - subdevice->single_reg = reg_base + ME6000_AO_01_SINGLE_REG; - } else if (ao_idx == 2) { - subdevice->ctrl_reg = reg_base + ME6000_AO_02_CTRL_REG; - subdevice->status_reg = reg_base + ME6000_AO_02_STATUS_REG; - subdevice->fifo_reg = reg_base + ME6000_AO_02_FIFO_REG; - subdevice->timer_reg = reg_base + ME6000_AO_02_TIMER_REG; - subdevice->irq_reset_reg = - reg_base + ME6000_AO_02_IRQ_RESET_REG; - subdevice->single_reg = reg_base + ME6000_AO_02_SINGLE_REG; - } else if (ao_idx == 3) { - subdevice->ctrl_reg = reg_base + ME6000_AO_03_CTRL_REG; - subdevice->status_reg = reg_base + ME6000_AO_03_STATUS_REG; - subdevice->fifo_reg = reg_base + ME6000_AO_03_FIFO_REG; - subdevice->timer_reg = reg_base + ME6000_AO_03_TIMER_REG; - subdevice->irq_reset_reg = - reg_base + ME6000_AO_03_IRQ_RESET_REG; - subdevice->single_reg = reg_base + ME6000_AO_03_SINGLE_REG; - } else { - subdevice->ctrl_reg = reg_base + ME6000_AO_DUMY; - subdevice->fifo_reg = reg_base + ME6000_AO_DUMY; - subdevice->timer_reg = reg_base + ME6000_AO_DUMY; - subdevice->irq_reset_reg = reg_base + ME6000_AO_DUMY; - subdevice->single_reg = reg_base + ME6000_AO_DUMY; - - subdevice->status_reg = reg_base + ME6000_AO_SINGLE_STATUS_REG; - if (ao_idx == 4) { - subdevice->single_reg = - reg_base + ME6000_AO_04_SINGLE_REG; - } else if (ao_idx == 5) { - subdevice->single_reg = - reg_base + ME6000_AO_05_SINGLE_REG; - } else if (ao_idx == 6) { - subdevice->single_reg = - reg_base + ME6000_AO_06_SINGLE_REG; - } else if (ao_idx == 7) { - subdevice->single_reg = - reg_base + ME6000_AO_07_SINGLE_REG; - } else if (ao_idx == 8) { - subdevice->single_reg = - reg_base + ME6000_AO_08_SINGLE_REG; - } else if (ao_idx == 9) { - subdevice->single_reg = - reg_base + ME6000_AO_09_SINGLE_REG; - } else if (ao_idx == 10) { - subdevice->single_reg = - reg_base + ME6000_AO_10_SINGLE_REG; - } else if (ao_idx == 11) { - subdevice->single_reg = - reg_base + ME6000_AO_11_SINGLE_REG; - } else if (ao_idx == 12) { - subdevice->single_reg = - reg_base + ME6000_AO_12_SINGLE_REG; - } else if (ao_idx == 13) { - subdevice->single_reg = - reg_base + ME6000_AO_13_SINGLE_REG; - } else if (ao_idx == 14) { - subdevice->single_reg = - reg_base + ME6000_AO_14_SINGLE_REG; - } else if (ao_idx == 15) { - subdevice->single_reg = - reg_base + ME6000_AO_15_SINGLE_REG; - } else { - PERROR_CRITICAL("WRONG SUBDEVICE ID=%d!", ao_idx); - me_subdevice_deinit((me_subdevice_t *) subdevice); - if (subdevice->fifo) { - free_pages((unsigned long)subdevice->circ_buf. - buf, ME6000_AO_CIRC_BUF_SIZE_ORDER); - } - subdevice->circ_buf.buf = NULL; - kfree(subdevice); - return NULL; - } - } -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Override base class methods. */ - subdevice->base.me_subdevice_destructor = me6000_ao_destructor; - subdevice->base.me_subdevice_io_reset_subdevice = - me6000_ao_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me6000_ao_io_single_config; - subdevice->base.me_subdevice_io_single_read = me6000_ao_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me6000_ao_io_single_write; - subdevice->base.me_subdevice_io_stream_config = - me6000_ao_io_stream_config; - subdevice->base.me_subdevice_io_stream_new_values = - me6000_ao_io_stream_new_values; - subdevice->base.me_subdevice_io_stream_write = - me6000_ao_io_stream_write; - subdevice->base.me_subdevice_io_stream_start = - me6000_ao_io_stream_start; - subdevice->base.me_subdevice_io_stream_status = - me6000_ao_io_stream_status; - subdevice->base.me_subdevice_io_stream_stop = me6000_ao_io_stream_stop; - subdevice->base.me_subdevice_query_number_channels = - me6000_ao_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me6000_ao_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me6000_ao_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me6000_ao_query_subdevice_caps_args; - subdevice->base.me_subdevice_query_range_by_min_max = - me6000_ao_query_range_by_min_max; - subdevice->base.me_subdevice_query_number_ranges = - me6000_ao_query_number_ranges; - subdevice->base.me_subdevice_query_range_info = - me6000_ao_query_range_info; - subdevice->base.me_subdevice_query_timer = me6000_ao_query_timer; - - //prepare work queue and work function - subdevice->me6000_workqueue = me6000_wq; - -/* workqueue API changed in kernel 2.6.20 */ - INIT_DELAYED_WORK(&subdevice->ao_control_task, - me6000_ao_work_control_task); - - if (subdevice->fifo) { //Set speed - outl(ME6000_AO_MIN_CHAN_TICKS - 1, subdevice->timer_reg); - subdevice->hardware_stop_delay = HZ / 10; //100ms - } - - return subdevice; -} - -/** @brief Stop presentation. Preserve FIFOs. -* -* @param instance The subdevice instance (pointer). -*/ -inline int ao_stop_immediately(me6000_ao_subdevice_t *instance) -{ - unsigned long cpu_flags; - uint32_t ctrl; - int timeout; - int i; - uint32_t single_mask; - - if (instance->ao_idx < ME6000_AO_SINGLE_STATUS_OFFSET) - single_mask = 0x0000; - else - single_mask = 0x0001 << (instance->ao_idx - - ME6000_AO_SINGLE_STATUS_OFFSET); - - timeout = - (instance->hardware_stop_delay > - (HZ / 10)) ? instance->hardware_stop_delay : HZ / 10; - for (i = 0; i <= timeout; i++) { - if (instance->fifo) { - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME6000_AO_CTRL_BIT_STOP | - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; - ctrl &= - ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | - ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - if (!(inl(instance->status_reg) & ME6000_AO_STATUS_BIT_FSM)) { // Exit. - break; - } - } else { - if (!(inl(instance->status_reg) & single_mask)) { // Exit. - break; - } - } - - PINFO("<%s> Wait for stop: %d\n", __func__, i); - - //Still working! - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } - - if (i > timeout) { - PERROR_CRITICAL("FSM IS BUSY!\n"); - return ME_ERRNO_INTERNAL; - } - return ME_ERRNO_SUCCESS; -} - -/** @brief Copy data from circular buffer to fifo (fast) in wraparound. -* @note This is time critical function. Checking is done at begining and end only. -* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied data. -* @return On error/success: 0. No datas were copied => no data in buffer. -* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. -*/ -inline int ao_write_data_wraparound(me6000_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is time critical function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int i = 1; - - if (count <= 0) { //Wrong count! - return 0; - } - - while (i < local_count) { - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - if (pos == instance->circ_buf.head) { - pos = instance->circ_buf.tail; - } - i++; - } - - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! - PERROR("idx=%d FIFO is full before all datas were copied!\n", - instance->ao_idx); - return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } else { //Add last value - value = *(instance->circ_buf.buf + pos); - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - } - - PINFO("idx=%d WRAPAROUND LOADED %d values\n", instance->ao_idx, - local_count); - return local_count; -} - -/** @brief Copy data from software buffer to fifo (fast). -* @note This is time critical function. Checking is done at begining and end only. -* @note The is not reasonable way to check how many walues was in FIFO at begining. The count must be managed externaly. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied data. -* @return On error/success: 0. No datas were copied => no data in buffer. -* @return On error: -ME_ERRNO_FIFO_BUFFER_OVERFLOW. -*/ -inline int ao_write_data(me6000_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is time critical function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int max_count; - int i = 1; - - if (count <= 0) { //Wrong count! - return 0; - } - - max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; - if (max_count <= 0) { //No data to copy! - return 0; - } - - if (max_count < count) { - local_count = max_count; - } - - while (i < local_count) { - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - i++; - } - - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full before all datas were copied! - PERROR("idx=%d FIFO is full before all datas were copied!\n", - instance->ao_idx); - return -ME_ERRNO_FIFO_BUFFER_OVERFLOW; - } else { //Add last value - value = *(instance->circ_buf.buf + pos); - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - } - - PINFO("idx=%d FAST LOADED %d values\n", instance->ao_idx, local_count); - return local_count; -} - -/** @brief Copy data from software buffer to fifo (slow). -* @note This is slow function that copy all data from buffer to FIFO with full control. -* -* @param instance The subdevice instance (pointer). -* @param count Maximum number of copied data. -* @param start_pos Position of the firs value in buffer. -* -* @return On success: Number of copied values. -* @return On error/success: 0. FIFO was full at begining. -* @return On error: -ME_ERRNO_RING_BUFFER_UNDEFFLOW. -*/ -inline int ao_write_data_pooling(me6000_ao_subdevice_t *instance, int count, - int start_pos) -{ /// @note This is slow function! - uint32_t status; - uint32_t value; - int pos = - (instance->circ_buf.tail + start_pos) & instance->circ_buf.mask; - int local_count = count; - int i; - int max_count; - - if (count <= 0) { //Wrong count! - PERROR("idx=%d SLOW LOADED: Wrong count!\n", instance->ao_idx); - return 0; - } - - max_count = me_circ_buf_values(&instance->circ_buf) - start_pos; - if (max_count <= 0) { //No data to copy! - PERROR("idx=%d SLOW LOADED: No data to copy!\n", - instance->ao_idx); - return 0; - } - - if (max_count < count) { - local_count = max_count; - } - - for (i = 0; i < local_count; i++) { - status = inl(instance->status_reg); - if (!(status & ME6000_AO_STATUS_BIT_FF)) { //FIFO is full! - return i; - } - //Get value from buffer - value = *(instance->circ_buf.buf + pos); - //Prepare it - if (instance->ao_idx & 0x1) { - value <<= 16; - } - //Put value to FIFO - outl(value, instance->fifo_reg); - //PDEBUG_REG("idx=%d fifo_reg outl(0x%lX+0x%lX)=0x%x\n", instance->ao_idx, instance->reg_base, instance->fifo_reg - instance->reg_base, value); - - pos++; - pos &= instance->circ_buf.mask; - } - - PINFO("idx=%d SLOW LOADED %d values\n", instance->ao_idx, local_count); - return local_count; -} - -/** @brief Copy data from user space to circular buffer. -* @param instance The subdevice instance (pointer). -* @param count Number of datas in user space. -* @param user_values Buffer's pointer. -* -* @return On success: Number of copied values. -* @return On error: -ME_ERRNO_INTERNAL. -*/ -inline int ao_get_data_from_user(me6000_ao_subdevice_t *instance, int count, - int *user_values) -{ - int i, err; - int empty_space; - int copied; - int value; - - empty_space = me_circ_buf_space(&instance->circ_buf); - //We have only this space free. - copied = (count < empty_space) ? count : empty_space; - for (i = 0; i < copied; i++) { //Copy from user to buffer - if ((err = get_user(value, (int *)(user_values + i)))) { - PERROR - ("idx=%d BUFFER LOADED: get_user(0x%p) return an error: %d\n", - instance->ao_idx, user_values + i, err); - return -ME_ERRNO_INTERNAL; - } - /// @note The analog output in me6000 series has size of 16 bits. - *(instance->circ_buf.buf + instance->circ_buf.head) = - (uint16_t) value; - instance->circ_buf.head++; - instance->circ_buf.head &= instance->circ_buf.mask; - } - - PINFO("idx=%d BUFFER LOADED %d values\n", instance->ao_idx, copied); - return copied; -} - -static void me6000_ao_work_control_task(struct work_struct *work) -{ - me6000_ao_subdevice_t *instance; - unsigned long cpu_flags = 0; - uint32_t status; - uint32_t ctrl; - uint32_t synch; - int reschedule = 0; - int signaling = 0; - uint32_t single_mask; - - instance = - container_of((void *)work, me6000_ao_subdevice_t, ao_control_task); - PINFO("<%s: %ld> executed. idx=%d\n", __func__, jiffies, - instance->ao_idx); - - status = inl(instance->status_reg); - PDEBUG_REG("status_reg inl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->status_reg - instance->reg_base, status); - -/// @note AO_STATUS_BIT_FSM doesn't work as should be for pure single channels (idx>=4) -// single_mask = (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET < 0) ? 0x0000 : (0x0001 << (instance->ao_idx-ME6000_AO_SINGLE_STATUS_OFFSET)); - single_mask = *instance->triggering_flags & (0x1 << instance->ao_idx); - - switch (instance->status) { // Checking actual mode. - - // Not configured for work. - case ao_status_none: - break; - - //This are stable modes. No need to do anything. (?) - case ao_status_single_configured: - case ao_status_stream_configured: - case ao_status_stream_fifo_error: - case ao_status_stream_buffer_error: - case ao_status_stream_error: - PERROR("Shouldn't be running!.\n"); - break; - - // Single modes - case ao_status_single_run_wait: - case ao_status_single_run: - case ao_status_single_end_wait: - if (instance->fifo) { // Extra registers. - if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. - if (((instance->fifo & ME6000_AO_HAS_FIFO) - && (!(status & ME6000_AO_STATUS_BIT_EF))) - || (!(instance->fifo & ME6000_AO_HAS_FIFO))) { // Single is in end state. - PDEBUG - ("Single call has been complited.\n"); - - // Set correct value for single_read(); - instance->single_value = - instance->single_value_in_fifo; - - // Set status as 'ao_status_single_end' - instance->status = ao_status_single_end; - - spin_lock(instance->preload_reg_lock); - if ((single_mask) && (*instance->preload_flags & (ME6000_AO_SYNC_HOLD << instance->ao_idx))) { // This is one of synchronous start channels. Set all as triggered. - *instance->triggering_flags = - 0x00000000; - } else { - //Set this channel as triggered (none active). - *instance->triggering_flags &= - ~(0x1 << instance->ao_idx); - } - spin_unlock(instance->preload_reg_lock); - - // Signal the end. - signaling = 1; - // Wait for stop ISM. - reschedule = 1; - - break; - } - } - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! - spin_lock_irqsave(&instance->subdevice_lock, - cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME6000_AO_CTRL_BIT_STOP | - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; - ctrl &= - ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | - ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); - ctrl &= - ~(ME6000_AO_CTRL_BIT_EX_TRIG_EDGE | - ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH); - //Disabling FIFO - ctrl &= ~ME6000_AO_CTRL_BIT_ENABLE_FIFO; - - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - - instance->reg_base, ctrl); - spin_unlock_irqrestore(&instance-> - subdevice_lock, - cpu_flags); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - spin_lock(instance->preload_reg_lock); - //Remove from synchronous start. Block triggering from this output. - synch = inl(instance->preload_reg); - synch &= - ~((ME6000_AO_SYNC_HOLD | - ME6000_AO_SYNC_EXT_TRIG) << instance-> - ao_idx); - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - set to single safe mode - synch |= - ME6000_AO_SYNC_HOLD << instance-> - ao_idx; - } - outl(synch, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch); - //Set this channel as triggered (none active). - *instance->triggering_flags &= - ~(0x1 << instance->ao_idx); - spin_unlock(instance->preload_reg_lock); - - // Set correct value for single_read(); - instance->single_value_in_fifo = - instance->single_value; - - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - } - } else { // No extra registers. -/* - if (!(status & single_mask)) - {// State machine is not working. - PDEBUG("Single call has been complited.\n"); - - // Set correct value for single_read(); - instance->single_value = instance->single_value_in_fifo; - - // Set status as 'ao_status_single_end' - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - // Wait for stop ISM. - reschedule = 1; - - break; - } -*/ - if (!single_mask) { // Was triggered. - PDEBUG("Single call has been complited.\n"); - - // Set correct value for single_read(); - instance->single_value = - instance->single_value_in_fifo; - - // Set status as 'ao_status_single_end' - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - - break; - } - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - - spin_lock(instance->preload_reg_lock); - //Remove from synchronous start. Block triggering from this output. - synch = inl(instance->preload_reg); - synch &= - ~(ME6000_AO_SYNC_EXT_TRIG << instance-> - ao_idx); - synch |= - ME6000_AO_SYNC_HOLD << instance->ao_idx; - - outl(synch, instance->preload_reg); - PDEBUG_REG - ("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch); - //Set this channel as triggered (none active). - *instance->triggering_flags &= - ~(0x1 << instance->ao_idx); - spin_unlock(instance->preload_reg_lock); - - // Restore old settings. - PDEBUG("Write old value back to register.\n"); - outl(instance->single_value, - instance->single_reg); - PDEBUG_REG - ("single_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->single_reg - instance->reg_base, - instance->single_value); - - // Set correct value for single_read(); - instance->single_value_in_fifo = - instance->single_value; - - instance->status = ao_status_single_end; - - // Signal the end. - signaling = 1; - } - } - - // Wait for stop. - reschedule = 1; - break; - - case ao_status_stream_end: - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - case ao_status_single_end: - if (instance->fifo) { // Extra registers. - if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working but the status is set to end. Force stop. - - // Wait for stop. - reschedule = 1; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - // Stop all actions. No conditions! Block interrupts and trigger. Leave FIFO untouched! - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP | - ME6000_AO_CTRL_BIT_STOP; - ctrl &= - ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | - ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - } else { // No extra registers. -/* - if (status & single_mask) - {// State machine is working but the status is set to end. Force stop. - - // Wait for stop. - reschedule = 1; - } -*/ - } - break; - - // Stream modes - case ao_status_stream_run_wait: - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (status & ME6000_AO_STATUS_BIT_FSM) { // State machine is working. Waiting for start finish. - instance->status = ao_status_stream_run; - - // Signal end of this step - signaling = 1; - } else { // State machine is not working. - if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty. Procedure has started and finish already! - instance->status = ao_status_stream_end; - - // Signal the end. - signaling = 1; - // Wait for stop. - reschedule = 1; - break; - } - } - - // Check timeout. - if ((instance->timeout.delay) && ((jiffies - instance->timeout.start_time) >= instance->timeout.delay)) { // Timeout - PDEBUG("Timeout reached.\n"); - // Stop all actions. No conditions! Block interrupts. Leave FIFO untouched! - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - ctrl = inl(instance->ctrl_reg); - ctrl |= - ME6000_AO_CTRL_BIT_STOP | - ME6000_AO_CTRL_BIT_IMMEDIATE_STOP; - ctrl &= - ~(ME6000_AO_CTRL_BIT_ENABLE_IRQ | - ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG); - outl(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, - ctrl); - spin_unlock_irqrestore(&instance->subdevice_lock, - cpu_flags); - - //Reset interrupt latch - inl(instance->irq_reset_reg); - - spin_lock(instance->preload_reg_lock); - //Remove from synchronous start. Block triggering from this output. - synch = inl(instance->preload_reg); - synch &= - ~((ME6000_AO_SYNC_HOLD | ME6000_AO_SYNC_EXT_TRIG) << - instance->ao_idx); - outl(synch, instance->preload_reg); - PDEBUG_REG("preload_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->preload_reg - instance->reg_base, - synch); - spin_unlock(instance->preload_reg_lock); - - instance->status = ao_status_stream_end; - - // Signal the end. - signaling = 1; - } - // Wait for stop. - reschedule = 1; - break; - - case ao_status_stream_run: - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. This is an error. - // BROKEN PIPE! - if (!(status & ME6000_AO_STATUS_BIT_EF)) { // FIFO is empty. - if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. - if (instance->stop_data_count && (instance->stop_data_count <= instance->data_count)) { //Finishing work. Requed data shown. - PDEBUG - ("ISM stoped. No data in FIFO. Buffer is not empty.\n"); - instance->status = - ao_status_stream_end; - } else { - PERROR - ("Output stream has been broken. ISM stoped. No data in FIFO. Buffer is not empty.\n"); - instance->status = - ao_status_stream_buffer_error; - } - } else { // Software buffer is empty. - PDEBUG - ("ISM stoped. No data in FIFO. Buffer is empty.\n"); - instance->status = ao_status_stream_end; - } - } else { // There are still datas in FIFO. - if (me_circ_buf_values(&instance->circ_buf)) { // Software buffer is not empty. - PERROR - ("Output stream has been broken. ISM stoped but some data in FIFO and buffer.\n"); - } else { // Software buffer is empty. - PERROR - ("Output stream has been broken. ISM stoped but some data in FIFO. Buffer is empty.\n"); - } - instance->status = ao_status_stream_fifo_error; - - } - - // Signal the failure. - signaling = 1; - break; - } - // Wait for stop. - reschedule = 1; - break; - - case ao_status_stream_end_wait: - if (!(instance->fifo & ME6000_AO_HAS_FIFO)) { // No FIFO - PERROR_CRITICAL - ("Streaming on single device! This feature is not implemented in this version!\n"); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - } - - if (!(status & ME6000_AO_STATUS_BIT_FSM)) { // State machine is not working. Waiting for stop finish. - instance->status = ao_status_stream_end; - signaling = 1; - } - // State machine is working. - reschedule = 1; - break; - - default: - PERROR_CRITICAL("Status is in wrong state (%d)!\n", - instance->status); - instance->status = ao_status_stream_error; - // Signal the end. - signaling = 1; - break; - - } - - if (signaling) { //Signal it. - wake_up_interruptible_all(&instance->wait_queue); - } - - if (instance->ao_control_task_flag && reschedule) { // Reschedule task - queue_delayed_work(instance->me6000_workqueue, - &instance->ao_control_task, 1); - } else { - PINFO("<%s> Ending control task.\n", __func__); - } - -} - -static int me6000_ao_query_range_by_min_max(me_subdevice_t *subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((*max - *min) < 0) { - PERROR("Invalid minimum and maximum values specified.\n"); - return ME_ERRNO_INVALID_MIN_MAX; - } - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - if ((*max <= (instance->max + 1000)) && (*min >= instance->min)) { - *min = instance->min; - *max = instance->max; - *maxdata = ME6000_AO_MAX_DATA; - *range = 0; - } else { - PERROR("No matching range available.\n"); - return ME_ERRNO_NO_RANGE; - } - } else { - PERROR("Invalid physical unit specified.\n"); - return ME_ERRNO_INVALID_UNIT; - } - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_number_ranges(me_subdevice_t *subdevice, - int unit, int *count) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if ((unit == ME_UNIT_VOLT) || (unit == ME_UNIT_ANY)) { - *count = 1; - } else { - *count = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_range_info(me_subdevice_t *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (range == 0) { - *unit = ME_UNIT_VOLT; - *min = instance->min; - *max = instance->max; - *maxdata = ME6000_AO_MAX_DATA; - } else { - PERROR("Invalid range number specified.\n"); - return ME_ERRNO_INVALID_RANGE; - } - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_timer(me_subdevice_t *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (instance->fifo) { //Streaming device. - *base_frequency = ME6000_AO_BASE_FREQUENCY; - if (timer == ME_TIMER_ACQ_START) { - *min_ticks = ME6000_AO_MIN_ACQ_TICKS; - *max_ticks = ME6000_AO_MAX_ACQ_TICKS; - } else if (timer == ME_TIMER_CONV_START) { - *min_ticks = ME6000_AO_MIN_CHAN_TICKS; - *max_ticks = ME6000_AO_MAX_CHAN_TICKS; - } - } else { //Not streaming device! - *base_frequency = 0; - *min_ticks = 0; - *max_ticks = 0; - } - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - me6000_ao_subdevice_t *instance; - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *number = 1; - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - me6000_ao_subdevice_t *instance; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *type = ME_TYPE_AO; - *subtype = - (instance-> - fifo & ME6000_AO_HAS_FIFO) ? ME_SUBTYPE_STREAMING : - ME_SUBTYPE_SINGLE; - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - me6000_ao_subdevice_t *instance; - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - *caps = - ME_CAPS_AO_TRIG_SYNCHRONOUS | ((instance->fifo) ? ME_CAPS_AO_FIFO : - ME_CAPS_NONE); - - return ME_ERRNO_SUCCESS; -} - -static int me6000_ao_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count) -{ - me6000_ao_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - instance = (me6000_ao_subdevice_t *) subdevice; - - PDEBUG("executed. idx=%d\n", instance->ao_idx); - - if (count != 1) { - PERROR("Invalid capability argument count.\n"); - return ME_ERRNO_INVALID_CAP_ARG_COUNT; - } - - switch (cap) { - case ME_CAP_AI_FIFO_SIZE: - args[0] = (instance->fifo) ? ME6000_AO_FIFO_COUNT : 0; - break; - - case ME_CAP_AI_BUFFER_SIZE: - args[0] = - (instance->circ_buf.buf) ? ME6000_AO_CIRC_BUF_COUNT : 0; - break; - - default: - PERROR("Invalid capability.\n"); - err = ME_ERRNO_INVALID_CAP; - args[0] = 0; - } - - return err; -} --- a/drivers/staging/meilhaus/me6000_ao.h +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @file me6000_ao.h - * - * @brief Meilhaus ME-6000 analog output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME6000_AO_H_ -#define _ME6000_AO_H_ - -#include "mesubdevice.h" -#include "mecirc_buf.h" -#include "meioctl.h" - -#ifdef __KERNEL__ - -#define ME6000_AO_MAX_SUBDEVICES 16 -#define ME6000_AO_FIFO_COUNT 8192 - -#define ME6000_AO_BASE_FREQUENCY 33000000L - -#define ME6000_AO_MIN_ACQ_TICKS 0LL -#define ME6000_AO_MAX_ACQ_TICKS 0LL - -#define ME6000_AO_MIN_CHAN_TICKS 66LL -#define ME6000_AO_MAX_CHAN_TICKS 0xFFFFFFFFLL - -#define ME6000_AO_MIN_RANGE -10000000 -#define ME6000_AO_MAX_RANGE 9999694 - -#define ME6000_AO_MIN_RANGE_HIGH 0 -#define ME6000_AO_MAX_RANGE_HIGH 49999237 - -#define ME6000_AO_MAX_DATA 0xFFFF - -#ifdef ME_SYNAPSE -# define ME6000_AO_CIRC_BUF_SIZE_ORDER 8 // 2^n PAGES =>> Maximum value of 1MB for Synapse -#else -# define ME6000_AO_CIRC_BUF_SIZE_ORDER 5 // 2^n PAGES =>> 128KB -#endif -#define ME6000_AO_CIRC_BUF_SIZE PAGE_SIZE< bit 0 in ME6000_AO_SINGLE_STATUS_REG. - -#define ME6000_AO_04_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_04_SINGLE_REG 0x74 // _/W - -#define ME6000_AO_05_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_05_SINGLE_REG 0x78 // _/W - -#define ME6000_AO_06_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_06_SINGLE_REG 0x7C // _/W - -#define ME6000_AO_07_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_07_SINGLE_REG 0x80 // _/W - -#define ME6000_AO_08_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_08_SINGLE_REG 0x84 // _/W - -#define ME6000_AO_09_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_09_SINGLE_REG 0x88 // _/W - -#define ME6000_AO_10_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_10_SINGLE_REG 0x8C // _/W - -#define ME6000_AO_11_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_11_SINGLE_REG 0x90 // _/W - -#define ME6000_AO_12_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_12_SINGLE_REG 0x94 // _/W - -#define ME6000_AO_13_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_13_SINGLE_REG 0x98 // _/W - -#define ME6000_AO_14_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_14_SINGLE_REG 0x9C // _/W - -#define ME6000_AO_15_STATUS_REG ME6000_AO_SINGLE_STATUS_REG -#define ME6000_AO_15_SINGLE_REG 0xA0 // _/W - -//ME6000_AO_CTRL_REG -#define ME6000_AO_MODE_SINGLE 0x00 -#define ME6000_AO_MODE_WRAPAROUND 0x01 -#define ME6000_AO_MODE_CONTINUOUS 0x02 -#define ME6000_AO_CTRL_MODE_MASK (ME6000_AO_MODE_WRAPAROUND | ME6000_AO_MODE_CONTINUOUS) - -#define ME6000_AO_CTRL_BIT_MODE_WRAPAROUND 0x001 -#define ME6000_AO_CTRL_BIT_MODE_CONTINUOUS 0x002 -#define ME6000_AO_CTRL_BIT_STOP 0x004 -#define ME6000_AO_CTRL_BIT_ENABLE_FIFO 0x008 -#define ME6000_AO_CTRL_BIT_ENABLE_EX_TRIG 0x010 -#define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE 0x020 -#define ME6000_AO_CTRL_BIT_ENABLE_IRQ 0x040 -#define ME6000_AO_CTRL_BIT_IMMEDIATE_STOP 0x080 -#define ME6000_AO_CTRL_BIT_EX_TRIG_EDGE_BOTH 0x800 - -//ME6000_AO_STATUS_REG -#define ME6000_AO_STATUS_BIT_FSM 0x01 -#define ME6000_AO_STATUS_BIT_FF 0x02 -#define ME6000_AO_STATUS_BIT_HF 0x04 -#define ME6000_AO_STATUS_BIT_EF 0x08 - -#define ME6000_AO_PRELOAD_REG 0xA8 // R/W ///ME6000_AO_SYNC_REG <==> ME6000_AO_PRELOAD_REG -/* -#define ME6000_AO_SYNC_HOLD_0 0x00000001 -#define ME6000_AO_SYNC_HOLD_1 0x00000002 -#define ME6000_AO_SYNC_HOLD_2 0x00000004 -#define ME6000_AO_SYNC_HOLD_3 0x00000008 -#define ME6000_AO_SYNC_HOLD_4 0x00000010 -#define ME6000_AO_SYNC_HOLD_5 0x00000020 -#define ME6000_AO_SYNC_HOLD_6 0x00000040 -#define ME6000_AO_SYNC_HOLD_7 0x00000080 -#define ME6000_AO_SYNC_HOLD_8 0x00000100 -#define ME6000_AO_SYNC_HOLD_9 0x00000200 -#define ME6000_AO_SYNC_HOLD_10 0x00000400 -#define ME6000_AO_SYNC_HOLD_11 0x00000800 -#define ME6000_AO_SYNC_HOLD_12 0x00001000 -#define ME6000_AO_SYNC_HOLD_13 0x00002000 -#define ME6000_AO_SYNC_HOLD_14 0x00004000 -#define ME6000_AO_SYNC_HOLD_15 0x00008000 -*/ -#define ME6000_AO_SYNC_HOLD 0x00000001 -/* -#define ME6000_AO_SYNC_EXT_TRIG_0 0x00010000 -#define ME6000_AO_SYNC_EXT_TRIG_1 0x00020000 -#define ME6000_AO_SYNC_EXT_TRIG_2 0x00040000 -#define ME6000_AO_SYNC_EXT_TRIG_3 0x00080000 -#define ME6000_AO_SYNC_EXT_TRIG_4 0x00100000 -#define ME6000_AO_SYNC_EXT_TRIG_5 0x00200000 -#define ME6000_AO_SYNC_EXT_TRIG_6 0x00400000 -#define ME6000_AO_SYNC_EXT_TRIG_7 0x00800000 -#define ME6000_AO_SYNC_EXT_TRIG_8 0x01000000 -#define ME6000_AO_SYNC_EXT_TRIG_9 0x02000000 -#define ME6000_AO_SYNC_EXT_TRIG_10 0x04000000 -#define ME6000_AO_SYNC_EXT_TRIG_11 0x08000000 -#define ME6000_AO_SYNC_EXT_TRIG_12 0x10000000 -#define ME6000_AO_SYNC_EXT_TRIG_13 0x20000000 -#define ME6000_AO_SYNC_EXT_TRIG_14 0x40000000 -#define ME6000_AO_SYNC_EXT_TRIG_15 0x80000000 -*/ -#define ME6000_AO_SYNC_EXT_TRIG 0x00010000 - -#define ME6000_AO_EXT_TRIG 0x80000000 - -// AO-IRQ -#define ME6000_AO_IRQ_STATUS_REG 0x60 // R/_ -#define ME6000_AO_00_IRQ_RESET_REG 0x64 // R/_ -#define ME6000_AO_01_IRQ_RESET_REG 0x68 // R/_ -#define ME6000_AO_02_IRQ_RESET_REG 0x6C // R/_ -#define ME6000_AO_03_IRQ_RESET_REG 0x70 // R/_ - -#define ME6000_IRQ_STATUS_BIT_0 0x01 -#define ME6000_IRQ_STATUS_BIT_1 0x02 -#define ME6000_IRQ_STATUS_BIT_2 0x04 -#define ME6000_IRQ_STATUS_BIT_3 0x08 - -#define ME6000_IRQ_STATUS_BIT_AO_HF ME6000_IRQ_STATUS_BIT_0 - -//DUMY register -#define ME6000_AO_DUMY 0xFC -#endif -#endif --- a/drivers/staging/meilhaus/me6000_device.c +++ /dev/null @@ -1,209 +0,0 @@ -/** - * @file me6000_device.c - * - * @brief Device class template implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "mefirmware.h" - -#include "mesubdevice.h" -#include "medebug.h" -#include "medevice.h" -#include "me6000_reg.h" -#include "me6000_device.h" -#include "meplx_reg.h" -#include "me6000_dio.h" -#include "me6000_ao.h" - -/** - * @brief Global variable. - * This is working queue for runing a separate atask that will be responsible for work status (start, stop, timeouts). - */ -static struct workqueue_struct *me6000_workqueue; - -me_device_t *me6000_pci_constructor(struct pci_dev *pci_device) -{ - me6000_device_t *me6000_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - int high_range = 0; - int fifo; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me6000_device = kmalloc(sizeof(me6000_device_t), GFP_KERNEL); - - if (!me6000_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me6000_device, 0, sizeof(me6000_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me6000_device, pci_device); - - if (err) { - kfree(me6000_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Download the xilinx firmware */ - err = me_xilinx_download(me6000_device->base.info.pci.reg_bases[1], - me6000_device->base.info.pci.reg_bases[2], - &pci_device->dev, "me6000.bin"); - - if (err) { - me_device_deinit((me_device_t *) me6000_device); - kfree(me6000_device); - PERROR("Can't download firmware.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - me6000_versions_get_device_index(me6000_device->base.info.pci. - device_id); - - // Initialize spin lock . - spin_lock_init(&me6000_device->preload_reg_lock); - spin_lock_init(&me6000_device->dio_ctrl_reg_lock); - - /* Create digital input/output instances. */ - for (i = 0; i < me6000_versions[version_idx].dio_subdevices; i++) { - subdevice = - (me_subdevice_t *) me6000_dio_constructor(me6000_device-> - base.info.pci. - reg_bases[3], i, - &me6000_device-> - dio_ctrl_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me6000_device); - kfree(me6000_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me6000_device->base.slist, - subdevice); - } - - /* Create analog output instances. */ - for (i = 0; i < me6000_versions[version_idx].ao_subdevices; i++) { - high_range = ((i == 8) - && - ((me6000_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME6359) - || (me6000_device->base.info.pci.device_id == - PCI_DEVICE_ID_MEILHAUS_ME6259) - ) - )? 1 : 0; - - fifo = - (i < - me6000_versions[version_idx]. - ao_fifo) ? ME6000_AO_HAS_FIFO : 0x0; - fifo |= (i < 4) ? ME6000_AO_EXTRA_HARDWARE : 0x0; - - subdevice = - (me_subdevice_t *) me6000_ao_constructor(me6000_device-> - base.info.pci. - reg_bases[2], - &me6000_device-> - preload_reg_lock, - &me6000_device-> - preload_flags, - &me6000_device-> - triggering_flags, - i, fifo, - me6000_device-> - base.irq, - high_range, - me6000_workqueue); - - if (!subdevice) { - me_device_deinit((me_device_t *) me6000_device); - kfree(me6000_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me6000_device->base.slist, - subdevice); - } - - return (me_device_t *) me6000_device; -} -EXPORT_SYMBOL(me6000_pci_constructor); - -// Init and exit of module. - -static int __init me6000_init(void) -{ - PDEBUG("executed.\n"); - - me6000_workqueue = create_singlethread_workqueue("me6000"); - return 0; -} - -static void __exit me6000_exit(void) -{ - PDEBUG("executed.\n"); - - flush_workqueue(me6000_workqueue); - destroy_workqueue(me6000_workqueue); -} - -module_init(me6000_init); -module_exit(me6000_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Device Driver Module for ME-6000 Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-6000 Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me6000_device.h +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file me6000_device.h - * - * @brief ME-6000 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME6000_DEVICE_H -#define _ME6000_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-6000 device capabilities. - */ -typedef struct me6000_version { - uint16_t device_id; - unsigned int dio_subdevices; - unsigned int ao_subdevices; - unsigned int ao_fifo; //How many devices have FIFO -} me6000_version_t; - -/** - * @brief ME-6000 device capabilities. - */ -static me6000_version_t me6000_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME6004, 0, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6008, 0, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME600F, 0, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6014, 0, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6018, 0, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME601F, 0, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6034, 0, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6038, 0, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME603F, 0, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6104, 0, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6108, 0, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME610F, 0, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6114, 0, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6118, 0, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME611F, 0, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6134, 0, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6138, 0, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME613F, 0, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6044, 2, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6048, 2, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME604F, 2, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6054, 2, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6058, 2, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME605F, 2, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6074, 2, 4, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME6078, 2, 8, 0}, - {PCI_DEVICE_ID_MEILHAUS_ME607F, 2, 16, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6144, 2, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6148, 2, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME614F, 2, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6154, 2, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6158, 2, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME615F, 2, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6174, 2, 4, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME6178, 2, 8, 4}, - {PCI_DEVICE_ID_MEILHAUS_ME617F, 2, 16, 4}, - - {PCI_DEVICE_ID_MEILHAUS_ME6259, 2, 9, 0}, - - {PCI_DEVICE_ID_MEILHAUS_ME6359, 2, 9, 4}, - - {0}, -}; - -#define ME6000_DEVICE_VERSIONS (ARRAY_SIZE(me6000_versions) - 1) /**< Returns the number of entries in #me6000_versions. */ - -/** - * @brief Returns the index of the device entry in #me6000_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me6000_versions. - */ -static inline unsigned int me6000_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME6000_DEVICE_VERSIONS; i++) - if (me6000_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-6000 device class structure. - */ -typedef struct me6000_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t preload_reg_lock; /**< Guards the preload register. */ - uint32_t preload_flags; - uint32_t triggering_flags; - - spinlock_t dio_ctrl_reg_lock; -} me6000_device_t; - -/** - * @brief The ME-6000 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-6000 device instance. \n - * NULL on error. - */ -me_device_t *me6000_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me6000_dio.c +++ /dev/null @@ -1,415 +0,0 @@ -/** - * @file me6000_dio.c - * - * @brief ME-6000 digital input/output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me6000_dio_reg.h" -#include "me6000_dio.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me6000_dio_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me6000_dio_subdevice_t *instance; - uint8_t mode; - - PDEBUG("executed.\n"); - - instance = (me6000_dio_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - mode &= ~(0x3 << (instance->dio_idx * 2)); - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - - outb(0x00, instance->port_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, 0x00); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me6000_dio_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me6000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - int size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - - PDEBUG("executed.\n"); - - instance = (me6000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - mode &= - ~((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - mode &= - ~((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - mode |= - ME6000_DIO_CTRL_BIT_MODE_0 << (instance-> - dio_idx * 2); - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_dio_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me6000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - - PDEBUG("executed.\n"); - - instance = (me6000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - if ((mode == - (ME6000_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = - inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - if ((mode == - (ME6000_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = inb(instance->port_reg) & 0x00FF; - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_dio_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me6000_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - uint8_t byte; - - PDEBUG("executed.\n"); - - instance = (me6000_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME6000_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - byte = inb(instance->port_reg) & 0x00FF; - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outb(byte, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME6000_DIO_CTRL_BIT_MODE_0 | - ME6000_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME6000_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - outb(value, instance->port_reg); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me6000_dio_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me6000_dio_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me6000_dio_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_DIR_BYTE; - return ME_ERRNO_SUCCESS; -} - -me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t *ctrl_reg_lock) -{ - me6000_dio_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me6000_dio_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me6000_dio_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - - /* Set the subdevice ports */ - subdevice->ctrl_reg = reg_base + ME6000_DIO_CTRL_REG; - switch (dio_idx) { - case 0: - subdevice->port_reg = reg_base + ME6000_DIO_PORT_0_REG; - break; - case 1: - subdevice->port_reg = reg_base + ME6000_DIO_PORT_1_REG; - break; - default: - err = ME_ERRNO_INVALID_SUBDEVICE; - } - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save digital i/o index */ - subdevice->dio_idx = dio_idx; - -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me6000_dio_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me6000_dio_io_single_config; - subdevice->base.me_subdevice_io_single_read = me6000_dio_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me6000_dio_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me6000_dio_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me6000_dio_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me6000_dio_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me6000_dio.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file me6000_dio.h - * - * @brief ME-6000 digital input/output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME6000_DIO_H_ -#define _ME6000_DIO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me6000_dio_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - unsigned int dio_idx; /**< The index of the digital i/o on the device. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me6000_dio_subdevice_t; - -/** - * @brief The constructor to generate a ME-6000 digital input/ouput subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param dio_idx The index of the digital i/o port on the device. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me6000_dio_subdevice_t *me6000_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me6000_dio_reg.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file me6000_dio_reg.h - * - * @brief ME-6000 digital input/output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME6000_DIO_REG_H_ -#define _ME6000_DIO_REG_H_ - -#ifdef __KERNEL__ - -#define ME6000_DIO_CTRL_REG 0x00 // R/W -#define ME6000_DIO_PORT_0_REG 0x01 // R/W -#define ME6000_DIO_PORT_1_REG 0x02 // R/W -#define ME6000_DIO_PORT_REG ME6000_DIO_PORT_0_REG // R/W - -#define ME6000_DIO_CTRL_BIT_MODE_0 0x01 -#define ME6000_DIO_CTRL_BIT_MODE_1 0x02 -#define ME6000_DIO_CTRL_BIT_MODE_2 0x04 -#define ME6000_DIO_CTRL_BIT_MODE_3 0x08 - -#endif -#endif --- a/drivers/staging/meilhaus/me6000_reg.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file me6000_reg.h - * - * @brief ME-6000 device register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME6000_REG_H_ -#define _ME6000_REG_H_ - -#ifdef __KERNEL__ - -#define ME6000_INIT_XILINX_REG 0xAC // R/- - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_device.c +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @file me8100_device.c - * - * @brief ME-8100 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "me8100_device.h" -#include "mesubdevice.h" -#include "me8100_di.h" -#include "me8100_do.h" -#include "me8254.h" - -me_device_t *me8100_pci_constructor(struct pci_dev *pci_device) -{ - me8100_device_t *me8100_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me8100_device = kmalloc(sizeof(me8100_device_t), GFP_KERNEL); - - if (!me8100_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me8100_device, 0, sizeof(me8100_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me8100_device, pci_device); - - if (err) { - kfree(me8100_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - me8100_versions_get_device_index(me8100_device->base.info.pci. - device_id); - - // Initialize spin lock . - spin_lock_init(&me8100_device->dio_ctrl_reg_lock); - spin_lock_init(&me8100_device->ctr_ctrl_reg_lock); - spin_lock_init(&me8100_device->clk_src_reg_lock); - - // Create subdevice instances. - - for (i = 0; i < me8100_versions[version_idx].di_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8100_di_constructor(me8100_device-> - base.info.pci. - reg_bases[2], - me8100_device-> - base.info.pci. - reg_bases[1], i, - me8100_device-> - base.irq, - &me8100_device-> - dio_ctrl_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8100_device); - kfree(me8100_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8100_device->base.slist, - subdevice); - } - - for (i = 0; i < me8100_versions[version_idx].do_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8100_do_constructor(me8100_device-> - base.info.pci. - reg_bases[2], i, - &me8100_device-> - dio_ctrl_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8100_device); - kfree(me8100_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8100_device->base.slist, - subdevice); - } - - for (i = 0; i < me8100_versions[version_idx].ctr_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8254_constructor(me8100_device->base. - info.pci.device_id, - me8100_device->base. - info.pci.reg_bases[2], - 0, i, - &me8100_device-> - ctr_ctrl_reg_lock, - &me8100_device-> - clk_src_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8100_device); - kfree(me8100_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8100_device->base.slist, - subdevice); - } - - return (me_device_t *) me8100_device; -} -EXPORT_SYMBOL(me8100_pci_constructor); - -// Init and exit of module. - -static int __init me8100_init(void) -{ - PDEBUG("executed.\n."); - return ME_ERRNO_SUCCESS; -} - -static void __exit me8100_exit(void) -{ - PDEBUG("executed.\n."); -} - -module_init(me8100_init); - -module_exit(me8100_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR("Guenter Gebhardt "); -MODULE_DESCRIPTION("Device Driver Module for Template Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me8100_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file me8100_device.h - * - * @brief ME-8100 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_DEVICE_H -#define _ME8100_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-8100 device capabilities. - */ -typedef struct me8100_version { - uint16_t device_id; - unsigned int di_subdevices; - unsigned int do_subdevices; - unsigned int ctr_subdevices; -} me8100_version_t; - -/** - * @brief Device capabilities. - */ -static me8100_version_t me8100_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME8100_A, 1, 1, 3}, - {PCI_DEVICE_ID_MEILHAUS_ME8100_B, 2, 2, 3}, - {0}, -}; - -#define ME8100_DEVICE_VERSIONS (ARRAY_SIZE(me8100_versions) - 1) /**< Returns the number of entries in #me8100_versions. */ - -/** - * @brief Returns the index of the device entry in #me8100_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me8100_versions. - */ -static inline unsigned int me8100_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME8100_DEVICE_VERSIONS; i++) - if (me8100_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-8100 device class structure. - */ -typedef struct me8100_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t dio_ctrl_reg_lock; - spinlock_t ctr_ctrl_reg_lock; - spinlock_t clk_src_reg_lock; -} me8100_device_t; - -/** - * @brief The ME-8100 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-8100 device instance. \n - * NULL on error. - */ -me_device_t *me8100_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_di.c +++ /dev/null @@ -1,684 +0,0 @@ -/** - * @file me8100_di.c - * - * @brief ME-8100 digital input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meerror.h" - -#include "meids.h" -#include "medebug.h" -#include "meplx_reg.h" -#include "me8100_reg.h" -#include "me8100_di_reg.h" -#include "me8100_di.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me8100_di_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8100_di_subdevice_t *instance; - unsigned short ctrl; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->ctrl_reg_lock); - ctrl = inw(instance->ctrl_reg); - ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0); - outw(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->ctrl_reg_lock); - - outw(0, instance->mask_reg); - PDEBUG_REG("mask_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->mask_reg - instance->reg_base, 0); - outw(0, instance->pattern_reg); - PDEBUG_REG("pattern_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->pattern_reg - instance->reg_base, 0); - instance->rised = -1; - instance->irq_count = 0; - instance->filtering_flag = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - outl(PLX_INTCSR_LOCAL_INT1_EN | - PLX_INTCSR_LOCAL_INT1_POL | - PLX_INTCSR_LOCAL_INT2_EN | - PLX_INTCSR_LOCAL_INT2_POL | - PLX_INTCSR_PCI_INT_EN, instance->irq_status_reg); - PDEBUG_REG("plx:irq_status_reg outl(0x%lX)=0x%x\n", - instance->irq_status_reg, - PLX_INTCSR_LOCAL_INT1_EN | PLX_INTCSR_LOCAL_INT1_POL | - PLX_INTCSR_LOCAL_INT2_EN | PLX_INTCSR_LOCAL_INT2_POL | - PLX_INTCSR_PCI_INT_EN); - - wake_up_interruptible_all(&instance->wait_queue); - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8100_di_io_irq_start(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me8100_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint16_t ctrl; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - if (flags & - ~(ME_IO_IRQ_START_PATTERN_FILTERING | - ME_IO_IRQ_START_DIO_WORD)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (irq_edge != ME_IRQ_EDGE_NOT_USED) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - if (flags & - ~(ME_IO_IRQ_START_EXTENDED_STATUS | - ME_IO_IRQ_START_DIO_WORD)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (irq_edge != ME_IRQ_EDGE_ANY) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - - if (!(irq_arg & 0xFFFF)) { - PERROR("No mask specified.\n"); - return ME_ERRNO_INVALID_IRQ_ARG; - } - } else { - PERROR("Invalid irq source specified.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - outw(irq_arg, instance->pattern_reg); - instance->compare_value = irq_arg; - instance->filtering_flag = - (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0; - } - if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - outw(irq_arg, instance->mask_reg); - } - - spin_lock(instance->ctrl_reg_lock); - ctrl = inw(instance->ctrl_reg); - ctrl |= ME8100_DIO_CTRL_BIT_INTB_0; - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - ctrl &= ~ME8100_DIO_CTRL_BIT_INTB_1; - } - - if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - ctrl |= ME8100_DIO_CTRL_BIT_INTB_1; - } - outw(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->ctrl_reg_lock); - - instance->rised = 0; - instance->status_value = 0; - instance->status_value_edges = 0; - instance->line_value = inw(instance->port_reg); - instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_di_io_irq_wait(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me8100_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - unsigned long cpu_flags; - int count; - - PDEBUG("executed.\n"); - PDEVELOP("PID: %d.\n", current->pid); - - instance = (me8100_di_subdevice_t *) subdevice; - - if (flags & - ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - count = instance->irq_count; - - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - ((count != - instance-> - irq_count) - || (instance-> - rised < 0)), - t); -// t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t); - if (t == 0) { - PERROR("Wait on interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - ((count != instance->irq_count) - || (instance->rised < 0))); -// wait_event_interruptible(instance->wait_queue, (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - *irq_count = instance->irq_count; - if (!err) { - if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) { - *value = instance->status_value; - } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) { - *value = instance->status_value_edges; - } else { // Use default - if (!instance->status_flag) { - *value = instance->status_value; - } else { - *value = instance->status_value_edges; - } - } - instance->rised = 0; -/* - instance->status_value = 0; - instance->status_value_edges = 0; -*/ - } else { - *value = 0; - } - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_di_io_irq_stop(me_subdevice_t *subdevice, - struct file *filep, int channel, int flags) -{ - me8100_di_subdevice_t *instance; - uint16_t ctrl; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->ctrl_reg_lock); - ctrl = inw(instance->ctrl_reg); - ctrl &= ~(ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0); - outw(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->ctrl_reg_lock); - instance->rised = -1; - instance->status_value = 0; - instance->status_value_edges = 0; - instance->filtering_flag = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8100_di_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8100_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_WORD: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_di_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8100_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - - switch (flags) { - - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 16)) { - *value = inw(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inw(instance->port_reg) & 0xFF; - } else if (channel == 1) { - *value = (inw(instance->port_reg) >> 8) & 0xFF; - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_WORD: - if (channel == 0) { - *value = inw(instance->port_reg); - } else { - PERROR("Invalid word number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_di_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 16; - return ME_ERRNO_SUCCESS; -} - -static int me8100_di_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8100_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_BIT_PATTERN_IRQ | ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY; - return ME_ERRNO_SUCCESS; -} - -static void me8100_di_destructor(struct me_subdevice *subdevice) -{ - me8100_di_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) subdevice; - - free_irq(instance->irq, (void *)instance); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static irqreturn_t me8100_isr(int irq, void *dev_id) -{ - me8100_di_subdevice_t *instance; - uint32_t icsr; - - uint16_t irq_status; - uint16_t line_value = 0; - - uint32_t status_val = 0; - - PDEBUG("executed.\n"); - - instance = (me8100_di_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - icsr = inl(instance->irq_status_reg); - if (instance->di_idx == 0) { - - if ((icsr & - (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN | - PLX_INTCSR_LOCAL_INT1_EN)) != - (PLX_INTCSR_LOCAL_INT1_STATE | PLX_INTCSR_PCI_INT_EN | - PLX_INTCSR_LOCAL_INT1_EN)) { - PINFO - ("%ld Shared interrupt. %s(): idx=0 plx:irq_status_reg=0x%04X\n", - jiffies, __func__, icsr); - return IRQ_NONE; - } - } else if (instance->di_idx == 1) { - if ((icsr & - (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN | - PLX_INTCSR_LOCAL_INT2_EN)) != - (PLX_INTCSR_LOCAL_INT2_STATE | PLX_INTCSR_PCI_INT_EN | - PLX_INTCSR_LOCAL_INT2_EN)) { - PINFO - ("%ld Shared interrupt. %s(): idx=1 plx:irq_status_reg=0x%04X\n", - jiffies, __func__, icsr); - return IRQ_NONE; - } - } else { - PERROR("%s():Wrong interrupt idx=%d csr=0x%X.\n", __func__, - instance->di_idx, icsr); - return IRQ_NONE; - } - - PDEBUG("me8100_isr():Interrupt from idx=%d occured.\n", - instance->di_idx); - spin_lock(&instance->subdevice_lock); - inw(instance->irq_reset_reg); - line_value = inw(instance->port_reg); - - irq_status = instance->line_value ^ line_value; - - // Make extended information. - status_val |= (0x00FF & (~(uint16_t) instance->line_value & line_value)) << 16; //Raise - status_val |= (0x00FF & ((uint16_t) instance->line_value & ~line_value)); //Fall - - instance->line_value = line_value; - - if (instance->rised == 0) { - instance->status_value = irq_status; - instance->status_value_edges = status_val; - } else { - instance->status_value |= irq_status; - instance->status_value_edges |= status_val; - } - - if (instance->filtering_flag) { // For compare mode only. - if (instance->compare_value == instance->line_value) { - instance->rised = 1; - instance->irq_count++; - } - } else { - instance->rised = 1; - instance->irq_count++; - } - - spin_unlock(&instance->subdevice_lock); - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base, - uint32_t plx_reg_base, - unsigned int di_idx, - int irq, - spinlock_t *ctrl_reg_lock) -{ - me8100_di_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8100_di_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8100_di_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the subdevice index. */ - subdevice->di_idx = di_idx; - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Register interrupt service routine. */ - subdevice->irq = irq; - err = request_irq(subdevice->irq, me8100_isr, - IRQF_DISABLED | IRQF_SHARED, - ME8100_NAME, (void *)subdevice); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", subdevice->irq); - - /* Initialize the registers */ - subdevice->ctrl_reg = - me8100_reg_base + ME8100_CTRL_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->port_reg = - me8100_reg_base + ME8100_DI_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->mask_reg = - me8100_reg_base + ME8100_MASK_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->pattern_reg = - me8100_reg_base + ME8100_PATTERN_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->din_int_reg = - me8100_reg_base + ME8100_INT_DI_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->irq_reset_reg = - me8100_reg_base + ME8100_RES_INT_REG_A + di_idx * ME8100_REG_OFFSET; - subdevice->irq_status_reg = plx_reg_base + PLX_INTCSR; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = me8100_reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_irq_start = me8100_di_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me8100_di_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me8100_di_io_irq_stop; - subdevice->base.me_subdevice_io_reset_subdevice = - me8100_di_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me8100_di_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8100_di_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me8100_di_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8100_di_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8100_di_query_subdevice_caps; - subdevice->base.me_subdevice_destructor = me8100_di_destructor; - - subdevice->rised = 0; - subdevice->irq_count = 0; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8100_di.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file me8100_di.h - * - * @brief ME-8100 digital input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_DI_H_ -#define _ME8100_DI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me8100_di_subdevice { - // Inheritance - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; - - unsigned di_idx; - - int irq; - volatile int rised; - unsigned int irq_count; - - uint status_flag; /**< Default interupt status flag */ - uint status_value; /**< Interupt status */ - uint status_value_edges; /**< Extended interupt status */ - uint line_value; - - uint16_t compare_value; - uint8_t filtering_flag; - - wait_queue_head_t wait_queue; - - unsigned long ctrl_reg; - unsigned long port_reg; - unsigned long mask_reg; - unsigned long pattern_reg; - unsigned long long din_int_reg; - unsigned long irq_reset_reg; - unsigned long irq_status_reg; -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif - -} me8100_di_subdevice_t; - -/** - * @brief The constructor to generate a ME-8100 digital input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8100_di_subdevice_t *me8100_di_constructor(uint32_t me8100_reg_base, - uint32_t plx_reg_base, - unsigned int di_idx, - int irq, - spinlock_t * ctrl_leg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_di_reg.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file me8100_di_reg.h - * - * @brief ME-8100 digital input subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_DI_REG_H_ -#define _ME8100_DI_REG_H_ - -#ifdef __KERNEL__ - -#define ME8100_RES_INT_REG_A 0x02 //(r, ) -#define ME8100_DI_REG_A 0x04 //(r, ) -#define ME8100_PATTERN_REG_A 0x08 //( ,w) -#define ME8100_MASK_REG_A 0x0A //( ,w) -#define ME8100_INT_DI_REG_A 0x0A //(r, ) - -#define ME8100_RES_INT_REG_B 0x0E //(r, ) -#define ME8100_DI_REG_B 0x10 //(r, ) -#define ME8100_PATTERN_REG_B 0x14 //( ,w) -#define ME8100_MASK_REG_B 0x16 //( ,w) -#define ME8100_INT_DI_REG_B 0x16 //(r, ) - -#define ME8100_REG_OFFSET 0x0C - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_do.c +++ /dev/null @@ -1,391 +0,0 @@ -/** - * @file me8100_do.c - * - * @brief ME-8100 digital output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me8100_reg.h" -#include "me8100_do_reg.h" -#include "me8100_do.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me8100_do_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8100_do_subdevice_t *instance; - uint16_t ctrl; - - PDEBUG("executed.\n"); - - instance = (me8100_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - ctrl = inw(instance->ctrl_reg); - ctrl &= ME8100_DIO_CTRL_BIT_INTB_1 | ME8100_DIO_CTRL_BIT_INTB_0; - outw(ctrl, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->ctrl_reg_lock); - outw(0, instance->port_reg); - instance->port_reg_mirror = 0; - PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8100_do_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8100_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - int config; - - PDEBUG("executed.\n"); - - instance = (me8100_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - config = inw(instance->ctrl_reg); - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_WORD: - if (channel == 0) { - if (single_config == - ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE) { - config &= ~(ME8100_DIO_CTRL_BIT_ENABLE_DIO); - } else if (single_config == ME_SINGLE_CONFIG_DIO_SINK) { - config |= ME8100_DIO_CTRL_BIT_ENABLE_DIO; - config &= ~ME8100_DIO_CTRL_BIT_SOURCE; - } else if (single_config == ME_SINGLE_CONFIG_DIO_SOURCE) { - config |= - ME8100_DIO_CTRL_BIT_ENABLE_DIO | - ME8100_DIO_CTRL_BIT_SOURCE; - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid word number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outw(config, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, config); - } - - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_do_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8100_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8100_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 16)) { - *value = instance->port_reg_mirror & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = instance->port_reg_mirror & 0xFF; - } else if (channel == 1) { - *value = (instance->port_reg_mirror >> 8) & 0xFF; - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_WORD: - if (channel == 0) { - *value = instance->port_reg_mirror; - } else { - PERROR("Invalid word number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_do_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me8100_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8100_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 16)) { - instance->port_reg_mirror = - value ? (instance-> - port_reg_mirror | (0x1 << channel)) - : (instance->port_reg_mirror & ~(0x1 << channel)); - outw(instance->port_reg_mirror, instance->port_reg); - PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - instance->port_reg_mirror); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - instance->port_reg_mirror &= ~0xFF; - instance->port_reg_mirror |= value & 0xFF; - outw(instance->port_reg_mirror, instance->port_reg); - PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - instance->port_reg_mirror); - } else if (channel == 1) { - instance->port_reg_mirror &= ~0xFF00; - instance->port_reg_mirror |= (value << 8) & 0xFF00; - outw(instance->port_reg_mirror, instance->port_reg); - PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - instance->port_reg_mirror); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_WORD: - if (channel == 0) { - instance->port_reg_mirror = value; - outw(value, instance->port_reg); - PDEBUG_REG("port_reg outw(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - value); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8100_do_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 16; - return ME_ERRNO_SUCCESS; -} - -static int me8100_do_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8100_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_SINK_SOURCE; - return ME_ERRNO_SUCCESS; -} - -me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base, - unsigned int do_idx, - spinlock_t *ctrl_reg_lock) -{ - me8100_do_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8100_do_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8100_do_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - - /* Initialize registers */ - if (do_idx == 0) { - subdevice->port_reg = reg_base + ME8100_DO_REG_A; - subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_A; - } else if (do_idx == 1) { - subdevice->port_reg = reg_base + ME8100_DO_REG_B; - subdevice->ctrl_reg = reg_base + ME8100_CTRL_REG_B; - } else { - PERROR("Wrong subdevice idx=%d.\n", do_idx); - kfree(subdevice); - return NULL; - } -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the subdevice index */ - subdevice->do_idx = do_idx; - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me8100_do_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me8100_do_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8100_do_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me8100_do_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me8100_do_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8100_do_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8100_do_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8100_do.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @file me8100_do.h - * - * @brief ME-8100 digital output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_DO_H_ -#define _ME8100_DO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me8100_do_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the #ctrl_reg. */ - - unsigned int do_idx; - - uint16_t port_reg_mirror; /**< Mirror used to store current port register setting which is write only. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Control register. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me8100_do_subdevice_t; - -/** - * @brief The constructor to generate a ME-8100 digital output subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param do_idx The index of the digital output subdevice on this device. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8100_do_subdevice_t *me8100_do_constructor(uint32_t reg_base, - unsigned int do_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_do_reg.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file me8100_ao_reg.h - * - * @brief ME-8100 analog output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_DO_REG_H_ -#define _ME8100_DO_REG_H_ - -#ifdef __KERNEL__ - -#define ME8100_DO_REG_A 0x06 //( ,w) -#define ME8100_DO_REG_B 0x12 //( ,w) - -#endif -#endif --- a/drivers/staging/meilhaus/me8100_reg.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @file me8100_reg.h - * - * @brief ME-8100 register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8100_REG_H_ -#define _ME8100_REG_H_ - -#ifdef __KERNEL__ - -#define ME8100_CTRL_REG_A 0x00 //( ,w) -#define ME8100_CTRL_REG_B 0x0C //( ,w) - -#define ME8100_DIO_CTRL_BIT_SOURCE 0x10 -#define ME8100_DIO_CTRL_BIT_INTB_1 0x20 -#define ME8100_DIO_CTRL_BIT_INTB_0 0x40 -#define ME8100_DIO_CTRL_BIT_ENABLE_DIO 0x80 - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_device.c +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @file me8200_device.c - * - * @brief ME-8200 device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include "meids.h" -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "meplx_reg.h" -#include "medevice.h" -#include "me8200_device.h" -#include "mesubdevice.h" -#include "me8200_di.h" -#include "me8200_do.h" -#include "me8200_dio.h" - -me_device_t *me8200_pci_constructor(struct pci_dev *pci_device) -{ - me8200_device_t *me8200_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - me8200_device = kmalloc(sizeof(me8200_device_t), GFP_KERNEL); - - if (!me8200_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(me8200_device, 0, sizeof(me8200_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) me8200_device, pci_device); - - if (err) { - kfree(me8200_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - me8200_versions_get_device_index(me8200_device->base.info.pci. - device_id); - - // Initialize spin lock . - spin_lock_init(&me8200_device->irq_ctrl_lock); - spin_lock_init(&me8200_device->irq_mode_lock); - spin_lock_init(&me8200_device->dio_ctrl_lock); - - /* Setup the PLX interrupt configuration */ - outl(PLX_INTCSR_LOCAL_INT1_EN | - PLX_INTCSR_LOCAL_INT1_POL | - PLX_INTCSR_LOCAL_INT2_EN | - PLX_INTCSR_LOCAL_INT2_POL | - PLX_INTCSR_PCI_INT_EN, - me8200_device->base.info.pci.reg_bases[1] + PLX_INTCSR); - - // Create subdevice instances. - - for (i = 0; i < me8200_versions[version_idx].di_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8200_di_constructor(me8200_device-> - base.info.pci. - reg_bases[2], i, - me8200_device-> - base.irq, - &me8200_device-> - irq_ctrl_lock, - &me8200_device-> - irq_mode_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8200_device); - kfree(me8200_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8200_device->base.slist, - subdevice); - } - - for (i = 0; i < me8200_versions[version_idx].do_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8200_do_constructor(me8200_device-> - base.info.pci. - reg_bases[2], i, - me8200_device-> - base.irq, - &me8200_device-> - irq_mode_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8200_device); - kfree(me8200_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8200_device->base.slist, - subdevice); - } - - for (i = 0; i < me8200_versions[version_idx].dio_subdevices; i++) { - subdevice = - (me_subdevice_t *) me8200_dio_constructor(me8200_device-> - base.info.pci. - reg_bases[2], i, - &me8200_device-> - dio_ctrl_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) me8200_device); - kfree(me8200_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&me8200_device->base.slist, - subdevice); - } - - return (me_device_t *) me8200_device; -} -EXPORT_SYMBOL(me8200_pci_constructor); - -// Init and exit of module. - -static int __init me8200_init(void) -{ - PDEBUG("executed.\n."); - return 0; -} - -static void __exit me8200_exit(void) -{ - PDEBUG("executed.\n."); -} - -module_init(me8200_init); - -module_exit(me8200_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR("Guenter Gebhardt "); -MODULE_DESCRIPTION("Device Driver Module for Template Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/me8200_device.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @file me8200_device.h - * - * @brief ME-8200 device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DEVICE_H -#define _ME8200_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding ME-8200 device capabilities. - */ -typedef struct me8200_version { - uint16_t device_id; - unsigned int di_subdevices; - unsigned int do_subdevices; - unsigned int dio_subdevices; -} me8200_version_t; - -/** - * @brief Device capabilities. - */ -static me8200_version_t me8200_versions[] = { - {PCI_DEVICE_ID_MEILHAUS_ME8200_A, 1, 1, 2}, - {PCI_DEVICE_ID_MEILHAUS_ME8200_B, 2, 2, 2}, - {0}, -}; - -#define ME8200_DEVICE_VERSIONS (ARRAY_SIZE(me8200_versions) - 1) /**< Returns the number of entries in #me8200_versions. */ - -/** - * @brief Returns the index of the device entry in #me8200_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #me8200_versions. - */ -static inline unsigned int me8200_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < ME8200_DEVICE_VERSIONS; i++) - if (me8200_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The ME-8200 device class structure. - */ -typedef struct me8200_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t irq_ctrl_lock; /**< Lock for the interrupt control register. */ - spinlock_t irq_mode_lock; /**< Lock for the interrupt mode register. */ - spinlock_t dio_ctrl_lock; /**< Lock for the digital i/o control register. */ -} me8200_device_t; - -/** - * @brief The ME-8200 device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new ME-8200 device instance. \n - * NULL on error. - */ -me_device_t *me8200_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_di.c +++ /dev/null @@ -1,832 +0,0 @@ -/** - * @file me8200_di.c - * - * @brief ME-8200 digital input subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -///Includes -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meerror.h" - -#include "meids.h" -#include "medebug.h" -#include "me8200_reg.h" -#include "me8200_di_reg.h" -#include "me8200_di.h" - -/// Defines -static void me8200_di_destructor(struct me_subdevice *subdevice); -static int me8200_di_io_irq_start(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags); -static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags); -static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, - struct file *filep, int channel, int flags); -static int me8200_di_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags); -static int me8200_di_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags); -static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags); -static int me8200_di_query_number_channels(me_subdevice_t *subdevice, - int *number); -static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype); -static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps); -static irqreturn_t me8200_isr(int irq, void *dev_id); -static irqreturn_t me8200_isr_EX(int irq, void *dev_id); -static void me8200_di_check_version(me8200_di_subdevice_t *instance, - unsigned long addr); - -///Functions -static int me8200_di_io_irq_start(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me8200_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - volatile uint8_t tmp; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_di_subdevice_t *) subdevice; - - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - if (flags & - ~(ME_IO_IRQ_START_PATTERN_FILTERING | - ME_IO_IRQ_START_DIO_BYTE)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (irq_edge != ME_IRQ_EDGE_NOT_USED) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - } else if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - if (flags & - ~(ME_IO_IRQ_START_EXTENDED_STATUS | - ME_IO_IRQ_START_DIO_BYTE)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if ((irq_edge != ME_IRQ_EDGE_RISING) - && (irq_edge != ME_IRQ_EDGE_FALLING) - && (irq_edge != ME_IRQ_EDGE_ANY)) { - PERROR("Invalid irq edge specified.\n"); - return ME_ERRNO_INVALID_IRQ_EDGE; - } - - if (!(irq_arg & 0xFF)) { - PERROR("No mask specified.\n"); - return ME_ERRNO_INVALID_IRQ_ARG; - } - } else { - PERROR("Invalid irq source specified.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - outb(irq_arg, instance->compare_reg); - PDEBUG_REG("compare_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->compare_reg - instance->reg_base, irq_arg); - outb(0xFF, instance->mask_reg); - PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->mask_reg - instance->reg_base, 0xff); - instance->compare_value = irq_arg; - instance->filtering_flag = - (flags & ME_IO_IRQ_START_PATTERN_FILTERING) ? 1 : 0; - } - if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - outb(irq_arg, instance->mask_reg); - PDEBUG_REG("mask_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->mask_reg - instance->reg_base, irq_arg); - instance->filtering_flag = 0; - } - - spin_lock(instance->irq_mode_lock); - tmp = inb(instance->irq_mode_reg); - tmp &= - ~(ME8200_IRQ_MODE_MASK << - (ME8200_IRQ_MODE_DI_SHIFT * instance->di_idx)); - if (irq_source == ME_IRQ_SOURCE_DIO_PATTERN) { - tmp |= - ME8200_IRQ_MODE_MASK_COMPARE << (ME8200_IRQ_MODE_DI_SHIFT * - instance->di_idx); - } - - if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - tmp |= - ME8200_IRQ_MODE_MASK_MASK << (ME8200_IRQ_MODE_DI_SHIFT * - instance->di_idx); - } - outb(tmp, instance->irq_mode_reg); - PDEBUG_REG("irq_mode_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_mode_reg - instance->reg_base, tmp); - spin_unlock(instance->irq_mode_lock); - - spin_lock(instance->irq_ctrl_lock); - tmp = inb(instance->irq_ctrl_reg); - tmp |= - (ME8200_DI_IRQ_CTRL_BIT_CLEAR << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - tmp |= - ME8200_DI_IRQ_CTRL_BIT_ENABLE << (ME8200_DI_IRQ_CTRL_SHIFT * - instance->di_idx); - - if (irq_source == ME_IRQ_SOURCE_DIO_MASK) { - tmp &= - ~(ME8200_DI_IRQ_CTRL_MASK_EDGE << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - if (irq_edge == ME_IRQ_EDGE_RISING) { - tmp |= - ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); - } else if (irq_edge == ME_IRQ_EDGE_FALLING) { - tmp |= - ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); - } else if (irq_edge == ME_IRQ_EDGE_ANY) { - tmp |= - ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx); - } - } - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - tmp &= - ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - - instance->line_value = inb(instance->port_reg); - spin_unlock(instance->irq_ctrl_lock); - - instance->rised = 0; - instance->status_value = 0; - instance->status_value_edges = 0; - instance->status_flag = flags & ME_IO_IRQ_START_EXTENDED_STATUS; - spin_unlock_irqrestore(&instance->subdevice_lock, status); - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_di_io_irq_wait(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me8200_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - unsigned long cpu_flags; - int count; - - PDEBUG("executed.\n"); - PDEVELOP("PID: %d.\n", current->pid); - - instance = (me8200_di_subdevice_t *) subdevice; - - if (flags & - ~(ME_IO_IRQ_WAIT_NORMAL_STATUS | ME_IO_IRQ_WAIT_EXTENDED_STATUS)) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - count = instance->count; - - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - ((count != - instance->count) - || (instance-> - rised < 0)), - t); -// t = wait_event_interruptible_timeout(instance->wait_queue, (instance->rised != 0), t); - if (t == 0) { - PERROR("Wait on interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - ((count != instance->count) - || (instance->rised < 0))); -// wait_event_interruptible(instance->wait_queue, (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - *irq_count = instance->count; - if (!err) { - if (flags & ME_IO_IRQ_WAIT_NORMAL_STATUS) { - *value = instance->status_value; - } else if (flags & ME_IO_IRQ_WAIT_EXTENDED_STATUS) { - *value = instance->status_value_edges; - } else { // Use default - if (!instance->status_flag) { - *value = instance->status_value; - } else { - *value = instance->status_value_edges; - } - } - instance->rised = 0; -/* - instance->status_value = 0; - instance->status_value_edges = 0; -*/ - } else { - *value = 0; - } - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_di_io_irq_stop(me_subdevice_t *subdevice, - struct file *filep, int channel, int flags) -{ - me8200_di_subdevice_t *instance; - uint8_t tmp; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_di_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER spin_lock_irqsave(&instance->subdevice_lock, status); - spin_lock(instance->irq_ctrl_lock); - tmp = inb(instance->irq_ctrl_reg); - tmp |= - (ME8200_DI_IRQ_CTRL_BIT_ENABLE << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - tmp &= - ~(ME8200_DI_IRQ_CTRL_BIT_ENABLE << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - tmp |= - (ME8200_DI_IRQ_CTRL_BIT_CLEAR << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); -// tmp &= ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->irq_ctrl_lock); - - instance->rised = -1; - instance->status_value = 0; - instance->status_value_edges = 0; - instance->filtering_flag = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, status); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8200_di_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8200_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - } else { - PERROR("Invalid port direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_di_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8200_di_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_di_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_reg); - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_di_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8200_di_subdevice_t *instance = (me8200_di_subdevice_t *) subdevice; - - PDEBUG("executed.\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - instance->count = 0; - return me8200_di_io_irq_stop(subdevice, filep, 0, 0); -} - -static int me8200_di_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me8200_di_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DI; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8200_di_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = - ME_CAPS_DIO_BIT_PATTERN_IRQ | - ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING | - ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING | - ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY; - return ME_ERRNO_SUCCESS; -} - -static irqreturn_t me8200_isr(int irq, void *dev_id) -{ - me8200_di_subdevice_t *instance; - uint8_t ctrl; - uint8_t irq_status; - uint8_t line_value = 0; - uint8_t line_status = 0; - uint32_t status_val = 0; - - instance = (me8200_di_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inb(instance->irq_status_reg); - if (!irq_status) { - PINFO - ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", - jiffies, __func__, instance->di_idx, irq_status); - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->irq_ctrl_lock); - ctrl = inb(instance->irq_ctrl_reg); - ctrl |= - ME8200_DI_IRQ_CTRL_BIT_CLEAR << (ME8200_DI_IRQ_CTRL_SHIFT * - instance->di_idx); - outb(ctrl, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, ctrl); - ctrl &= - ~(ME8200_DI_IRQ_CTRL_BIT_CLEAR << - (ME8200_DI_IRQ_CTRL_SHIFT * instance->di_idx)); - outb(ctrl, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, ctrl); - - line_value = inb(instance->port_reg); - spin_unlock(instance->irq_ctrl_lock); - - line_status = ((uint8_t) instance->line_value ^ line_value); - - // Make extended information. - status_val |= (0x00FF & (~(uint8_t) instance->line_value & line_value)) << 16; //Raise - status_val |= (0x00FF & ((uint8_t) instance->line_value & ~line_value)); //Fall - - instance->line_value = (int)line_value; - - if (instance->rised == 0) { - instance->status_value = irq_status | line_status; - instance->status_value_edges = status_val; - } else { - instance->status_value |= irq_status | line_status; - instance->status_value_edges |= status_val; - } - - if (instance->filtering_flag) { // For compare mode only. - if (instance->compare_value == instance->line_value) { - instance->rised = 1; - instance->count++; - } - } else { - instance->rised = 1; - instance->count++; - } - spin_unlock(&instance->subdevice_lock); - - spin_unlock(&instance->subdevice_lock); - - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -static irqreturn_t me8200_isr_EX(int irq, void *dev_id) -{ - me8200_di_subdevice_t *instance; - uint8_t irq_status = 0; - uint16_t irq_status_EX = 0; - uint32_t status_val = 0; - int i, j; - - instance = (me8200_di_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - //Reset latches. Copy status to extended registers. - irq_status = inb(instance->irq_status_reg); - PDEBUG_REG("idx=%d irq_status_reg=0x%02X\n", instance->di_idx, - irq_status); - - if (!irq_status) { - PINFO - ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", - jiffies, __func__, instance->di_idx, irq_status); - return IRQ_NONE; - } - - irq_status_EX = inb(instance->irq_status_low_reg); - irq_status_EX |= (inb(instance->irq_status_high_reg) << 8); - - PDEVELOP("EXTENDED REG: 0x%04x\n", irq_status_EX); - instance->line_value = inb(instance->port_reg); - - // Format extended information. - for (i = 0, j = 0; i < 8; i++, j += 2) { - status_val |= ((0x01 << j) & irq_status_EX) >> (j - i); //Fall - status_val |= ((0x01 << (j + 1)) & irq_status_EX) << (15 - j + i); //Raise - } - - spin_lock(&instance->subdevice_lock); - if (instance->rised == 0) { - instance->status_value = irq_status; - instance->status_value_edges = status_val; - } else { - instance->status_value |= irq_status; - instance->status_value_edges |= status_val; - } - - if (instance->filtering_flag) { // For compare mode only. - if (instance->compare_value == instance->line_value) { - instance->rised = 1; - instance->count++; - } - } else { - instance->rised = 1; - instance->count++; - } - spin_unlock(&instance->subdevice_lock); - - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -static void me8200_di_destructor(struct me_subdevice *subdevice) -{ - me8200_di_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me8200_di_subdevice_t *) subdevice; - - free_irq(instance->irq, (void *)instance); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_regbase, - unsigned int di_idx, - int irq, - spinlock_t *irq_ctrl_lock, - spinlock_t *irq_mode_lock) -{ - me8200_di_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8200_di_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8200_di_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Check firmware version. - me8200_di_check_version(subdevice, - me8200_regbase + ME8200_FIRMWARE_VERSION_REG); - - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->irq_ctrl_lock = irq_ctrl_lock; - subdevice->irq_mode_lock = irq_mode_lock; - - /* Save the subdevice index. */ - subdevice->di_idx = di_idx; - - /* Initialize registers */ - if (di_idx == 0) { - subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_0_REG; - subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_0_REG; - subdevice->compare_reg = - me8200_regbase + ME8200_DI_COMPARE_0_REG; - subdevice->irq_status_reg = - me8200_regbase + ME8200_DI_CHANGE_0_REG; - - subdevice->irq_status_low_reg = - me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_LOW_REG; - subdevice->irq_status_high_reg = - me8200_regbase + ME8200_DI_EXTEND_CHANGE_0_HIGH_REG; - } else if (di_idx == 1) { - subdevice->port_reg = me8200_regbase + ME8200_DI_PORT_1_REG; - subdevice->mask_reg = me8200_regbase + ME8200_DI_MASK_1_REG; - subdevice->compare_reg = - me8200_regbase + ME8200_DI_COMPARE_1_REG; - subdevice->irq_status_reg = - me8200_regbase + ME8200_DI_CHANGE_1_REG; - - subdevice->irq_status_low_reg = - me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_LOW_REG; - subdevice->irq_status_high_reg = - me8200_regbase + ME8200_DI_EXTEND_CHANGE_1_HIGH_REG; - } else { - PERROR("Wrong subdevice idx=%d.\n", di_idx); - kfree(subdevice); - return NULL; - } - subdevice->irq_ctrl_reg = me8200_regbase + ME8200_DI_IRQ_CTRL_REG; - subdevice->irq_mode_reg = me8200_regbase + ME8200_IRQ_MODE_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = me8200_regbase; -#endif - - /* Initialize wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_irq_start = me8200_di_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me8200_di_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me8200_di_io_irq_stop; - subdevice->base.me_subdevice_io_reset_subdevice = - me8200_di_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me8200_di_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8200_di_io_single_read; - subdevice->base.me_subdevice_query_number_channels = - me8200_di_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8200_di_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8200_di_query_subdevice_caps; - subdevice->base.me_subdevice_destructor = me8200_di_destructor; - - subdevice->rised = 0; - subdevice->count = 0; - - /* Register interrupt service routine. */ - subdevice->irq = irq; - if (subdevice->version > 0) { // NEW - err = request_irq(subdevice->irq, me8200_isr_EX, - IRQF_DISABLED | IRQF_SHARED, - ME8200_NAME, (void *)subdevice); - } else { //OLD - err = request_irq(subdevice->irq, me8200_isr, - IRQF_DISABLED | IRQF_SHARED, - ME8200_NAME, (void *)subdevice); - } - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - PDEBUG("Registred irq=%d.\n", subdevice->irq); - - return subdevice; -} - -static void me8200_di_check_version(me8200_di_subdevice_t *instance, - unsigned long addr) -{ - - PDEBUG("executed.\n"); - instance->version = 0x000000FF & inb(addr); - PDEVELOP("me8200 firmware version: %d\n", instance->version); - - /// @note Fix for wrong values in this registry. - if ((instance->version < 0x7) || (instance->version > 0x1F)) - instance->version = 0x0; -} --- a/drivers/staging/meilhaus/me8200_di.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file me8200_di.h - * - * @brief ME-8200 digital input subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DI_H_ -#define _ME8200_DI_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me8200_di_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; - spinlock_t *irq_ctrl_lock; - spinlock_t *irq_mode_lock; - - unsigned int di_idx; - unsigned int version; - - int irq; /**< The number of the interrupt request. */ - volatile int rised; /**< Flag to indicate if an interrupt occured. */ - uint status_flag; /**< Default interupt status flag */ - uint status_value; /**< Interupt status */ - uint status_value_edges; /**< Extended interupt status */ - uint line_value; - int count; /**< Counts the number of interrupts occured. */ - uint8_t compare_value; - uint8_t filtering_flag; - - wait_queue_head_t wait_queue; /**< To wait on interrupts. */ - - unsigned long port_reg; /**< The digital input port. */ - unsigned long compare_reg; /**< The register to hold the value to compare with. */ - unsigned long mask_reg; /**< The register to hold the mask. */ - unsigned long irq_mode_reg; /**< The interrupt mode register. */ - unsigned long irq_ctrl_reg; /**< The interrupt control register. */ - unsigned long irq_status_reg; /**< The interrupt status register. Also interrupt reseting register (firmware version 7 and later).*/ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif - unsigned long firmware_version_reg; /**< The interrupt reseting register. */ - - unsigned long irq_status_low_reg; /**< The interrupt extended status register (low part). */ - unsigned long irq_status_high_reg; /**< The interrupt extended status register (high part). */ -} me8200_di_subdevice_t; - -/** - * @brief The constructor to generate a ME-8200 digital input subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8200_di_subdevice_t *me8200_di_constructor(uint32_t me8200_reg_base, - unsigned int di_idx, - int irq, - spinlock_t * irq_ctrl_lock, - spinlock_t * irq_mode_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_dio.c +++ /dev/null @@ -1,418 +0,0 @@ -/** - * @file me8200_dio.c - * - * @brief ME-8200 digital input/output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me8200_dio_reg.h" -#include "me8200_dio.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me8200_dio_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8200_dio_subdevice_t *instance; - uint8_t mode; - - PDEBUG("executed.\n"); - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - instance = (me8200_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - mode &= ~(0x3 << (instance->dio_idx * 2)); - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - spin_unlock(instance->ctrl_reg_lock); - outb(0x00, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0x00); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8200_dio_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8200_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint32_t mode; - uint32_t size = - flags & (ME_IO_SINGLE_CONFIG_DIO_BIT | ME_IO_SINGLE_CONFIG_DIO_BYTE - | ME_IO_SINGLE_CONFIG_DIO_WORD | - ME_IO_SINGLE_CONFIG_DIO_DWORD); - - PDEBUG("executed.\n"); - - instance = (me8200_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - mode = inb(instance->ctrl_reg); - switch (size) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - mode &= - ~((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - mode &= - ~((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - mode |= - ME8200_DIO_CTRL_BIT_MODE_0 << (instance-> - dio_idx * 2); - } else { - PERROR - ("Invalid port configuration specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid channel number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - - break; - - default: - PERROR("Invalid flags.\n"); - - err = ME_ERRNO_INVALID_FLAGS; - } - - if (!err) { - outb(mode, instance->ctrl_reg); - PDEBUG_REG("ctrl_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->ctrl_reg - instance->reg_base, mode); - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_dio_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8200_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - - PDEBUG("executed.\n"); - - instance = (me8200_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if ((mode == - (ME8200_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = - inb(instance-> - port_reg) & (0x0001 << channel); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if ((mode == - (ME8200_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) || !mode) { - *value = inb(instance->port_reg) & 0x00FF; - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_dio_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me8200_dio_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t mode; - uint8_t byte; - - PDEBUG("executed.\n"); - - instance = (me8200_dio_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - mode = - inb(instance-> - ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME8200_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - byte = inb(instance->port_reg); - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outb(byte, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, byte); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - mode = - inb(instance-> - ctrl_reg) & ((ME8200_DIO_CTRL_BIT_MODE_0 | - ME8200_DIO_CTRL_BIT_MODE_1) << - (instance->dio_idx * 2)); - - if (mode == - (ME8200_DIO_CTRL_BIT_MODE_0 << - (instance->dio_idx * 2))) { - outb(value, instance->port_reg); - PDEBUG_REG("port_reg outl(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - - instance->reg_base, value); - } else { - PERROR("Port not in output or input mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(instance->ctrl_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_dio_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me8200_dio_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8200_dio_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_DIR_BYTE; - return ME_ERRNO_SUCCESS; -} - -me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t *ctrl_reg_lock) -{ - me8200_dio_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8200_dio_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8200_dio_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save digital i/o index */ - subdevice->dio_idx = dio_idx; - - /* Save the subdevice index */ - subdevice->ctrl_reg = reg_base + ME8200_DIO_CTRL_REG; - subdevice->port_reg = reg_base + ME8200_DIO_PORT_REG + dio_idx; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me8200_dio_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me8200_dio_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8200_dio_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me8200_dio_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me8200_dio_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8200_dio_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8200_dio_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8200_dio.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file me8200_dio.h - * - * @brief ME-8200 digital input/output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DIO_H_ -#define _ME8200_DIO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me8200_dio_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - unsigned int dio_idx; /**< The index of the digital i/o on the device. */ - - unsigned long port_reg; /**< Register holding the port status. */ - unsigned long ctrl_reg; /**< Register to configure the port direction. */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me8200_dio_subdevice_t; - -/** - * @brief The constructor to generate a ME-8200 digital input/ouput subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param dio_idx The index of the digital i/o port on the device. - * @param ctrl_reg_lock Spin lock protecting the control register. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8200_dio_subdevice_t *me8200_dio_constructor(uint32_t reg_base, - unsigned int dio_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_dio_reg.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file me8200_dio_reg.h - * - * @brief ME-8200 digital input/output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DIO_REG_H_ -#define _ME8200_DIO_REG_H_ - -#ifdef __KERNEL__ - -#define ME8200_DIO_CTRL_REG 0x7 // R/W -#define ME8200_DIO_PORT_0_REG 0x8 // R/W -#define ME8200_DIO_PORT_1_REG 0x9 // R/W -#define ME8200_DIO_PORT_REG ME8200_DIO_PORT_0_REG // R/W - -#define ME8200_DIO_CTRL_BIT_MODE_0 0x01 -#define ME8200_DIO_CTRL_BIT_MODE_1 0x02 -#define ME8200_DIO_CTRL_BIT_MODE_2 0x04 -#define ME8200_DIO_CTRL_BIT_MODE_3 0x08 - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_di_reg.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file me8200_di_reg.h - * - * @brief ME-8200 digital input subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DI_REG_H_ -#define _ME8200_DI_REG_H_ - -#ifdef __KERNEL__ - -// Common registry for whole family. -#define ME8200_DI_PORT_0_REG 0x3 // R -#define ME8200_DI_PORT_1_REG 0x4 // R - -#define ME8200_DI_MASK_0_REG 0x5 // R/W -#define ME8200_DI_MASK_1_REG 0x6 // R/W - -#define ME8200_DI_COMPARE_0_REG 0xA // R/W -#define ME8200_DI_COMPARE_1_REG 0xB // R/W - -#define ME8200_DI_IRQ_CTRL_REG 0xC // R/W - -#ifndef ME8200_IRQ_MODE_REG -# define ME8200_IRQ_MODE_REG 0xD // R/W -#endif - -// This registry are for all versions -#define ME8200_DI_CHANGE_0_REG 0xE // R -#define ME8200_DI_CHANGE_1_REG 0xF // R - -#define ME8200_DI_IRQ_CTRL_BIT_CLEAR 0x4 -#define ME8200_DI_IRQ_CTRL_BIT_ENABLE 0x8 - -// This registry are for firmware versions 7 and later -#define ME8200_DI_EXTEND_CHANGE_0_LOW_REG 0x10 // R -#define ME8200_DI_EXTEND_CHANGE_0_HIGH_REG 0x11 // R -#define ME8200_DI_EXTEND_CHANGE_1_LOW_REG 0x12 // R -#define ME8200_DI_EXTEND_CHANGE_1_HIGH_REG 0x13 // R - -#ifndef ME8200_FIRMWARE_VERSION_REG -# define ME8200_FIRMWARE_VERSION_REG 0x14 // R -#endif - -// Bit definitions -#define ME8200_DI_IRQ_CTRL_MASK_EDGE 0x3 -#define ME8200_DI_IRQ_CTRL_MASK_EDGE_RISING 0x0 -#define ME8200_DI_IRQ_CTRL_MASK_EDGE_FALLING 0x1 -#define ME8200_DI_IRQ_CTRL_MASK_EDGE_ANY 0x3 - -// Others -#define ME8200_DI_IRQ_CTRL_SHIFT 4 - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_do.c +++ /dev/null @@ -1,591 +0,0 @@ -/** - * @file me8200_do.c - * - * @brief ME-8200 digital output subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "meids.h" -#include "medebug.h" -#include "me8200_reg.h" -#include "me8200_do_reg.h" -#include "me8200_do.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static int me8200_do_io_irq_start(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - me8200_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t tmp; - unsigned long status; - - if (flags & ~ME_IO_IRQ_START_DIO_BYTE) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel != 0) { - PERROR("Invalid channel specified.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - if (irq_source != ME_IRQ_SOURCE_DIO_OVER_TEMP) { - PERROR("Invalid interrupt source specified.\n"); - return ME_ERRNO_INVALID_IRQ_SOURCE; - } - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - spin_lock(instance->irq_mode_lock); - tmp = inb(instance->irq_ctrl_reg); - tmp |= - ME8200_IRQ_MODE_BIT_ENABLE_POWER << (ME8200_IRQ_MODE_POWER_SHIFT * - instance->do_idx); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->irq_mode_lock); - instance->rised = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_do_io_irq_wait(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - me8200_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - long t = 0; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (time_out < 0) { - PERROR("Invalid time_out specified.\n"); - return ME_ERRNO_INVALID_TIMEOUT; - } - - if (time_out) { - t = (time_out * HZ) / 1000; - - if (t == 0) - t = 1; - } - - ME_SUBDEVICE_ENTER; - - if (instance->rised <= 0) { - instance->rised = 0; - - if (time_out) { - t = wait_event_interruptible_timeout(instance-> - wait_queue, - (instance->rised != - 0), t); - - if (t == 0) { - PERROR - ("Wait on external interrupt timed out.\n"); - err = ME_ERRNO_TIMEOUT; - } - } else { - wait_event_interruptible(instance->wait_queue, - (instance->rised != 0)); - } - - if (instance->rised < 0) { - PERROR("Wait on interrupt aborted by user.\n"); - err = ME_ERRNO_CANCELLED; - } - } - - if (signal_pending(current)) { - PERROR("Wait on external interrupt aborted by signal.\n"); - err = ME_ERRNO_SIGNAL; - } - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - instance->rised = 0; - *irq_count = instance->count; - *value = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_do_io_irq_stop(me_subdevice_t *subdevice, - struct file *filep, int channel, int flags) -{ - me8200_do_subdevice_t *instance; - uint8_t tmp; - unsigned long cpu_flags; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - spin_lock(instance->irq_mode_lock); - tmp = inb(instance->irq_ctrl_reg); - tmp &= - ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER << - (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx)); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->irq_mode_lock); - instance->rised = -1; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8200_do_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8200_do_subdevice_t *instance; - unsigned long cpu_flags; - uint8_t tmp; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, cpu_flags); - outb(0x00, instance->port_reg); - PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->port_reg - instance->reg_base, 0x00); - spin_lock(instance->irq_mode_lock); - tmp = inb(instance->irq_ctrl_reg); - tmp &= - ~(ME8200_IRQ_MODE_BIT_ENABLE_POWER << - (ME8200_IRQ_MODE_POWER_SHIFT * instance->do_idx)); - outb(tmp, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outb(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, tmp); - spin_unlock(instance->irq_mode_lock); - instance->rised = -1; - instance->count = 0; - spin_unlock_irqrestore(&instance->subdevice_lock, cpu_flags); - wake_up_interruptible_all(&instance->wait_queue); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8200_do_io_single_config(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8200_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - switch (flags) { - case ME_IO_SINGLE_CONFIG_NO_FLAGS: - case ME_IO_SINGLE_CONFIG_DIO_BYTE: - if (channel == 0) { - if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - } else { - PERROR("Invalid byte direction specified.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - PERROR("Invalid byte specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_do_io_single_read(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8200_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_reg); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_do_io_single_write(me_subdevice_t *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me8200_do_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - uint8_t state; - unsigned long status; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock_irqsave(&instance->subdevice_lock, status); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - state = inb(instance->port_reg); - state = - value ? (state | (0x1 << channel)) : (state & - ~(0x1 << - channel)); - outb(state, instance->port_reg); - PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - state); - } else { - PERROR("Invalid bit number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - outb(value, instance->port_reg); - PDEBUG_REG("port_reg outb(0x%lX+0x%lX)=0x%x\n", - instance->reg_base, - instance->port_reg - instance->reg_base, - value); - } else { - PERROR("Invalid byte number specified.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock_irqrestore(&instance->subdevice_lock, status); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8200_do_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 8; - return ME_ERRNO_SUCCESS; -} - -static int me8200_do_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8200_do_query_subdevice_caps(me_subdevice_t *subdevice, int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_OVER_TEMP_IRQ; - return ME_ERRNO_SUCCESS; -} - -static void me8200_do_destructor(struct me_subdevice *subdevice) -{ - me8200_do_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me8200_do_subdevice_t *) subdevice; - - free_irq(instance->irq, (void *)instance); - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static irqreturn_t me8200_do_isr(int irq, void *dev_id) -{ - me8200_do_subdevice_t *instance; - uint16_t ctrl; - uint8_t irq_status; - - instance = (me8200_do_subdevice_t *) dev_id; - - if (irq != instance->irq) { - PERROR("Incorrect interrupt num: %d.\n", irq); - return IRQ_NONE; - } - - irq_status = inb(instance->irq_status_reg); - if (! - (irq_status & - (ME8200_DO_IRQ_STATUS_BIT_ACTIVE << instance->do_idx))) { - PINFO - ("%ld Shared interrupt. %s(): idx=%d irq_status_reg=0x%04X\n", - jiffies, __func__, instance->do_idx, irq_status); - return IRQ_NONE; - } - - PDEBUG("executed.\n"); - - spin_lock(&instance->subdevice_lock); - instance->rised = 1; - instance->count++; - - spin_lock(instance->irq_mode_lock); - ctrl = inw(instance->irq_ctrl_reg); - ctrl |= ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx; - outw(ctrl, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, ctrl); - ctrl &= ~(ME8200_IRQ_MODE_BIT_CLEAR_POWER << instance->do_idx); - outw(ctrl, instance->irq_ctrl_reg); - PDEBUG_REG("irq_ctrl_reg outw(0x%lX+0x%lX)=0x%x\n", instance->reg_base, - instance->irq_ctrl_reg - instance->reg_base, ctrl); - spin_unlock(instance->irq_mode_lock); - spin_unlock(&instance->subdevice_lock); - wake_up_interruptible_all(&instance->wait_queue); - - return IRQ_HANDLED; -} - -me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base, - unsigned int do_idx, - int irq, - spinlock_t *irq_mode_lock) -{ - me8200_do_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8200_do_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8200_do_subdevice_t)); - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->irq_mode_lock = irq_mode_lock; - - /* Save the index of the digital output */ - subdevice->do_idx = do_idx; - subdevice->irq = irq; - - /* Initialize the registers */ - if (do_idx == 0) { - subdevice->port_reg = reg_base + ME8200_DO_PORT_0_REG; - } else if (do_idx == 1) { - subdevice->port_reg = reg_base + ME8200_DO_PORT_1_REG; - } else { - PERROR("Wrong subdevice idx=%d.\n", do_idx); - kfree(subdevice); - return NULL; - } - subdevice->irq_ctrl_reg = reg_base + ME8200_IRQ_MODE_REG; - subdevice->irq_status_reg = reg_base + ME8200_DO_IRQ_STATUS_REG; -#ifdef MEDEBUG_DEBUG_REG - subdevice->reg_base = reg_base; -#endif - - /* Initialize the wait queue */ - init_waitqueue_head(&subdevice->wait_queue); - - /* Request the interrupt line */ - err = request_irq(irq, me8200_do_isr, - IRQF_DISABLED | IRQF_SHARED, - ME8200_NAME, (void *)subdevice); - - if (err) { - PERROR("Cannot get interrupt line.\n"); - kfree(subdevice); - return NULL; - } - PINFO("Registered irq=%d.\n", irq); - - /* Overload base class methods. */ - subdevice->base.me_subdevice_io_irq_start = me8200_do_io_irq_start; - subdevice->base.me_subdevice_io_irq_wait = me8200_do_io_irq_wait; - subdevice->base.me_subdevice_io_irq_stop = me8200_do_io_irq_stop; - subdevice->base.me_subdevice_io_reset_subdevice = - me8200_do_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = - me8200_do_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8200_do_io_single_read; - subdevice->base.me_subdevice_io_single_write = - me8200_do_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me8200_do_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8200_do_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8200_do_query_subdevice_caps; - subdevice->base.me_subdevice_destructor = me8200_do_destructor; - - subdevice->rised = 0; - subdevice->count = 0; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8200_do.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file me8200_do.h - * - * @brief ME-8200 digital output subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DO_H_ -#define _ME8200_DO_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The template subdevice class. - */ -typedef struct me8200_do_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *irq_mode_lock; - - int irq; /**< The number of the interrupt request */ - int rised; /**< Flag to indicate if an interrupt occured */ - int count; /**< Counts the number of interrupts occured */ - wait_queue_head_t wait_queue; /**< To wait on interrupts */ - - unsigned int do_idx; /**< The number of the digital output */ - - unsigned long port_reg; /**< The digital output port */ - unsigned long irq_ctrl_reg; /**< The interrupt control register */ - unsigned long irq_status_reg; /**< The interrupt status register */ -#ifdef MEDEBUG_DEBUG_REG - unsigned long reg_base; -#endif -} me8200_do_subdevice_t; - -/** - * @brief The constructor to generate a ME-8200 digital output subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param do_idx The index of the digital output subdevice on this device. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8200_do_subdevice_t *me8200_do_constructor(uint32_t reg_base, - unsigned int do_idx, - int irq, - spinlock_t * irq_mode_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_do_reg.h +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file me8200_ao_reg.h - * - * @brief ME-8200 analog output subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_DO_REG_H_ -#define _ME8200_DO_REG_H_ - -#ifdef __KERNEL__ - -#define ME8200_DO_IRQ_STATUS_REG 0x0 // R -#define ME8200_DO_PORT_0_REG 0x1 // R/W -#define ME8200_DO_PORT_1_REG 0x2 // R/W - -#define ME8200_DO_IRQ_STATUS_BIT_ACTIVE 0x1 -#define ME8200_DO_IRQ_STATUS_SHIFT 1 - -#endif -#endif --- a/drivers/staging/meilhaus/me8200_reg.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @file me8200_reg.h - * - * @brief ME-8200 register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8200_REG_H_ -#define _ME8200_REG_H_ - -#ifdef __KERNEL__ - -#define ME8200_IRQ_MODE_REG 0xD // R/W - -#define ME8200_IRQ_MODE_MASK 0x3 - -#define ME8200_IRQ_MODE_MASK_MASK 0x0 -#define ME8200_IRQ_MODE_MASK_COMPARE 0x1 - -#define ME8200_IRQ_MODE_BIT_ENABLE_POWER 0x10 -#define ME8200_IRQ_MODE_BIT_CLEAR_POWER 0x40 - -#define ME8200_IRQ_MODE_DI_SHIFT 2 -#define ME8200_IRQ_MODE_POWER_SHIFT 1 - -#endif -#endif --- a/drivers/staging/meilhaus/me8254.c +++ /dev/null @@ -1,1176 +0,0 @@ -/** - * @file me8254.c - * - * @brief 8254 subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "me8254_reg.h" -#include "me8254.h" - -/* - * Defines - */ -#define ME8254_NUMBER_CHANNELS 1 /**< One channel per counter. */ -#define ME8254_CTR_WIDTH 16 /**< One counter has 16 bits. */ - -/* - * Functions - */ - -static int me8254_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8254_subdevice_t *instance; - uint8_t clk_src; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8254_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - if (instance->ctr_idx == 0) - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - else if (instance->ctr_idx == 1) - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - else - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - spin_unlock(instance->ctrl_reg_lock); - - outb(0x00, instance->val_reg); - outb(0x00, instance->val_reg); - - spin_lock(instance->clk_src_reg_lock); - clk_src = inb(instance->clk_src_reg); - - switch (instance->device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME1400: - case PCI_DEVICE_ID_MEILHAUS_ME140A: - case PCI_DEVICE_ID_MEILHAUS_ME140B: - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - if (instance->me8254_idx == 0) { - if (instance->ctr_idx == 0) - clk_src &= - ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ | - ME1400AB_8254_A_0_CLK_SRC_QUARZ); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV); - else - clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV); - } else { - if (instance->ctr_idx == 0) - clk_src &= - ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ | - ME1400AB_8254_B_0_CLK_SRC_QUARZ); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV); - else - clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV); - } - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - case PCI_DEVICE_ID_MEILHAUS_ME140D: - switch (instance->me8254_idx) { - case 0: - case 2: - case 4: - case 6: - case 8: - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); - else - clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); - break; - - default: - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); - else - clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); - break; - } - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - case PCI_DEVICE_ID_MEILHAUS_ME4660: - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - case PCI_DEVICE_ID_MEILHAUS_ME4660S: - case PCI_DEVICE_ID_MEILHAUS_ME4660IS: - case PCI_DEVICE_ID_MEILHAUS_ME4670: - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - case PCI_DEVICE_ID_MEILHAUS_ME4680: - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - - /* No clock source register available */ - break; - - default: - PERROR("Invalid device type.\n"); - err = ME_ERRNO_INTERNAL; - } - - if (!err) - outb(clk_src, instance->clk_src_reg); - - spin_unlock(instance->clk_src_reg_lock); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me1400_ab_ref_config(me8254_subdevice_t *instance, int ref) -{ - uint8_t clk_src; - - spin_lock(instance->clk_src_reg_lock); - clk_src = inb(instance->clk_src_reg); - - switch (ref) { - case ME_REF_CTR_EXTERNAL: - if (instance->me8254_idx == 0) { - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_QUARZ); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400AB_8254_A_1_CLK_SRC_PREV); - else - clk_src &= ~(ME1400AB_8254_A_2_CLK_SRC_PREV); - } else { - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_QUARZ); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400AB_8254_B_1_CLK_SRC_PREV); - else - clk_src &= ~(ME1400AB_8254_B_2_CLK_SRC_PREV); - } - - break; - - case ME_REF_CTR_PREVIOUS: - if (instance->me8254_idx == 0) { - if (instance->ctr_idx == 0) { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } else if (instance->ctr_idx == 1) - clk_src |= (ME1400AB_8254_A_1_CLK_SRC_PREV); - else - clk_src |= (ME1400AB_8254_A_2_CLK_SRC_PREV); - } else { - if (instance->ctr_idx == 0) { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } else if (instance->ctr_idx == 1) - clk_src |= (ME1400AB_8254_B_1_CLK_SRC_PREV); - else - clk_src |= (ME1400AB_8254_B_2_CLK_SRC_PREV); - } - - break; - - case ME_REF_CTR_INTERNAL_1MHZ: - if (instance->me8254_idx == 0) { - if (instance->ctr_idx == 0) { - clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); - clk_src &= ~(ME1400AB_8254_A_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - if (instance->ctr_idx == 0) { - clk_src |= (ME1400AB_8254_B_0_CLK_SRC_QUARZ); - clk_src &= ~(ME1400AB_8254_B_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } - - break; - - case ME_REF_CTR_INTERNAL_10MHZ: - if (instance->me8254_idx == 0) { - if (instance->ctr_idx == 0) { - clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); - clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - if (instance->ctr_idx == 0) { - clk_src |= (ME1400AB_8254_A_0_CLK_SRC_QUARZ); - clk_src |= (ME1400AB_8254_A_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } - - break; - - default: - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - outb(clk_src, instance->clk_src_reg); - spin_unlock(instance->clk_src_reg_lock); - - return ME_ERRNO_SUCCESS; -} - -static int me1400_cd_ref_config(me8254_subdevice_t *instance, int ref) -{ - uint8_t clk_src; - - spin_lock(instance->clk_src_reg_lock); - clk_src = inb(instance->clk_src_reg); - - switch (ref) { - case ME_REF_CTR_EXTERNAL: - switch (instance->me8254_idx) { - case 0: - case 2: - case 4: - case 6: - case 8: - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); - else - clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); - break; - - default: - if (instance->ctr_idx == 0) - clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); - else if (instance->ctr_idx == 1) - clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); - else - clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); - break; - } - break; - - case ME_REF_CTR_PREVIOUS: - switch (instance->me8254_idx) { - case 0: - case 2: - case 4: - case 6: - case 8: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_PREV); - } else if (instance->ctr_idx == 1) { - clk_src &= ~(ME1400CD_8254_ACE_1_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_ACE_1_CLK_SRC_PREV); - } else { - clk_src &= ~(ME1400CD_8254_ACE_2_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_ACE_2_CLK_SRC_PREV); - } - break; - - default: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_PREV); - } else if (instance->ctr_idx == 1) { - clk_src &= ~(ME1400CD_8254_BD_1_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_BD_1_CLK_SRC_PREV); - } else { - clk_src &= ~(ME1400CD_8254_BD_2_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_BD_2_CLK_SRC_PREV); - } - break; - } - - break; - - case ME_REF_CTR_INTERNAL_1MHZ: - switch (instance->me8254_idx) { - case 0: - case 2: - case 4: - case 6: - case 8: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_1MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - break; - - default: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_1MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - break; - } - - break; - - case ME_REF_CTR_INTERNAL_10MHZ: - switch (instance->me8254_idx) { - case 0: - case 2: - case 4: - case 6: - case 8: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_ACE_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_ACE_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - break; - - default: - if (instance->ctr_idx == 0) { - clk_src &= ~(ME1400CD_8254_BD_0_CLK_SRC_MASK); - clk_src |= (ME1400CD_8254_BD_0_CLK_SRC_10MHZ); - } else { - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - break; - } - - break; - - default: - PERROR("Invalid reference.\n"); - spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - outb(clk_src, instance->clk_src_reg); - spin_unlock(instance->clk_src_reg_lock); - - return ME_ERRNO_SUCCESS; -} - -static int me4600_ref_config(me8254_subdevice_t *instance, int ref) -{ - switch (ref) { - - case ME_REF_CTR_EXTERNAL: - // Nothing to do - break; - - default: - PERROR("Invalid reference.\n"); -// spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - return ME_ERRNO_SUCCESS; -} - -static int me8100_ref_config(me8254_subdevice_t *instance, int ref) -{ - switch (ref) { - - case ME_REF_CTR_EXTERNAL: - // Nothing to do - break; - - default: - PERROR("Invalid reference.\n"); -// spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_REF; - } - - return ME_ERRNO_SUCCESS; -} - -static int me8254_io_single_config(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8254_subdevice_t *instance; - int err; - - PDEBUG("executed.\n"); - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - instance = (me8254_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - // Configure the counter modes - if (instance->ctr_idx == 0) { - if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M1 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M2 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M3 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M4 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { - outb(ME8254_CTRL_SC0 | ME8254_CTRL_LM | ME8254_CTRL_M5 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else { - PERROR("Invalid single configuration.\n"); - spin_unlock(&instance->subdevice_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else if (instance->ctr_idx == 1) { - if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M1 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M2 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M3 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M4 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { - outb(ME8254_CTRL_SC1 | ME8254_CTRL_LM | ME8254_CTRL_M5 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else { - PERROR("Invalid single configuration.\n"); - spin_unlock(&instance->subdevice_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } else { - if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_0) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M0 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_1) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M1 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_2) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M2 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_3) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M3 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_4) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M4 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else if (single_config == ME_SINGLE_CONFIG_CTR_8254_MODE_5) { - outb(ME8254_CTRL_SC2 | ME8254_CTRL_LM | ME8254_CTRL_M5 | - ME8254_CTRL_BIN, instance->ctrl_reg); - } else { - PERROR("Invalid single configuration.\n"); - spin_unlock(&instance->subdevice_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - } - - switch (instance->device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME1400: - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - case PCI_DEVICE_ID_MEILHAUS_ME140A: - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - case PCI_DEVICE_ID_MEILHAUS_ME140B: - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - err = me1400_ab_ref_config(instance, ref); - - if (err) { - spin_unlock(&instance->subdevice_lock); - return err; - } - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - case PCI_DEVICE_ID_MEILHAUS_ME140D: - err = me1400_cd_ref_config(instance, ref); - - if (err) { - spin_unlock(&instance->subdevice_lock); - return err; - } - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - case PCI_DEVICE_ID_MEILHAUS_ME4660: - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - case PCI_DEVICE_ID_MEILHAUS_ME4660S: - case PCI_DEVICE_ID_MEILHAUS_ME4660IS: - case PCI_DEVICE_ID_MEILHAUS_ME4670: - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - case PCI_DEVICE_ID_MEILHAUS_ME4680: - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - err = me4600_ref_config(instance, ref); - - if (err) { - spin_unlock(&instance->subdevice_lock); - return err; - } - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - err = me8100_ref_config(instance, ref); - - if (err) { - spin_unlock(&instance->subdevice_lock); - return err; - } - - break; - - default: - PERROR("Invalid device type.\n"); - - spin_unlock(&instance->subdevice_lock); -// spin_unlock(instance->clk_src_reg_lock); - return ME_ERRNO_INVALID_SINGLE_CONFIG; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8254_io_single_read(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8254_subdevice_t *instance; - uint16_t lo_byte; - uint16_t hi_byte; - - PDEBUG("executed.\n"); - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - instance = (me8254_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - if (instance->ctr_idx == 0) - outb(ME8254_CTRL_SC0 | ME8254_CTRL_TLO, instance->ctrl_reg); - else if (instance->ctr_idx == 1) - outb(ME8254_CTRL_SC1 | ME8254_CTRL_TLO, instance->ctrl_reg); - else - outb(ME8254_CTRL_SC2 | ME8254_CTRL_TLO, instance->ctrl_reg); - - lo_byte = inb(instance->val_reg); - hi_byte = inb(instance->val_reg); - spin_unlock(instance->ctrl_reg_lock); - - *value = lo_byte | (hi_byte << 8); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8254_io_single_write(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me8254_subdevice_t *instance; - - PDEBUG("executed.\n"); - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - instance = (me8254_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - outb(value, instance->val_reg); - outb((value >> 8), instance->val_reg); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8254_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = ME8254_NUMBER_CHANNELS; - return ME_ERRNO_SUCCESS; -} - -static int me8254_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_CTR; - *subtype = ME_SUBTYPE_CTR_8254; - return ME_ERRNO_SUCCESS; -} - -static int me8254_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - me8254_subdevice_t *instance; - PDEBUG("executed.\n"); - instance = (me8254_subdevice_t *) subdevice; - *caps = instance->caps; - return ME_ERRNO_SUCCESS; -} - -static int me8254_query_subdevice_caps_args(struct me_subdevice *subdevice, - int cap, int *args, int count) -{ - PDEBUG("executed.\n"); - - if (count != 1) { - PERROR("Invalid capability argument count.\n"); - return ME_ERRNO_INVALID_CAP_ARG_COUNT; - } - - if (cap == ME_CAP_CTR_WIDTH) { - args[0] = ME8254_CTR_WIDTH; - } else { - PERROR("Invalid capability.\n"); - return ME_ERRNO_INVALID_CAP; - } - - return ME_ERRNO_SUCCESS; -} - -static uint32_t me1400AB_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - - case 0: - return (reg_base + ME1400AB_8254_A_0_VAL_REG + ctr_idx); - - default: - return (reg_base + ME1400AB_8254_B_0_VAL_REG + ctr_idx); - } - - return 0; -} - -static uint32_t me1400AB_get_ctrl_reg(uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - case 0: - return (reg_base + ME1400AB_8254_A_CTRL_REG); - - default: - return (reg_base + ME1400AB_8254_B_CTRL_REG); - } - - return 0; -} - -static uint32_t me1400AB_get_clk_src_reg(uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - case 0: - return (reg_base + ME1400AB_CLK_SRC_REG); - - default: - return (reg_base + ME1400AB_CLK_SRC_REG); - } - - return 0; -} - -static uint32_t me1400CD_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - case 0: - return (reg_base + ME1400C_8254_A_0_VAL_REG + ctr_idx); - - case 1: - return (reg_base + ME1400C_8254_B_0_VAL_REG + ctr_idx); - - case 2: - return (reg_base + ME1400C_8254_C_0_VAL_REG + ctr_idx); - - case 3: - return (reg_base + ME1400C_8254_D_0_VAL_REG + ctr_idx); - - case 4: - return (reg_base + ME1400C_8254_E_0_VAL_REG + ctr_idx); - - case 5: - return (reg_base + ME1400D_8254_A_0_VAL_REG + ctr_idx); - - case 6: - return (reg_base + ME1400D_8254_B_0_VAL_REG + ctr_idx); - - case 7: - return (reg_base + ME1400D_8254_C_0_VAL_REG + ctr_idx); - - case 8: - return (reg_base + ME1400D_8254_D_0_VAL_REG + ctr_idx); - - default: - return (reg_base + ME1400D_8254_E_0_VAL_REG + ctr_idx); - } - - return 0; -} - -static uint32_t me1400CD_get_ctrl_reg(uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - case 0: - return (reg_base + ME1400C_8254_A_CTRL_REG); - - case 1: - return (reg_base + ME1400C_8254_B_CTRL_REG); - - case 2: - return (reg_base + ME1400C_8254_C_CTRL_REG); - - case 3: - return (reg_base + ME1400C_8254_D_CTRL_REG); - - case 4: - return (reg_base + ME1400C_8254_E_CTRL_REG); - - case 5: - return (reg_base + ME1400D_8254_A_CTRL_REG); - - case 6: - return (reg_base + ME1400D_8254_B_CTRL_REG); - - case 7: - return (reg_base + ME1400D_8254_C_CTRL_REG); - - case 8: - return (reg_base + ME1400D_8254_D_CTRL_REG); - - default: - return (reg_base + ME1400D_8254_E_CTRL_REG); - } - - return 0; -} - -static uint32_t me1400CD_get_clk_src_reg(uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx) -{ - switch (me8254_idx) { - case 0: - return (reg_base + ME1400C_CLK_SRC_0_REG); - - case 1: - return (reg_base + ME1400C_CLK_SRC_0_REG); - - case 2: - return (reg_base + ME1400C_CLK_SRC_1_REG); - - case 3: - return (reg_base + ME1400C_CLK_SRC_1_REG); - - case 4: - return (reg_base + ME1400C_CLK_SRC_2_REG); - - case 5: - return (reg_base + ME1400D_CLK_SRC_0_REG); - - case 6: - return (reg_base + ME1400D_CLK_SRC_0_REG); - - case 7: - return (reg_base + ME1400D_CLK_SRC_1_REG); - - case 8: - return (reg_base + ME1400D_CLK_SRC_1_REG); - - default: - return (reg_base + ME1400D_CLK_SRC_2_REG); - } - - return 0; -} - -static uint32_t me4600_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - return (reg_base + ME4600_8254_0_VAL_REG + ctr_idx); -} - -static uint32_t me4600_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - return (reg_base + ME4600_8254_CTRL_REG); -} - -static uint32_t me8100_get_val_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - return (reg_base + ME8100_COUNTER_REG_0 + ctr_idx * 2); -} - -static uint32_t me8100_get_ctrl_reg(uint32_t reg_base, unsigned int me8254_idx, - unsigned int ctr_idx) -{ - return (reg_base + ME8100_COUNTER_CTRL_REG); -} - -me8254_subdevice_t *me8254_constructor(uint32_t device_id, - uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx, - spinlock_t *ctrl_reg_lock, - spinlock_t *clk_src_reg_lock) -{ - me8254_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - // Allocate memory for subdevice instance - subdevice = kmalloc(sizeof(me8254_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for 8254 instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8254_subdevice_t)); - - // Check if counter index is out of range - - if (ctr_idx > 2) { - PERROR("Counter index is out of range.\n"); - kfree(subdevice); - return NULL; - } - // Initialize subdevice base class - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - subdevice->ctrl_reg_lock = ctrl_reg_lock; - subdevice->clk_src_reg_lock = clk_src_reg_lock; - - // Save type of Meilhaus device - subdevice->device_id = device_id; - - // Save the indices - subdevice->me8254_idx = me8254_idx; - subdevice->ctr_idx = ctr_idx; - - // Do device specific initialization - switch (device_id) { - - case PCI_DEVICE_ID_MEILHAUS_ME140A: - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - // Check if 8254 index is out of range - if (me8254_idx > 0) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - case PCI_DEVICE_ID_MEILHAUS_ME140B: // Fall through - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - // Check if 8254 index is out of range - if (me8254_idx > 1) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - // Initialize the counters capabilities - if (ctr_idx == 0) - subdevice->caps = - ME_CAPS_CTR_CLK_INTERNAL_1MHZ | - ME_CAPS_CTR_CLK_INTERNAL_10MHZ | - ME_CAPS_CTR_CLK_EXTERNAL; - else - subdevice->caps = - ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL; - - // Get the counters registers - subdevice->val_reg = - me1400AB_get_val_reg(reg_base, me8254_idx, ctr_idx); - subdevice->ctrl_reg = - me1400AB_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); - subdevice->clk_src_reg = - me1400AB_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - // Check if 8254 index is out of range - if (me8254_idx > 4) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - case PCI_DEVICE_ID_MEILHAUS_ME140D: - // Check if 8254 index is out of range - if (me8254_idx > 9) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - // Initialize the counters capabilities - if (ctr_idx == 0) { - if (me8254_idx == 0) - subdevice->caps = - ME_CAPS_CTR_CLK_PREVIOUS | - ME_CAPS_CTR_CLK_INTERNAL_1MHZ | - ME_CAPS_CTR_CLK_INTERNAL_10MHZ | - ME_CAPS_CTR_CLK_EXTERNAL; - else - subdevice->caps = - ME_CAPS_CTR_CLK_INTERNAL_1MHZ | - ME_CAPS_CTR_CLK_INTERNAL_10MHZ | - ME_CAPS_CTR_CLK_EXTERNAL; - } else - subdevice->caps = - ME_CAPS_CTR_CLK_PREVIOUS | ME_CAPS_CTR_CLK_EXTERNAL; - - // Get the counters registers - subdevice->val_reg = - me1400CD_get_val_reg(reg_base, me8254_idx, ctr_idx); - subdevice->ctrl_reg = - me1400CD_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); - subdevice->clk_src_reg = - me1400CD_get_clk_src_reg(reg_base, me8254_idx, ctr_idx); - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - case PCI_DEVICE_ID_MEILHAUS_ME4660: - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - case PCI_DEVICE_ID_MEILHAUS_ME4660S: - case PCI_DEVICE_ID_MEILHAUS_ME4660IS: - case PCI_DEVICE_ID_MEILHAUS_ME4670: - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - case PCI_DEVICE_ID_MEILHAUS_ME4680: - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - // Check if 8254 index is out of range - if (me8254_idx > 0) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - // Initialize the counters capabilities - subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; - - // Get the counters registers - subdevice->val_reg = - me4600_get_val_reg(reg_base, me8254_idx, ctr_idx); - subdevice->ctrl_reg = - me4600_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); - subdevice->clk_src_reg = 0; // Not used - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - // Check if 8254 index is out of range - if (me8254_idx > 0) { - PERROR("8254 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - // Initialize the counters capabilities - subdevice->caps = ME_CAPS_CTR_CLK_EXTERNAL; - - // Get the counters registers - subdevice->val_reg = - me8100_get_val_reg(reg_base, me8254_idx, ctr_idx); - subdevice->ctrl_reg = - me8100_get_ctrl_reg(reg_base, me8254_idx, ctr_idx); - subdevice->clk_src_reg = 0; // Not used - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4650: - case PCI_DEVICE_ID_MEILHAUS_ME1400: - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - PERROR("No 8254 subdevices available for subdevice device.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - - default: - PERROR("Unknown device type.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - // Overload subdevice base class methods. - subdevice->base.me_subdevice_io_reset_subdevice = - me8254_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = me8254_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8254_io_single_read; - subdevice->base.me_subdevice_io_single_write = me8254_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me8254_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8254_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8254_query_subdevice_caps; - subdevice->base.me_subdevice_query_subdevice_caps_args = - me8254_query_subdevice_caps_args; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8254.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file me8254.h - * - * @brief 8254 counter implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _ME8254_H_ -#define _ME8254_H_ - -#include "mesubdevice.h" -#include "meslock.h" - -#ifdef __KERNEL__ - -/** - * @brief The 8254 subdevice class. - */ -typedef struct me8254_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect the control register from concurrent access. */ - spinlock_t *clk_src_reg_lock; /**< Spin lock to protect the clock source register from concurrent access. */ - - uint32_t device_id; /**< The Meilhaus device type carrying the 8254 chip. */ - int me8254_idx; /**< The index of the 8254 chip on the device. */ - int ctr_idx; /**< The index of the counter on the 8254 chip. */ - - int caps; /**< Holds the device capabilities. */ - - unsigned long val_reg; /**< Holds the actual counter value. */ - unsigned long ctrl_reg; /**< Register to configure the 8254 modes. */ - unsigned long clk_src_reg; /**< Register to configure the counter connections. */ -} me8254_subdevice_t; - -/** - * @brief The constructor to generate a 8254 instance. - * - * @param device_id The kind of Meilhaus device holding the 8254. - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param me8254_idx The index of the 8254 chip on the Meilhaus device. - * @param ctr_idx The index of the counter inside a 8254 chip. - * @param ctrl_reg_lock Pointer to spin lock protecting the 8254 control register from concurrent access. - * @param clk_src_reg_lock Pointer to spin lock protecting the clock source register from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8254_subdevice_t *me8254_constructor(uint32_t device_id, - uint32_t reg_base, - unsigned int me8254_idx, - unsigned int ctr_idx, - spinlock_t * ctrl_reg_lock, - spinlock_t * clk_src_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8254_reg.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @file me8254_reg.h - * - * @brief 8254 counter register definitions. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME8254_REG_H_ -#define _ME8254_REG_H_ - -#ifdef __KERNEL__ - -/* ME1400 A/B register offsets */ -#define ME1400AB_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400AB_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 1 value register. */ -#define ME1400AB_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 2 value register. */ -#define ME1400AB_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */ - -#define ME1400AB_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */ -#define ME1400AB_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 1 value register. */ -#define ME1400AB_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 2 value register. */ -#define ME1400AB_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */ - -#define ME1400AB_CLK_SRC_REG 0x0010 /**< Offset of clock source register. */ - -/* ME1400 C register offsets */ -#define ME1400C_8254_A_0_VAL_REG 0x0004 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400C_8254_A_1_VAL_REG 0x0005 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400C_8254_A_2_VAL_REG 0x0006 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400C_8254_A_CTRL_REG 0x0007 /**< Offset of 8254 A control register. */ - -#define ME1400C_8254_B_0_VAL_REG 0x000C /**< Offset of 8254 B counter 0 value register. */ -#define ME1400C_8254_B_1_VAL_REG 0x000D /**< Offset of 8254 B counter 0 value register. */ -#define ME1400C_8254_B_2_VAL_REG 0x000E /**< Offset of 8254 B counter 0 value register. */ -#define ME1400C_8254_B_CTRL_REG 0x000F /**< Offset of 8254 B control register. */ - -#define ME1400C_8254_C_0_VAL_REG 0x0010 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400C_8254_C_1_VAL_REG 0x0011 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400C_8254_C_2_VAL_REG 0x0012 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400C_8254_C_CTRL_REG 0x0013 /**< Offset of 8254 C control register. */ - -#define ME1400C_8254_D_0_VAL_REG 0x0014 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400C_8254_D_1_VAL_REG 0x0015 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400C_8254_D_2_VAL_REG 0x0016 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400C_8254_D_CTRL_REG 0x0017 /**< Offset of 8254 D control register. */ - -#define ME1400C_8254_E_0_VAL_REG 0x0018 /**< Offset of 8254 E counter 0 value register. */ -#define ME1400C_8254_E_1_VAL_REG 0x0019 /**< Offset of 8254 E counter 0 value register. */ -#define ME1400C_8254_E_2_VAL_REG 0x001A /**< Offset of 8254 E counter 0 value register. */ -#define ME1400C_8254_E_CTRL_REG 0x001B /**< Offset of 8254 E control register. */ - -#define ME1400C_CLK_SRC_0_REG 0x001C /**< Offset of clock source register 0. */ -#define ME1400C_CLK_SRC_1_REG 0x001D /**< Offset of clock source register 1. */ -#define ME1400C_CLK_SRC_2_REG 0x001E /**< Offset of clock source register 2. */ - -/* ME1400 D register offsets */ -#define ME1400D_8254_A_0_VAL_REG 0x0044 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400D_8254_A_1_VAL_REG 0x0045 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400D_8254_A_2_VAL_REG 0x0046 /**< Offset of 8254 A counter 0 value register. */ -#define ME1400D_8254_A_CTRL_REG 0x0047 /**< Offset of 8254 A control register. */ - -#define ME1400D_8254_B_0_VAL_REG 0x004C /**< Offset of 8254 B counter 0 value register. */ -#define ME1400D_8254_B_1_VAL_REG 0x004D /**< Offset of 8254 B counter 0 value register. */ -#define ME1400D_8254_B_2_VAL_REG 0x004E /**< Offset of 8254 B counter 0 value register. */ -#define ME1400D_8254_B_CTRL_REG 0x004F /**< Offset of 8254 B control register. */ - -#define ME1400D_8254_C_0_VAL_REG 0x0050 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400D_8254_C_1_VAL_REG 0x0051 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400D_8254_C_2_VAL_REG 0x0052 /**< Offset of 8254 C counter 0 value register. */ -#define ME1400D_8254_C_CTRL_REG 0x0053 /**< Offset of 8254 C control register. */ - -#define ME1400D_8254_D_0_VAL_REG 0x0054 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400D_8254_D_1_VAL_REG 0x0055 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400D_8254_D_2_VAL_REG 0x0056 /**< Offset of 8254 D counter 0 value register. */ -#define ME1400D_8254_D_CTRL_REG 0x0057 /**< Offset of 8254 D control register. */ - -#define ME1400D_8254_E_0_VAL_REG 0x0058 /**< Offset of 8254 E counter 0 value register. */ -#define ME1400D_8254_E_1_VAL_REG 0x0059 /**< Offset of 8254 E counter 0 value register. */ -#define ME1400D_8254_E_2_VAL_REG 0x005A /**< Offset of 8254 E counter 0 value register. */ -#define ME1400D_8254_E_CTRL_REG 0x005B /**< Offset of 8254 E control register. */ - -#define ME1400D_CLK_SRC_0_REG 0x005C /**< Offset of clock source register 0. */ -#define ME1400D_CLK_SRC_1_REG 0x005D /**< Offset of clock source register 1. */ -#define ME1400D_CLK_SRC_2_REG 0x005E /**< Offset of clock source register 2. */ - -/* ME4600 register offsets */ -#define ME4600_8254_0_VAL_REG 0x0000 /**< Offset of 8254 A counter 0 value register. */ -#define ME4600_8254_1_VAL_REG 0x0001 /**< Offset of 8254 A counter 0 value register. */ -#define ME4600_8254_2_VAL_REG 0x0002 /**< Offset of 8254 A counter 0 value register. */ -#define ME4600_8254_CTRL_REG 0x0003 /**< Offset of 8254 A control register. */ - -/* Command words for 8254 control register */ -#define ME8254_CTRL_SC0 0x00 /**< Counter 0 selection. */ -#define ME8254_CTRL_SC1 0x40 /**< Counter 1 selection. */ -#define ME8254_CTRL_SC2 0x80 /**< Counter 2 selection. */ - -#define ME8254_CTRL_TLO 0x00 /**< Counter latching operation. */ -#define ME8254_CTRL_LSB 0x10 /**< Only read LSB. */ -#define ME8254_CTRL_MSB 0x20 /**< Only read MSB. */ -#define ME8254_CTRL_LM 0x30 /**< First read LSB, then MSB. */ - -#define ME8254_CTRL_M0 0x00 /**< Mode 0 selection. */ -#define ME8254_CTRL_M1 0x02 /**< Mode 1 selection. */ -#define ME8254_CTRL_M2 0x04 /**< Mode 2 selection. */ -#define ME8254_CTRL_M3 0x06 /**< Mode 3 selection. */ -#define ME8254_CTRL_M4 0x08 /**< Mode 4 selection. */ -#define ME8254_CTRL_M5 0x0A /**< Mode 5 selection. */ - -#define ME8254_CTRL_BIN 0x00 /**< Binary counter. */ -#define ME8254_CTRL_BCD 0x01 /**< BCD counter. */ - -/* ME-1400 A/B clock source register bits */ -#define ME1400AB_8254_A_0_CLK_SRC_1MHZ (0 << 7) /**< 1MHz clock. */ -#define ME1400AB_8254_A_0_CLK_SRC_10MHZ (1 << 7) /**< 10MHz clock. */ -#define ME1400AB_8254_A_0_CLK_SRC_PIN (0 << 6) /**< CLK 0 to SUB-D. */ -#define ME1400AB_8254_A_0_CLK_SRC_QUARZ (1 << 6) /**< Connect CLK 0 with quarz. */ - -#define ME1400AB_8254_A_1_CLK_SRC_PIN (0 << 5) /**< CLK 1 to SUB-D. */ -#define ME1400AB_8254_A_1_CLK_SRC_PREV (1 << 5) /**< Connect OUT 0 with CLK 1. */ - -#define ME1400AB_8254_A_2_CLK_SRC_PIN (0 << 4) /**< CLK 2 to SUB-D. */ -#define ME1400AB_8254_A_2_CLK_SRC_PREV (1 << 4) /**< Connect OUT 1 with CLK 2. */ - -#define ME1400AB_8254_B_0_CLK_SRC_1MHZ (0 << 3) /**< 1MHz clock. */ -#define ME1400AB_8254_B_0_CLK_SRC_10MHZ (1 << 3) /**< 10MHz clock. */ -#define ME1400AB_8254_B_0_CLK_SRC_PIN (0 << 2) /**< CLK 0 to SUB-D. */ -#define ME1400AB_8254_B_0_CLK_SRC_QUARZ (1 << 2) /**< Connect CLK 0 with quarz. */ - -#define ME1400AB_8254_B_1_CLK_SRC_PIN (0 << 1) /**< CLK 1 to SUB-D. */ -#define ME1400AB_8254_B_1_CLK_SRC_PREV (1 << 1) /**< Connect OUT 0 with CLK 1. */ - -#define ME1400AB_8254_B_2_CLK_SRC_PIN (0 << 0) /**< CLK 2 to SUB-D. */ -#define ME1400AB_8254_B_2_CLK_SRC_PREV (1 << 0) /**< Connect OUT 1 with CLK 2. */ - -/* ME-1400 C/D clock source registers bits */ -#define ME1400CD_8254_ACE_0_CLK_SRC_MASK 0x03 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_ACE_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ -#define ME1400CD_8254_ACE_0_CLK_SRC_1MHZ 0x01 /**< Connect CLK to 1MHz. */ -#define ME1400CD_8254_ACE_0_CLK_SRC_10MHZ 0x02 /**< Connect CLK to 10MHz. */ -#define ME1400CD_8254_ACE_0_CLK_SRC_PREV 0x03 /**< Connect CLK to previous counter output on ME-1400 D extension. */ - -#define ME1400CD_8254_ACE_1_CLK_SRC_MASK 0x04 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_ACE_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ -#define ME1400CD_8254_ACE_1_CLK_SRC_PREV 0x04 /**< Connect CLK to previous counter output. */ - -#define ME1400CD_8254_ACE_2_CLK_SRC_MASK 0x08 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_ACE_2_CLK_SRC_PIN 0x00 /**< Connect to SUB-D. */ -#define ME1400CD_8254_ACE_2_CLK_SRC_PREV 0x08 /**< Connect CLK to previous counter output. */ - -#define ME1400CD_8254_BD_0_CLK_SRC_MASK 0x30 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_BD_0_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ -#define ME1400CD_8254_BD_0_CLK_SRC_1MHZ 0x10 /**< Connect CLK to 1MHz. */ -#define ME1400CD_8254_BD_0_CLK_SRC_10MHZ 0x20 /**< Connect CLK to 10MHz. */ -#define ME1400CD_8254_BD_0_CLK_SRC_PREV 0x30 /**< Connect CLK to previous counter output. */ - -#define ME1400CD_8254_BD_1_CLK_SRC_MASK 0x40 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_BD_1_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ -#define ME1400CD_8254_BD_1_CLK_SRC_PREV 0x40 /**< Connect CLK to previous counter output. */ - -#define ME1400CD_8254_BD_2_CLK_SRC_MASK 0x80 /**< Masks all CLK source bits. */ -#define ME1400CD_8254_BD_2_CLK_SRC_PIN 0x00 /**< Connect CLK to SUB-D. */ -#define ME1400CD_8254_BD_2_CLK_SRC_PREV 0x80 /**< Connect CLK to previous counter output. */ - -/* ME-8100 counter registers */ -#define ME8100_COUNTER_REG_0 0x18 //(r,w) -#define ME8100_COUNTER_REG_1 0x1A //(r,w) -#define ME8100_COUNTER_REG_2 0x1C //(r,w) -#define ME8100_COUNTER_CTRL_REG 0x1E //(r,w) - -#endif -#endif --- a/drivers/staging/meilhaus/me8255.c +++ /dev/null @@ -1,462 +0,0 @@ -/** - * @file me8255.c - * - * @brief 8255 subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" -#include "medebug.h" - -#include "me8255_reg.h" -#include "me8255.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static uint8_t get_mode_from_mirror(uint32_t mirror) -{ - PDEBUG("executed.\n"); - - if (mirror & ME8255_PORT_0_OUTPUT) { - if (mirror & ME8255_PORT_1_OUTPUT) { - if (mirror & ME8255_PORT_2_OUTPUT) { - return ME8255_MODE_OOO; - } else { - return ME8255_MODE_IOO; - } - } else { - if (mirror & ME8255_PORT_2_OUTPUT) { - return ME8255_MODE_OIO; - } else { - return ME8255_MODE_IIO; - } - } - } else { - if (mirror & ME8255_PORT_1_OUTPUT) { - if (mirror & ME8255_PORT_2_OUTPUT) { - return ME8255_MODE_OOI; - } else { - return ME8255_MODE_IOI; - } - } else { - if (mirror & ME8255_PORT_2_OUTPUT) { - return ME8255_MODE_OII; - } else { - return ME8255_MODE_III; - } - } - } -} - -static int me8255_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - me8255_subdevice_t *instance; - - PDEBUG("executed.\n"); - - instance = (me8255_subdevice_t *) subdevice; - - if (flags) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - spin_lock(instance->ctrl_reg_lock); - *instance->ctrl_reg_mirror &= - ~(ME8255_PORT_0_OUTPUT << instance->dio_idx); - outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), - instance->ctrl_reg); - spin_unlock(instance->ctrl_reg_lock); - - outb(0, instance->port_reg); - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return ME_ERRNO_SUCCESS; -} - -static int me8255_io_single_config(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - me8255_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8255_subdevice_t *) subdevice; - - if (flags & ~ME_IO_SINGLE_CONFIG_DIO_BYTE) { - PERROR("Invalid flag specified.\n"); - return ME_ERRNO_INVALID_FLAGS; - } - - if (channel) { - PERROR("Invalid channel.\n"); - return ME_ERRNO_INVALID_CHANNEL; - } - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - if (single_config == ME_SINGLE_CONFIG_DIO_INPUT) { - spin_lock(instance->ctrl_reg_lock); - *instance->ctrl_reg_mirror &= - ~(ME8255_PORT_0_OUTPUT << instance->dio_idx); - outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), - instance->ctrl_reg); - spin_unlock(instance->ctrl_reg_lock); - } else if (single_config == ME_SINGLE_CONFIG_DIO_OUTPUT) { - spin_lock(instance->ctrl_reg_lock); - *instance->ctrl_reg_mirror |= - (ME8255_PORT_0_OUTPUT << instance->dio_idx); - outb(get_mode_from_mirror(*instance->ctrl_reg_mirror), - instance->ctrl_reg); - spin_unlock(instance->ctrl_reg_lock); - } else { - PERROR("Invalid port direction.\n"); - err = ME_ERRNO_INVALID_SINGLE_CONFIG; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8255_io_single_read(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - me8255_subdevice_t *instance; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8255_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - *value = inb(instance->port_reg) & (0x1 << channel); - } else { - PERROR("Invalid bit number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - *value = inb(instance->port_reg); - } else { - PERROR("Invalid byte number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8255_io_single_write(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - me8255_subdevice_t *instance; - uint8_t byte; - int err = ME_ERRNO_SUCCESS; - - PDEBUG("executed.\n"); - - instance = (me8255_subdevice_t *) subdevice; - - ME_SUBDEVICE_ENTER; - - spin_lock(&instance->subdevice_lock); - switch (flags) { - case ME_IO_SINGLE_TYPE_DIO_BIT: - if ((channel >= 0) && (channel < 8)) { - if (*instance-> - ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT << - instance->dio_idx)) { - byte = inb(instance->port_reg); - - if (value) - byte |= 0x1 << channel; - else - byte &= ~(0x1 << channel); - - outb(byte, instance->port_reg); - } else { - PERROR("Port not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid bit number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - case ME_IO_SINGLE_NO_FLAGS: - case ME_IO_SINGLE_TYPE_DIO_BYTE: - if (channel == 0) { - if (*instance-> - ctrl_reg_mirror & (ME8255_PORT_0_OUTPUT << - instance->dio_idx)) { - outb(value, instance->port_reg); - } else { - PERROR("Port not in output mode.\n"); - err = ME_ERRNO_PREVIOUS_CONFIG; - } - } else { - PERROR("Invalid byte number.\n"); - err = ME_ERRNO_INVALID_CHANNEL; - } - break; - - default: - PERROR("Invalid flags specified.\n"); - err = ME_ERRNO_INVALID_FLAGS; - } - spin_unlock(&instance->subdevice_lock); - - ME_SUBDEVICE_EXIT; - - return err; -} - -static int me8255_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = ME8255_NUMBER_CHANNELS; - return ME_ERRNO_SUCCESS; -} - -static int me8255_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = ME_TYPE_DIO; - *subtype = ME_SUBTYPE_SINGLE; - return ME_ERRNO_SUCCESS; -} - -static int me8255_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = ME_CAPS_DIO_DIR_BYTE; - return ME_ERRNO_SUCCESS; -} - -me8255_subdevice_t *me8255_constructor(uint32_t device_id, - uint32_t reg_base, - unsigned int me8255_idx, - unsigned int dio_idx, - int *ctrl_reg_mirror, - spinlock_t *ctrl_reg_lock) -{ - me8255_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(me8255_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for 8255 instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(me8255_subdevice_t)); - - /* Check if counter index is out of range */ - - if (dio_idx > 2) { - PERROR("DIO index is out of range.\n"); - kfree(subdevice); - return NULL; - } - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the pointer to global port settings */ - subdevice->ctrl_reg_mirror = ctrl_reg_mirror; - - /* Save type of Meilhaus device */ - subdevice->device_id = device_id; - - /* Save the indices */ - subdevice->me8255_idx = me8255_idx; - subdevice->dio_idx = dio_idx; - - /* Do device specific initialization */ - switch (device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME1400: - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - - case PCI_DEVICE_ID_MEILHAUS_ME140A: - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - /* Check if 8255 index is out of range */ - if (me8255_idx > 0) { - PERROR("8255 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - case PCI_DEVICE_ID_MEILHAUS_ME140B: /* Fall through */ - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - /* Check if 8255 index is out of range */ - if (me8255_idx > 1) { - PERROR("8255 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - /* Get the registers */ - if (me8255_idx == 0) { - subdevice->ctrl_reg = reg_base + ME1400AB_PORT_A_CTRL; - subdevice->port_reg = - reg_base + ME1400AB_PORT_A_0 + dio_idx; - } else if (me8255_idx == 1) { - subdevice->ctrl_reg = reg_base + ME1400AB_PORT_B_CTRL; - subdevice->port_reg = - reg_base + ME1400AB_PORT_B_0 + dio_idx; - } - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - /* Check if 8255 index is out of range */ - if (me8255_idx > 0) { - PERROR("8255 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - case PCI_DEVICE_ID_MEILHAUS_ME140D: /* Fall through */ - /* Check if 8255 index is out of range */ - if (me8255_idx > 1) { - PERROR("8255 index is out of range.\n"); - me_subdevice_deinit(&subdevice->base); - kfree(subdevice); - return NULL; - } - - /* Get the registers */ - if (me8255_idx == 0) { - subdevice->ctrl_reg = reg_base + ME1400CD_PORT_A_CTRL; - subdevice->port_reg = - reg_base + ME1400CD_PORT_A_0 + dio_idx; - } else if (me8255_idx == 1) { - subdevice->ctrl_reg = reg_base + ME1400CD_PORT_B_CTRL; - subdevice->port_reg = - reg_base + ME1400CD_PORT_B_0 + dio_idx; - } - - break; - - default: - PERROR("Unknown device type. dev ID: 0x%04x\n", device_id); - - me_subdevice_deinit(&subdevice->base); - - kfree(subdevice); - - return NULL; - } - - /* Overload subdevice base class methods. */ - subdevice->base.me_subdevice_io_reset_subdevice = - me8255_io_reset_subdevice; - subdevice->base.me_subdevice_io_single_config = me8255_io_single_config; - subdevice->base.me_subdevice_io_single_read = me8255_io_single_read; - subdevice->base.me_subdevice_io_single_write = me8255_io_single_write; - subdevice->base.me_subdevice_query_number_channels = - me8255_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - me8255_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - me8255_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/me8255.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file me8255.h - * - * @brief Meilhaus PIO 8255 implementation. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME8255_H_ -#define _ME8255_H_ - -#include "mesubdevice.h" -#include "meslock.h" - -#ifdef __KERNEL__ - -/** - * @brief The 8255 subdevice class. - */ -typedef struct me8255_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - - int *ctrl_reg_mirror; /**< Pointer to mirror of the control register. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg and #ctrl_reg_mirror from concurrent access. */ - - uint32_t device_id; /**< The PCI device id of the device holding the 8255 chip. */ - int me8255_idx; /**< The index of the 8255 chip on the device. */ - int dio_idx; /**< The index of the DIO port on the 8255 chip. */ - - unsigned long port_reg; /**< Register to read or write a value from or to the port respectively. */ - unsigned long ctrl_reg; /**< Register to configure the 8255 modes. */ -} me8255_subdevice_t; - -/** - * @brief The constructor to generate a 8255 instance. - * - * @param device_id The kind of Meilhaus device holding the 8255. - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param me8255_idx The index of the 8255 chip on the Meilhaus device. - * @param dio_idx The index of the counter inside a 8255 chip. - * @param ctr_reg_mirror Pointer to mirror of control register. - * @param ctrl_reg_lock Pointer to spin lock protecting the 8255 control register and #ctrl_reg_mirror from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -me8255_subdevice_t *me8255_constructor(uint32_t device_id, - uint32_t reg_base, - unsigned int me8255_idx, - unsigned int dio_idx, - int *ctrl_reg_mirror, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/me8255_reg.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file me8255_reg.h - * - * @brief 8255 counter register definitions. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME8255_REG_H_ -#define _ME8255_REG_H_ - -#ifdef __KERNEL__ - -#define ME8255_NUMBER_CHANNELS 8 /**< The number of channels per 8255 port. */ - -#define ME1400AB_PORT_A_0 0x0000 /**< Port 0 offset. */ -#define ME1400AB_PORT_A_1 0x0001 /**< Port 1 offset. */ -#define ME1400AB_PORT_A_2 0x0002 /**< Port 2 offset. */ -#define ME1400AB_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */ - -#define ME1400AB_PORT_B_0 0x0008 /**< Port 0 offset. */ -#define ME1400AB_PORT_B_1 0x0009 /**< Port 1 offset. */ -#define ME1400AB_PORT_B_2 0x000A /**< Port 2 offset. */ -#define ME1400AB_PORT_B_CTRL 0x000B /**< Control register for 8255 B. */ - -#define ME1400CD_PORT_A_0 0x0000 /**< Port 0 offset. */ -#define ME1400CD_PORT_A_1 0x0001 /**< Port 1 offset. */ -#define ME1400CD_PORT_A_2 0x0002 /**< Port 2 offset. */ -#define ME1400CD_PORT_A_CTRL 0x0003 /**< Control register for 8255 A. */ - -#define ME1400CD_PORT_B_0 0x0040 /**< Port 0 offset. */ -#define ME1400CD_PORT_B_1 0x0041 /**< Port 1 offset. */ -#define ME1400CD_PORT_B_2 0x0042 /**< Port 2 offset. */ -#define ME1400CD_PORT_B_CTRL 0x0043 /**< Control register for 8255 B. */ - -#define ME8255_MODE_OOO 0x80 /**< Port 2 = Output, Port 1 = Output, Port 0 = Output */ -#define ME8255_MODE_IOO 0x89 /**< Port 2 = Input, Port 1 = Output, Port 0 = Output */ -#define ME8255_MODE_OIO 0x82 /**< Port 2 = Output, Port 1 = Input, Port 0 = Output */ -#define ME8255_MODE_IIO 0x8B /**< Port 2 = Input, Port 1 = Input, Port 0 = Output */ -#define ME8255_MODE_OOI 0x90 /**< Port 2 = Output, Port 1 = Output, Port 0 = Input */ -#define ME8255_MODE_IOI 0x99 /**< Port 2 = Input, Port 1 = Output, Port 0 = Input */ -#define ME8255_MODE_OII 0x92 /**< Port 2 = Output, Port 1 = Input, Port 0 = Input */ -#define ME8255_MODE_III 0x9B /**< Port 2 = Input, Port 1 = Input, Port 0 = Input */ - -#define ME8255_PORT_0_OUTPUT 0x1 /**< If set in mirror then port 0 is in output mode. */ -#define ME8255_PORT_1_OUTPUT 0x2 /**< If set in mirror then port 1 is in output mode. */ -#define ME8255_PORT_2_OUTPUT 0x4 /**< If set in mirror then port 2 is in output mode. */ - -#endif -#endif --- a/drivers/staging/meilhaus/mecirc_buf.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @file mecirc_buf.h - * - * @brief Meilhaus circular buffer implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _MECIRC_BUF_H_ -#define _MECIRC_BUF_H_ - -# ifdef __KERNEL__ - -# ifdef BOSCH - -typedef struct me_circ_buf { - unsigned int mask; -// unsigned int count; - uint32_t *buf; - int volatile head; - int volatile tail; -} me_circ_buf_t; - -static inline int me_circ_buf_values(me_circ_buf_t * buf) -{ -// return ((buf->head - buf->tail) & (buf->count - 1)); - return ((buf->head - buf->tail) & (buf->mask)); -} - -static inline int me_circ_buf_space(me_circ_buf_t * buf) -{ -// return ((buf->tail - (buf->head + 1)) & (buf->count - 1)); - return ((buf->tail - (buf->head + 1)) & (buf->mask)); -} - -static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) -{ - int end; - int n; -// end = buf->count - buf->tail; -// n = (buf->head + end) & (buf->count - 1); - end = buf->mask + 1 - buf->tail; - n = (buf->head + end) & (buf->mask); - return (n < end) ? n : end; -} - -static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) -{ - int end; - int n; - -// end = buf->count - 1 - buf->head; -// n = (end + buf->tail) & (buf->count - 1); - end = buf->mask - buf->head; - n = (end + buf->tail) & (buf->mask); - return (n <= end) ? n : (end + 1); -} - -#define _CBUFF_32b_t - -# else //~BOSCH -/// @note buf->mask = buf->count-1 = ME4600_AI_CIRC_BUF_COUNT-1 - -# ifdef _CBUFF_32b_t - //32 bit -typedef struct me_circ_buf_32b { - int volatile head; - int volatile tail; - unsigned int mask; //buffor size-1 must be 2^n-1 to work - uint32_t *buf; -} me_circ_buf_t; -# else - //16 bit -typedef struct me_circ_buf_16b { - int volatile head; - int volatile tail; - unsigned int mask; //buffor size-1 must be 2^n-1 to work - uint16_t *buf; -} me_circ_buf_t; -# endif //_CBUFF_32b_t - -/** How many values is in buffer */ -static inline int me_circ_buf_values(me_circ_buf_t * buf) -{ - return ((buf->head - buf->tail) & (buf->mask)); -} - -/** How many space left */ -static inline int me_circ_buf_space(me_circ_buf_t * buf) -{ - return ((buf->tail - (buf->head + 1)) & (buf->mask)); -} - -/** How many values can be read from buffor in one chunck. */ -static inline int me_circ_buf_values_to_end(me_circ_buf_t * buf) -{ - return (buf->tail <= - buf->head) ? (buf->head - buf->tail) : (buf->mask - buf->tail + - 1); -} - -/** How many values can be write to buffer in one chunck. */ -static inline int me_circ_buf_space_to_end(me_circ_buf_t * buf) -{ - return (buf->tail <= - buf->head) ? (buf->mask - buf->head + 1) : (buf->tail - - buf->head - 1); -} - -# endif //BOSCH -# endif //__KERNEL__ -#endif //_MECIRC_BUF_H_ --- a/drivers/staging/meilhaus/mecommon.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File :mecommon.h - * Author :GG (Guenter Gebhardt) - * Author :KG (Krzysztof Gantzke) - */ - -#ifndef _MECOMMON_H_ -#define _MECOMMON_H_ - -/*================================================================== - The version of this release - ================================================================*/ - -#ifndef ME_VERSION_DRIVER -/* Unknown version */ -# define ME_VERSION_DRIVER 0xFFFFFFFF -#endif - -#ifndef LIBMEDRIVER_VERSION -/* Unknown version */ -# define LIBMEDRIVER_VERSION 0xFFFFFFFF -#endif - -#endif --- a/drivers/staging/meilhaus/medebug.h +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @file medebug.h - * - * @brief Debugging defines. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -#ifndef _MEDEBUG_H_ -#define _MEDEBUG_H_ - -#ifdef __KERNEL__ - -#include - -//Messages control. - -#ifdef MEDEBUG_TEST_ALL /* Switch to enable all info messages. */ -# ifndef MEDEBUG_TEST -# define MEDEBUG_TEST -# endif -# ifndef MEDEBUG_TEST_INFO -# define MEDEBUG_TEST_INFO -# endif -# ifndef MEDEBUG_DEBUG_REG -# define MEDEBUG_DEBUG_REG /* Switch to enable registry access debuging messages. */ -# endif -# ifndef MEDEBUG_DEBUG_LOCKS -# define MEDEBUG_DEBUG_LOCKS /* Switch to enable locking messages. */ -# endif -#endif - -#ifdef MEDEBUG_TEST_INFO /* Switch to enable info and test messages. */ -# ifndef MEDEBUG_INFO -# define MEDEBUG_INFO /* Switch to enable info messages. */ -# endif -# ifndef MEDEBUG_TEST -# define MEDEBUG_TEST -# endif -#endif - -#ifdef MEDEBUG_TEST /* Switch to enable debug test messages. */ -# ifndef MEDEBUG_DEBUG -# define MEDEBUG_DEBUG /* Switch to enable debug messages. */ -# endif -# ifndef MEDEBUG_ERROR -# define MEDEBUG_ERROR /* Switch to enable error messages. */ -# endif -#endif - -#ifdef MEDEBUG_ERROR /* Switch to enable error messages. */ -# ifndef MEDEBUG_ERROR_CRITICAL /* Also critical error messages. */ -# define MEDEBUG_ERROR_CRITICAL /* Switch to enable high importance error messages. */ -# endif -#endif - -#undef PDEBUG /* Only to be sure. */ -#undef PINFO /* Only to be sure. */ -#undef PERROR /* Only to be sure. */ -#undef PERROR_CRITICAL /* Only to be sure. */ -#undef PDEBUG_REG /* Only to be sure. */ -#undef PDEBUG_LOCKS /* Only to be sure. */ -#undef PSECURITY /* Only to be sure. */ -#undef PLOG /* Only to be sure. */ - -#ifdef MEDEBUG_DEBUG -# define PDEBUG(fmt, args...) \ - printk(KERN_DEBUG"ME_DRV D: <%s> " fmt, __func__, ##args) -#else -# define PDEBUG(fmt, args...) -#endif - -#ifdef MEDEBUG_DEBUG_LOCKS -# define PDEBUG_LOCKS(fmt, args...) \ - printk(KERN_DEBUG"ME_DRV L: <%s> " fmt, __func__, ##args) -#else -# define PDEBUG_LOCKS(fmt, args...) -#endif - -#ifdef MEDEBUG_DEBUG_REG -# define PDEBUG_REG(fmt, args...) \ - printk(KERN_DEBUG"ME_DRV R: <%s:%d> REG:" fmt, __func__, __LINE__, ##args) -#else -# define PDEBUG_REG(fmt, args...) -#endif - -#ifdef MEDEBUG_INFO -# define PINFO(fmt, args...) \ - printk(KERN_INFO"ME_DRV I: " fmt, ##args) -#else -# define PINFO(fmt, args...) -#endif - -#ifdef MEDEBUG_ERROR -# define PERROR(fmt, args...) \ - printk(KERN_ERR"ME_DRV E: <%s:%i> " fmt, __FILE__, __LINE__, ##args) -#else -# define PERROR(fmt, args...) -#endif - -#ifdef MEDEBUG_ERROR_CRITICAL -# define PERROR_CRITICAL(fmt, args...) \ - printk(KERN_CRIT"ME_DRV C: <%s:%i> " fmt, __FILE__, __LINE__, ##args) -#else -# define PERROR_CRITICAL(fmt, args...) -#endif - -//This debug is only to detect logical errors! -# define PSECURITY(fmt, args...) \ - printk(KERN_CRIT"ME_DRV SECURITY: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args) -//This debug is to keep track in customers' system -# define PLOG(fmt, args...) \ - printk(KERN_INFO"ME_DRV: " fmt, ##args) - -//This debug is to check new parts during development -#ifdef MEDEBUG_DEVELOP -# define PDEVELOP(fmt, args...) \ - printk(KERN_CRIT"ME_DRV: <%s:%s:%i> " fmt, __FILE__, __func__, __LINE__, ##args) -#else -# define PDEVELOP(fmt, args...) -#endif - -#endif //__KERNEL__ -#endif //_MEDEBUG_H_ --- a/drivers/staging/meilhaus/medefines.h +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : medefines.h - * Author : GG (Guenter Gebhardt) - * Author : KG (Krzysztof Gantzke) - */ - -#ifndef _MEDEFINES_H_ -#define _MEDEFINES_H_ - -/*================================================================== - General - ================================================================*/ - -#define ME_VALUE_NOT_USED 0x0 -#define ME_VALUE_INVALID ~0x0 - -/*================================================================== - Defines common to access functions - ================================================================*/ - -#define ME_LOCK_RELEASE 0x00010001 -#define ME_LOCK_SET 0x00010002 -#define ME_LOCK_CHECK 0x00010003 - -/*================================================================== - Defines meOpen function - ================================================================*/ - -#define ME_OPEN_NO_FLAGS 0x0 - -/*================================================================== - Defines meClose function - ================================================================*/ - -#define ME_CLOSE_NO_FLAGS 0x0 - -/*================================================================== - Defines meLockDriver function - ================================================================*/ - -#define ME_LOCK_DRIVER_NO_FLAGS 0x0 - -/*================================================================== - Defines meLockDevice function - ================================================================*/ - -#define ME_LOCK_DEVICE_NO_FLAGS 0x0 - -/*================================================================== - Defines meLockSubdevice function - ================================================================*/ - -#define ME_LOCK_SUBDEVICE_NO_FLAGS 0x0 - - -/*================================================================== - Defines common to error functions - ================================================================*/ - -#define ME_ERROR_MSG_MAX_COUNT 256 - -#define ME_SWITCH_DISABLE 0x00020001 -#define ME_SWITCH_ENABLE 0x00020002 - -/*================================================================== - Defines common to io functions - ================================================================*/ - -#define ME_REF_DIO_FIFO_LOW 0x00030001 -#define ME_REF_DIO_FIFO_HIGH 0x00030002 - -#define ME_REF_CTR_PREVIOUS 0x00040001 -#define ME_REF_CTR_INTERNAL_1MHZ 0x00040002 -#define ME_REF_CTR_INTERNAL_10MHZ 0x00040003 -#define ME_REF_CTR_EXTERNAL 0x00040004 - -#define ME_REF_AI_GROUND 0x00050001 -#define ME_REF_AI_DIFFERENTIAL 0x00050002 - -#define ME_REF_AO_GROUND 0x00060001 - -#define ME_TRIG_CHAN_DEFAULT 0x00070001 -#define ME_TRIG_CHAN_SYNCHRONOUS 0x00070002 - -#define ME_TRIG_TYPE_NONE 0x00000000 -#define ME_TRIG_TYPE_SW 0x00080001 -#define ME_TRIG_TYPE_THRESHOLD 0x00080002 -#define ME_TRIG_TYPE_WINDOW 0x00080003 -#define ME_TRIG_TYPE_EDGE 0x00080004 -#define ME_TRIG_TYPE_SLOPE 0x00080005 -#define ME_TRIG_TYPE_EXT_DIGITAL 0x00080006 -#define ME_TRIG_TYPE_EXT_ANALOG 0x00080007 -#define ME_TRIG_TYPE_PATTERN 0x00080008 -#define ME_TRIG_TYPE_TIMER 0x00080009 -#define ME_TRIG_TYPE_COUNT 0x0008000A -#define ME_TRIG_TYPE_FOLLOW 0x0008000B - -#define ME_TRIG_EDGE_NONE 0x00000000 -#define ME_TRIG_EDGE_ABOVE 0x00090001 -#define ME_TRIG_EDGE_BELOW 0x00090002 -#define ME_TRIG_EDGE_ENTRY 0x00090003 -#define ME_TRIG_EDGE_EXIT 0x00090004 -#define ME_TRIG_EDGE_RISING 0x00090005 -#define ME_TRIG_EDGE_FALLING 0x00090006 -#define ME_TRIG_EDGE_ANY 0x00090007 - -#define ME_TIMER_ACQ_START 0x000A0001 -#define ME_TIMER_SCAN_START 0x000A0002 -#define ME_TIMER_CONV_START 0x000A0003 - -/*================================================================== - Defines for meIOFrequencyToTicks function - ================================================================*/ - -#define ME_IO_FREQUENCY_TO_TICKS_NO_FLAGS 0x0 - -/*================================================================== - Defines for meIOIrqStart function - ================================================================*/ - -#define ME_IRQ_SOURCE_DIO_PATTERN 0x000B0001 -#define ME_IRQ_SOURCE_DIO_MASK 0x000B0002 -#define ME_IRQ_SOURCE_DIO_LINE 0x000B0003 -#define ME_IRQ_SOURCE_DIO_OVER_TEMP 0x000B0004 - -#define ME_IRQ_EDGE_NOT_USED 0x00000000 -#define ME_IRQ_EDGE_RISING 0x000C0001 -#define ME_IRQ_EDGE_FALLING 0x000C0002 -#define ME_IRQ_EDGE_ANY 0x000C0003 - -/*================================================================== - Defines for meIOIrqStart function - ================================================================*/ - -#define ME_IO_IRQ_START_NO_FLAGS 0x000000 -#define ME_IO_IRQ_START_DIO_BIT 0x000001 -#define ME_IO_IRQ_START_DIO_BYTE 0x000002 -#define ME_IO_IRQ_START_DIO_WORD 0x000004 -#define ME_IO_IRQ_START_DIO_DWORD 0x000008 -#define ME_IO_IRQ_START_PATTERN_FILTERING 0x000010 -#define ME_IO_IRQ_START_EXTENDED_STATUS 0x000020 - -/*================================================================== - Defines for meIOIrqWait function - ================================================================*/ - -#define ME_IO_IRQ_WAIT_NO_FLAGS 0x000000 -#define ME_IO_IRQ_WAIT_NORMAL_STATUS 0x000001 -#define ME_IO_IRQ_WAIT_EXTENDED_STATUS 0x000002 - -/*================================================================== - Defines for meIOIrqStop function - ================================================================*/ - -#define ME_IO_IRQ_STOP_NO_FLAGS 0x000000 - -/*================================================================== - Defines for meIOIrqSetCallback function - ================================================================*/ - -#define ME_IO_IRQ_SET_CALLBACK_NO_FLAGS 0x0 - -/*================================================================== - Defines for meIOResetDevice function - ================================================================*/ - -#define ME_IO_RESET_DEVICE_NO_FLAGS 0x0 - -/*================================================================== - Defines for meIOResetSubdevice function - ================================================================*/ - -#define ME_IO_RESET_SUBDEVICE_NO_FLAGS 0x0 - -/*================================================================== - Defines for meIOSingleConfig function - ================================================================*/ - -#define ME_SINGLE_CONFIG_DIO_INPUT 0x000D0001 -#define ME_SINGLE_CONFIG_DIO_OUTPUT 0x000D0002 -#define ME_SINGLE_CONFIG_DIO_HIGH_IMPEDANCE 0x000D0003 -#define ME_SINGLE_CONFIG_DIO_SINK 0x000D0004 -#define ME_SINGLE_CONFIG_DIO_SOURCE 0x000D0005 -#define ME_SINGLE_CONFIG_DIO_MUX32M 0x000D0006 -#define ME_SINGLE_CONFIG_DIO_DEMUX32 0x000D0007 -#define ME_SINGLE_CONFIG_DIO_BIT_PATTERN 0x000D0008 - -#define ME_SINGLE_CONFIG_CTR_8254_MODE_0 0x000E0001 -#define ME_SINGLE_CONFIG_CTR_8254_MODE_1 0x000E0002 -#define ME_SINGLE_CONFIG_CTR_8254_MODE_2 0x000E0003 -#define ME_SINGLE_CONFIG_CTR_8254_MODE_3 0x000E0004 -#define ME_SINGLE_CONFIG_CTR_8254_MODE_4 0x000E0005 -#define ME_SINGLE_CONFIG_CTR_8254_MODE_5 0x000E0006 - -#define ME_IO_SINGLE_CONFIG_NO_FLAGS 0x00 -#define ME_IO_SINGLE_CONFIG_DIO_BIT 0x01 -#define ME_IO_SINGLE_CONFIG_DIO_BYTE 0x02 -#define ME_IO_SINGLE_CONFIG_DIO_WORD 0x04 -#define ME_IO_SINGLE_CONFIG_DIO_DWORD 0x08 -#define ME_IO_SINGLE_CONFIG_MULTISIG_LED_ON 0x10 -#define ME_IO_SINGLE_CONFIG_MULTISIG_LED_OFF 0x20 -#define ME_IO_SINGLE_CONFIG_AI_RMS 0x40 -#define ME_IO_SINGLE_CONFIG_CONTINUE 0x80 - -/*================================================================== - Defines for meIOSingle function - ================================================================*/ - -#define ME_IO_SINGLE_NO_FLAGS 0x0 -#define ME_IO_SINGLE_NONBLOCKING 0x20 - -#define ME_DIR_INPUT 0x000F0001 -#define ME_DIR_OUTPUT 0x000F0002 - -#define ME_IO_SINGLE_TYPE_NO_FLAGS 0x00 -#define ME_IO_SINGLE_TYPE_DIO_BIT 0x01 -#define ME_IO_SINGLE_TYPE_DIO_BYTE 0x02 -#define ME_IO_SINGLE_TYPE_DIO_WORD 0x04 -#define ME_IO_SINGLE_TYPE_DIO_DWORD 0x08 -#define ME_IO_SINGLE_TYPE_TRIG_SYNCHRONOUS 0x10 -#define ME_IO_SINGLE_TYPE_WRITE_NONBLOCKING 0x20 - -/*================================================================== - Defines for meIOStreamConfig function - ================================================================*/ - -#define ME_IO_STREAM_CONFIG_NO_FLAGS 0x0 -#define ME_IO_STREAM_CONFIG_BIT_PATTERN 0x1 -#define ME_IO_STREAM_CONFIG_WRAPAROUND 0x2 -#define ME_IO_STREAM_CONFIG_SAMPLE_AND_HOLD 0x4 -#define ME_IO_STREAM_CONFIG_HARDWARE_ONLY 0x8 - -#define ME_IO_STREAM_CONFIG_TYPE_NO_FLAGS 0x0 - -#define ME_IO_STREAM_TRIGGER_TYPE_NO_FLAGS 0x0 - -/*================================================================== - Defines for meIOStreamRead function - ================================================================*/ - -#define ME_READ_MODE_BLOCKING 0x00100001 -#define ME_READ_MODE_NONBLOCKING 0x00100002 - -#define ME_IO_STREAM_READ_NO_FLAGS 0x0 -#define ME_IO_STREAM_READ_FRAMES 0x1 - -/*================================================================== - Defines for meIOStreamWrite function - ================================================================*/ - -#define ME_WRITE_MODE_BLOCKING 0x00110001 -#define ME_WRITE_MODE_NONBLOCKING 0x00110002 -#define ME_WRITE_MODE_PRELOAD 0x00110003 - -#define ME_IO_STREAM_WRITE_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for meIOStreamStart function - ================================================================*/ - -#define ME_IO_STREAM_START_NO_FLAGS 0x00000000 - -#define ME_START_MODE_BLOCKING 0x00120001 -#define ME_START_MODE_NONBLOCKING 0x00120002 - -#define ME_IO_STREAM_START_TYPE_NO_FLAGS 0x0 -#define ME_IO_STREAM_START_TYPE_TRIG_SYNCHRONOUS 0x1 - -/*================================================================== - Defines for meIOStreamStop function - ================================================================*/ - -#define ME_IO_STREAM_STOP_NO_FLAGS 0x00000000 -#define ME_IO_STREAM_STOP_PRESERVE_BUFFERS 0x00000001 - -#define ME_STOP_MODE_IMMEDIATE 0x00130001 -#define ME_STOP_MODE_LAST_VALUE 0x00130002 - -#define ME_IO_STREAM_STOP_TYPE_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for meIOStreamStatus function - ================================================================*/ - -#define ME_WAIT_NONE 0x00140001 -#define ME_WAIT_IDLE 0x00140002 - -#define ME_STATUS_INVALID 0x00000000 -#define ME_STATUS_IDLE 0x00150001 -#define ME_STATUS_BUSY 0x00150002 -#define ME_STATUS_ERROR 0x00150003 - -#define ME_IO_STREAM_STATUS_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for meIOStreamSetCallbacks function - ================================================================*/ - -#define ME_IO_STREAM_SET_CALLBACKS_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for meIOStreamNewValues function - ================================================================*/ - -#define ME_IO_STREAM_NEW_VALUES_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for meIOTimeToTicks function - ================================================================*/ - -#define ME_IO_STREAM_TIME_TO_TICKS_NO_FLAGS 0x00000000 - -/*================================================================== - Defines for module types - ================================================================*/ - -#define ME_MODULE_TYPE_MULTISIG_NONE 0x00000000 -#define ME_MODULE_TYPE_MULTISIG_DIFF16_10V 0x00160001 -#define ME_MODULE_TYPE_MULTISIG_DIFF16_20V 0x00160002 -#define ME_MODULE_TYPE_MULTISIG_DIFF16_50V 0x00160003 -#define ME_MODULE_TYPE_MULTISIG_CURRENT16_0_20MA 0x00160004 -#define ME_MODULE_TYPE_MULTISIG_RTD8_PT100 0x00160005 -#define ME_MODULE_TYPE_MULTISIG_RTD8_PT500 0x00160006 -#define ME_MODULE_TYPE_MULTISIG_RTD8_PT1000 0x00160007 -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_B 0x00160008 -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_E 0x00160009 -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_J 0x0016000A -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_K 0x0016000B -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_N 0x0016000C -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_R 0x0016000D -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_S 0x0016000E -#define ME_MODULE_TYPE_MULTISIG_TE8_TYPE_T 0x0016000F -#define ME_MODULE_TYPE_MULTISIG_TE8_TEMP_SENSOR 0x00160010 - -/*================================================================== - Defines for meQuerySubdeviceCaps function - ================================================================*/ - -#define ME_CAPS_NONE 0x00000000 - -#define ME_CAPS_DIO_DIR_BIT 0x00000001 -#define ME_CAPS_DIO_DIR_BYTE 0x00000002 -#define ME_CAPS_DIO_DIR_WORD 0x00000004 -#define ME_CAPS_DIO_DIR_DWORD 0x00000008 -#define ME_CAPS_DIO_SINK_SOURCE 0x00000010 -#define ME_CAPS_DIO_BIT_PATTERN_IRQ 0x00000020 -#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_RISING 0x00000040 -#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_FALLING 0x00000080 -#define ME_CAPS_DIO_BIT_MASK_IRQ_EDGE_ANY 0x00000100 -#define ME_CAPS_DIO_OVER_TEMP_IRQ 0x00000200 - -#define ME_CAPS_CTR_CLK_PREVIOUS 0x00000001 -#define ME_CAPS_CTR_CLK_INTERNAL_1MHZ 0x00000002 -#define ME_CAPS_CTR_CLK_INTERNAL_10MHZ 0x00000004 -#define ME_CAPS_CTR_CLK_EXTERNAL 0x00000008 - -#define ME_CAPS_AI_TRIG_SYNCHRONOUS 0x00000001 -/// @note Backward compatibility for me1600 in old style. -#define ME_CAPS_AI_TRIG_SIMULTANEOUS ME_CAPS_AI_TRIG_SYNCHRONOUS -#define ME_CAPS_AI_FIFO 0x00000002 -#define ME_CAPS_AI_FIFO_THRESHOLD 0x00000004 - -#define ME_CAPS_AO_TRIG_SYNCHRONOUS 0x00000001 -/// @note Backward compatibility for me1600 in old style. -#define ME_CAPS_AO_TRIG_SIMULTANEOUS ME_CAPS_AO_TRIG_SYNCHRONOUS -#define ME_CAPS_AO_FIFO 0x00000002 -#define ME_CAPS_AO_FIFO_THRESHOLD 0x00000004 - -#define ME_CAPS_EXT_IRQ_EDGE_RISING 0x00000001 -#define ME_CAPS_EXT_IRQ_EDGE_FALLING 0x00000002 -#define ME_CAPS_EXT_IRQ_EDGE_ANY 0x00000004 - -/*================================================================== - Defines for meQuerySubdeviceCapsArgs function - ================================================================*/ - -#define ME_CAP_AI_FIFO_SIZE 0x001D0000 -#define ME_CAP_AI_BUFFER_SIZE 0x001D0001 - -#define ME_CAP_AO_FIFO_SIZE 0x001F0000 -#define ME_CAP_AO_BUFFER_SIZE 0x001F0001 - -#define ME_CAP_CTR_WIDTH 0x00200000 - -/*================================================================== - Defines common to query functions - ================================================================*/ - -#define ME_UNIT_INVALID 0x00000000 -#define ME_UNIT_VOLT 0x00170001 -#define ME_UNIT_AMPERE 0x00170002 -#define ME_UNIT_ANY 0x00170003 - -#define ME_TYPE_INVALID 0x00000000 -#define ME_TYPE_AO 0x00180001 -#define ME_TYPE_AI 0x00180002 -#define ME_TYPE_DIO 0x00180003 -#define ME_TYPE_DO 0x00180004 -#define ME_TYPE_DI 0x00180005 -#define ME_TYPE_CTR 0x00180006 -#define ME_TYPE_EXT_IRQ 0x00180007 - -#define ME_SUBTYPE_INVALID 0x00000000 -#define ME_SUBTYPE_SINGLE 0x00190001 -#define ME_SUBTYPE_STREAMING 0x00190002 -#define ME_SUBTYPE_CTR_8254 0x00190003 -#define ME_SUBTYPE_ANY 0x00190004 - -#define ME_DEVICE_DRIVER_NAME_MAX_COUNT 64 -#define ME_DEVICE_NAME_MAX_COUNT 64 - -#define ME_DEVICE_DESCRIPTION_MAX_COUNT 256 - -#define ME_BUS_TYPE_INVALID 0x00000000 -#define ME_BUS_TYPE_PCI 0x001A0001 -#define ME_BUS_TYPE_USB 0x001A0002 - -#define ME_PLUGGED_INVALID 0x00000000 -#define ME_PLUGGED_IN 0x001B0001 -#define ME_PLUGGED_OUT 0x001B0002 - -#define ME_EXTENSION_TYPE_INVALID 0x00000000 -#define ME_EXTENSION_TYPE_NONE 0x001C0001 -#define ME_EXTENSION_TYPE_MUX32M 0x001C0002 -#define ME_EXTENSION_TYPE_DEMUX32 0x001C0003 -#define ME_EXTENSION_TYPE_MUX32S 0x001C0004 - -#define ME_ACCESS_TYPE_INVALID 0x00000000 -#define ME_ACCESS_TYPE_LOCAL 0x001D0001 -#define ME_ACCESS_TYPE_REMOTE 0x001D0002 - -/// @note Add by KG - -/*================================================================== - Defines for meUtilityPWM - ================================================================*/ -#define ME_PWM_START_CONNECT_INTERNAL 0x00200001 - -/* Flags for SingleConfig channels configure */ -#define ME_SINGLE_CHANNEL_NOT_CONFIGURED 0x00 -#define ME_SINGLE_CHANNEL_CONFIGURED 0x01 - -/* Define if configuration should be downloaded to driver */ -#define ME_CONFIG_LOAD_NO_FLAGS 0x0 -#define ME_CONFIG_LOAD_TO_DRIVER 0x1 - -#endif --- a/drivers/staging/meilhaus/medevice.c +++ /dev/null @@ -1,1740 +0,0 @@ -/** - * @file medevice.c - * - * @brief Meilhaus device base class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#include "mecommon.h" -#include "meinternal.h" -#include "medefines.h" -#include "meerror.h" - -#include "medebug.h" -#include "medevice.h" - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -static int me_device_io_irq_start(struct me_device *device, - struct file *filep, - int subdevice, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_irq_start(s, - filep, - channel, - irq_source, - irq_edge, irq_arg, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_irq_wait(struct me_device *device, - struct file *filep, - int subdevice, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_irq_wait(s, - filep, - channel, - irq_count, - value, time_out, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_irq_stop(struct me_device *device, - struct file *filep, - int subdevice, int channel, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_irq_stop(s, filep, channel, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_reset_device(struct me_device *device, - struct file *filep, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - int i, n; - - PDEBUG("executed.\n"); - - /* Get the number of subdevices. */ - n = me_slist_get_number_subdevices(&device->slist); - - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - - /* Reset every subdevice in list. */ - for (i = 0; i < n; i++) { - s = me_slist_get_subdevice(&device->slist, i); - err = s->me_subdevice_io_reset_subdevice(s, filep, flags); - - if (err) { - PERROR("Cannot reset subdevice.\n"); - break; - } - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_reset_subdevice(struct me_device *device, - struct file *filep, - int subdevice, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_reset_subdevice(s, filep, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_single_config(struct me_device *device, - struct file *filep, - int subdevice, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_single_config(s, - filep, - channel, - single_config, - ref, - trig_chan, - trig_type, - trig_edge, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_single_read(struct me_device *device, - struct file *filep, - int subdevice, - int channel, - int *value, int time_out, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_single_read(s, - filep, - channel, - value, time_out, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_single_write(struct me_device *device, - struct file *filep, - int subdevice, - int channel, - int value, int time_out, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_single_write(s, - filep, - channel, - value, time_out, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_config(struct me_device *device, - struct file *filep, - int subdevice, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_config(s, - filep, - config_list, - count, - trigger, - fifo_irq_threshold, - flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_new_values(struct me_device *device, - struct file *filep, - int subdevice, - int time_out, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_new_values(s, - filep, - time_out, - count, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_read(struct me_device *device, - struct file *filep, - int subdevice, - int read_mode, - int *values, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_read(s, - filep, - read_mode, - values, count, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_start(struct me_device *device, - struct file *filep, - int subdevice, - int start_mode, int time_out, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_start(s, - filep, - start_mode, - time_out, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_status(struct me_device *device, - struct file *filep, - int subdevice, - int wait, - int *status, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_status(s, - filep, - wait, - status, count, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_stop(struct me_device *device, - struct file *filep, - int subdevice, int stop_mode, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_stop(s, - filep, stop_mode, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_io_stream_write(struct me_device *device, - struct file *filep, - int subdevice, - int write_mode, - int *values, int *count, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_io_stream_write(s, - filep, - write_mode, - values, count, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_lock_device(struct me_device *device, - struct file *filep, int lock, int flags) -{ - PDEBUG("executed.\n"); - - return me_dlock_lock(&device->dlock, - filep, lock, flags, &device->slist); -} - -static int me_device_lock_subdevice(struct me_device *device, - struct file *filep, - int subdevice, int lock, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Enter device. - err = me_dlock_enter(&device->dlock, filep); - - if (err) { - PERROR("Cannot enter device.\n"); - return err; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_lock_subdevice(s, filep, lock, flags); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - // Exit device. - me_dlock_exit(&device->dlock, filep); - - return err; -} - -static int me_device_query_description_device(struct me_device *device, - char **description) -{ - PDEBUG("executed.\n"); - *description = device->device_description; - return ME_ERRNO_SUCCESS; -} - -static int me_device_query_info_device(struct me_device *device, - int *vendor_id, - int *device_id, - int *serial_no, - int *bus_type, - int *bus_no, - int *dev_no, int *func_no, int *plugged) -{ - PDEBUG("executed.\n"); - - if (device->bus_type == ME_BUS_TYPE_PCI) { - *vendor_id = device->info.pci.vendor_id; - *device_id = device->info.pci.device_id; - *serial_no = device->info.pci.serial_no; - *bus_type = ME_BUS_TYPE_PCI; - *bus_no = device->info.pci.pci_bus_no; - *dev_no = device->info.pci.pci_dev_no; - *func_no = device->info.pci.pci_func_no; - *plugged = ME_PLUGGED_IN; - } else { - *plugged = ME_PLUGGED_OUT; - } - return ME_ERRNO_SUCCESS; -} - -static int me_device_query_name_device(struct me_device *device, char **name) -{ - PDEBUG("executed.\n"); - *name = device->device_name; - return ME_ERRNO_SUCCESS; -} - -static int me_device_query_name_device_driver(struct me_device *device, - char **name) -{ - PDEBUG("executed.\n"); - *name = device->driver_name; - return ME_ERRNO_SUCCESS; -} - -static int me_device_query_number_subdevices(struct me_device *device, - int *number) -{ - PDEBUG("executed.\n"); - return me_slist_query_number_subdevices(&device->slist, number); -} - -static int me_device_query_number_channels(struct me_device *device, - int subdevice, int *number) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_number_channels(s, number); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_number_ranges(struct me_device *device, - int subdevice, int unit, int *count) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_number_ranges(s, unit, count); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_range_by_min_max(struct me_device *device, - int subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_range_by_min_max(s, - unit, - min, - max, - maxdata, range); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_range_info(struct me_device *device, - int subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_range_info(s, - range, - unit, min, max, maxdata); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_subdevice_by_type(struct me_device *device, - int start_subdevice, - int type, - int subtype, int *subdevice) -{ - PDEBUG("executed.\n"); - - return me_slist_get_subdevice_by_type(&device->slist, - start_subdevice, - type, subtype, subdevice); -} - -static int me_device_query_subdevice_type(struct me_device *device, - int subdevice, - int *type, int *subtype) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_subdevice_type(s, type, subtype); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_subdevice_caps(struct me_device *device, - int subdevice, int *caps) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_subdevice_caps(s, caps); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_subdevice_caps_args(struct me_device *device, - int subdevice, - int cap, int *args, int count) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_subdevice_caps_args(s, - cap, - args, count); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_timer(struct me_device *device, - int subdevice, - int timer, - int *base_frequency, - uint64_t *min_ticks, uint64_t *max_ticks) -{ - int err = ME_ERRNO_SUCCESS; - me_subdevice_t *s; - - PDEBUG("executed.\n"); - - // Check subdevice index. - - if (subdevice >= me_slist_get_number_subdevices(&device->slist)) { - PERROR("Invalid subdevice.\n"); - return ME_ERRNO_INVALID_SUBDEVICE; - } - // Get subdevice instance. - s = me_slist_get_subdevice(&device->slist, subdevice); - - if (s) { - // Call subdevice method. - err = s->me_subdevice_query_timer(s, - timer, - base_frequency, - min_ticks, max_ticks); - } else { - // Something really bad happened. - PERROR("Cannot get subdevice instance.\n"); - err = ME_ERRNO_INTERNAL; - } - - return err; -} - -static int me_device_query_version_device_driver(struct me_device *device, - int *version) -/** @todo Versions shold be read from driver. I must overwrite this function in each module. Here should be returned an error! -*/ -{ - PDEBUG("executed.\n"); - *version = ME_VERSION_DRIVER; - return ME_ERRNO_SUCCESS; -} - -static int me_device_config_load(struct me_device *device, struct file *filep, - me_cfg_device_entry_t *config) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_SUCCESS; //If no need for config return success. -// return ME_ERRNO_NOT_SUPPORTED; -} - -static void me_device_destructor(me_device_t *me_device) -{ - PDEBUG("executed.\n"); - me_device_deinit(me_device); - kfree(me_device); -} - -/* //me_device_usb_init -int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface) -{ - PDEBUG("executed.\n"); - return -1; -} -*/ - -static int get_device_descriptions(uint16_t device_id, - char **device_name, - char **device_description, - char **driver_name) -/** @todo This is wrong concept! Static table has too strong limitations! -* 'device_name' and 'driver_name' should be calculated from 'device_id' -* 'device_description' should be read from device or moved to user space and handled by library! -*/ -{ - PDEBUG("executed.\n"); - - switch (device_id) { - case PCI_DEVICE_ID_MEILHAUS_ME1000: - case PCI_DEVICE_ID_MEILHAUS_ME1000_A: - case PCI_DEVICE_ID_MEILHAUS_ME1000_B: - *device_name = ME1000_NAME_DEVICE_ME1000; - *device_description = ME1000_DESCRIPTION_DEVICE_ME1000; - *driver_name = ME1000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1400: - *device_name = ME1400_NAME_DEVICE_ME1400; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140A: - *device_name = ME1400_NAME_DEVICE_ME1400A; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400A; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140B: - *device_name = ME1400_NAME_DEVICE_ME1400B; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400B; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - *device_name = ME1400_NAME_DEVICE_ME1400E; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400E; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - *device_name = ME1400_NAME_DEVICE_ME1400EA; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EA; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - *device_name = ME1400_NAME_DEVICE_ME1400EB; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400EB; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - *device_name = ME1400_NAME_DEVICE_ME1400C; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400C; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140D: - *device_name = ME1400_NAME_DEVICE_ME1400D; - *device_description = ME1400_DESCRIPTION_DEVICE_ME1400D; - *driver_name = ME1400_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: - *device_name = ME1600_NAME_DEVICE_ME16004U; - *device_description = ME1600_DESCRIPTION_DEVICE_ME16004U; - *driver_name = ME1600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: - *device_name = ME1600_NAME_DEVICE_ME16008U; - *device_description = ME1600_DESCRIPTION_DEVICE_ME16008U; - *driver_name = ME1600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: - *device_name = ME1600_NAME_DEVICE_ME160012U; - *device_description = ME1600_DESCRIPTION_DEVICE_ME160012U; - *driver_name = ME1600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: - *device_name = ME1600_NAME_DEVICE_ME160016U; - *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U; - *driver_name = ME1600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: - *device_name = ME1600_NAME_DEVICE_ME160016U8I; - *device_description = ME1600_DESCRIPTION_DEVICE_ME160016U8I; - *driver_name = ME1600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - *device_name = ME4600_NAME_DEVICE_ME4610; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4610; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4650: - *device_name = ME4600_NAME_DEVICE_ME4650; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4650; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660: - *device_name = ME4600_NAME_DEVICE_ME4660; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4660; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - *device_name = ME4600_NAME_DEVICE_ME4660I; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4660I; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660S: - *device_name = ME4600_NAME_DEVICE_ME4660S; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4660S; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660IS: - *device_name = ME4600_NAME_DEVICE_ME4660IS; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4660IS; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670: - *device_name = ME4600_NAME_DEVICE_ME4670; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4670; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - *device_name = ME4600_NAME_DEVICE_ME4670I; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4670I; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - *device_name = ME4600_NAME_DEVICE_ME4670S; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4670S; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - *device_name = ME4600_NAME_DEVICE_ME4670IS; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4670IS; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680: - *device_name = ME4600_NAME_DEVICE_ME4680; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4680; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - *device_name = ME4600_NAME_DEVICE_ME4680I; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4680I; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - *device_name = ME4600_NAME_DEVICE_ME4680S; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4680S; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - *device_name = ME4600_NAME_DEVICE_ME4680IS; - *device_description = ME4600_DESCRIPTION_DEVICE_ME4680IS; - *driver_name = ME4600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6004: - *device_name = ME6000_NAME_DEVICE_ME60004; - *device_description = ME6000_DESCRIPTION_DEVICE_ME60004; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6008: - *device_name = ME6000_NAME_DEVICE_ME60008; - *device_description = ME6000_DESCRIPTION_DEVICE_ME60008; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME600F: - *device_name = ME6000_NAME_DEVICE_ME600016; - *device_description = ME6000_DESCRIPTION_DEVICE_ME600016; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6014: - *device_name = ME6000_NAME_DEVICE_ME6000I4; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6018: - *device_name = ME6000_NAME_DEVICE_ME6000I8; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME601F: - *device_name = ME6000_NAME_DEVICE_ME6000I16; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6034: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE4; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6038: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE8; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME603F: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE16; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6104: - *device_name = ME6000_NAME_DEVICE_ME61004; - *device_description = ME6000_DESCRIPTION_DEVICE_ME61004; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6108: - *device_name = ME6000_NAME_DEVICE_ME61008; - *device_description = ME6000_DESCRIPTION_DEVICE_ME61008; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME610F: - *device_name = ME6000_NAME_DEVICE_ME610016; - *device_description = ME6000_DESCRIPTION_DEVICE_ME610016; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6114: - *device_name = ME6000_NAME_DEVICE_ME6100I4; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6118: - *device_name = ME6000_NAME_DEVICE_ME6100I8; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME611F: - *device_name = ME6000_NAME_DEVICE_ME6100I16; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6134: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE4; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6138: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE8; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME613F: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE16; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6044: - *device_name = ME6000_NAME_DEVICE_ME60004DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME60004DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6048: - *device_name = ME6000_NAME_DEVICE_ME60008DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME60008DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME604F: - *device_name = ME6000_NAME_DEVICE_ME600016DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME600016DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6054: - *device_name = ME6000_NAME_DEVICE_ME6000I4DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6058: - *device_name = ME6000_NAME_DEVICE_ME6000I8DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME605F: - *device_name = ME6000_NAME_DEVICE_ME6000I16DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6074: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE4DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6078: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE8DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME607F: - *device_name = ME6000_NAME_DEVICE_ME6000ISLE16DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6144: - *device_name = ME6000_NAME_DEVICE_ME61004DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME61004DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6148: - *device_name = ME6000_NAME_DEVICE_ME61008DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME61008DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME614F: - *device_name = ME6000_NAME_DEVICE_ME610016DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME610016DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6154: - *device_name = ME6000_NAME_DEVICE_ME6100I4DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6158: - *device_name = ME6000_NAME_DEVICE_ME6100I8DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME615F: - *device_name = ME6000_NAME_DEVICE_ME6100I16DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6174: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE4DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6178: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE8DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME617F: - *device_name = ME6000_NAME_DEVICE_ME6100ISLE16DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6259: - *device_name = ME6000_NAME_DEVICE_ME6200I9DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6359: - *device_name = ME6000_NAME_DEVICE_ME6300I9DIO; - *device_description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO; - *driver_name = ME6000_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0630: - *device_name = ME0600_NAME_DEVICE_ME0630; - *device_description = ME0600_DESCRIPTION_DEVICE_ME0630; - *driver_name = ME0600_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - *device_name = ME8100_NAME_DEVICE_ME8100A; - *device_description = ME8100_DESCRIPTION_DEVICE_ME8100A; - *driver_name = ME8100_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - *device_name = ME8100_NAME_DEVICE_ME8100B; - *device_description = ME8100_DESCRIPTION_DEVICE_ME8100B; - *driver_name = ME8100_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8200_A: - *device_name = ME8200_NAME_DEVICE_ME8200A; - *device_description = ME8200_DESCRIPTION_DEVICE_ME8200A; - *driver_name = ME8200_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8200_B: - *device_name = ME8200_NAME_DEVICE_ME8200B; - *device_description = ME8200_DESCRIPTION_DEVICE_ME8200B; - *driver_name = ME8200_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0940: - *device_name = ME0900_NAME_DEVICE_ME0940; - *device_description = ME0900_DESCRIPTION_DEVICE_ME0940; - *driver_name = ME0900_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0950: - *device_name = ME0900_NAME_DEVICE_ME0950; - *device_description = ME0900_DESCRIPTION_DEVICE_ME0950; - *driver_name = ME0900_NAME_DRIVER; - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0960: - *device_name = ME0900_NAME_DEVICE_ME0960; - *device_description = ME0900_DESCRIPTION_DEVICE_ME0960; - *driver_name = ME0900_NAME_DRIVER; - break; -/* - case USB_DEVICE_ID_MEPHISTO_S1: - *device_name = MEPHISTO_S1_NAME_DEVICE; - *device_description = MEPHISTO_S1_DESCRIPTION_DEVICE; - *driver_name = MEPHISTO_S1_NAME_DRIVER; - break; -*/ - default: - *device_name = EMPTY_NAME_DEVICE; - *device_description = EMPTY_DESCRIPTION_DEVICE; - *driver_name = EMPTY_NAME_DRIVER; - - PERROR("Invalid device id.\n"); - - return 1; - } - - return 0; -} - -int me_device_pci_init(me_device_t *me_device, struct pci_dev *pci_device) -{ - int err; - int i; - - PDEBUG("executed.\n"); - - // Initialize device list head. - INIT_LIST_HEAD(&me_device->list); - - // Initialize device description strings. - err = get_device_descriptions(pci_device->device, - &me_device->device_name, - &me_device->device_description, - &me_device->driver_name); - - if (err) { - PERROR("Cannot initialize device description strings.\n"); - return 1; - } - // Enable the pci device. - err = pci_enable_device(pci_device); - - if (err < 0) { - PERROR("Cannot enable PCI device.\n"); - return 1; - } - // Request the PCI register regions. - err = pci_request_regions(pci_device, me_device->device_name); - - if (err < 0) { - PERROR("Cannot request PCI regions.\n"); - goto ERROR_0; - } - // The bus carrying the device is a PCI bus. - me_device->bus_type = ME_BUS_TYPE_PCI; - - // Store the PCI information for later usage. - me_device->info.pci.pci_device = pci_device; - - // Get PCI register bases and sizes. - for (i = 0; i < 6; i++) { - me_device->info.pci.reg_bases[i] = - pci_resource_start(pci_device, i); - me_device->info.pci.reg_sizes[i] = - pci_resource_len(pci_device, i); - } - - // Get the PCI location. - me_device->info.pci.pci_bus_no = pci_device->bus->number; - me_device->info.pci.pci_dev_no = PCI_SLOT(pci_device->devfn); - me_device->info.pci.pci_func_no = PCI_FUNC(pci_device->devfn); - - // Get Meilhaus specific device information. - me_device->info.pci.vendor_id = pci_device->vendor; - me_device->info.pci.device_id = pci_device->device; - pci_read_config_byte(pci_device, 0x08, - &me_device->info.pci.hw_revision); - pci_read_config_dword(pci_device, 0x2C, &me_device->info.pci.serial_no); - - // Get the interrupt request number. - me_device->irq = pci_device->irq; - - // Initialize device lock instance. - err = me_dlock_init(&me_device->dlock); - - if (err) { - PERROR("Cannot initialize device lock instance.\n"); - goto ERROR_1; - } - // Initialize subdevice list instance. - me_slist_init(&me_device->slist); - - if (err) { - PERROR("Cannot initialize subdevice list instance.\n"); - goto ERROR_2; - } - // Initialize method pointers. - me_device->me_device_io_irq_start = me_device_io_irq_start; - me_device->me_device_io_irq_wait = me_device_io_irq_wait; - me_device->me_device_io_irq_stop = me_device_io_irq_stop; - me_device->me_device_io_reset_device = me_device_io_reset_device; - me_device->me_device_io_reset_subdevice = me_device_io_reset_subdevice; - me_device->me_device_io_single_config = me_device_io_single_config; - me_device->me_device_io_single_read = me_device_io_single_read; - me_device->me_device_io_single_write = me_device_io_single_write; - me_device->me_device_io_stream_config = me_device_io_stream_config; - me_device->me_device_io_stream_new_values = - me_device_io_stream_new_values; - me_device->me_device_io_stream_read = me_device_io_stream_read; - me_device->me_device_io_stream_start = me_device_io_stream_start; - me_device->me_device_io_stream_status = me_device_io_stream_status; - me_device->me_device_io_stream_stop = me_device_io_stream_stop; - me_device->me_device_io_stream_write = me_device_io_stream_write; - me_device->me_device_lock_device = me_device_lock_device; - me_device->me_device_lock_subdevice = me_device_lock_subdevice; - me_device->me_device_query_description_device = - me_device_query_description_device; - me_device->me_device_query_info_device = me_device_query_info_device; - me_device->me_device_query_name_device = me_device_query_name_device; - me_device->me_device_query_name_device_driver = - me_device_query_name_device_driver; - me_device->me_device_query_number_subdevices = - me_device_query_number_subdevices; - me_device->me_device_query_number_channels = - me_device_query_number_channels; - me_device->me_device_query_number_ranges = - me_device_query_number_ranges; - me_device->me_device_query_range_by_min_max = - me_device_query_range_by_min_max; - me_device->me_device_query_range_info = me_device_query_range_info; - me_device->me_device_query_subdevice_by_type = - me_device_query_subdevice_by_type; - me_device->me_device_query_subdevice_type = - me_device_query_subdevice_type; - me_device->me_device_query_subdevice_caps = - me_device_query_subdevice_caps; - me_device->me_device_query_subdevice_caps_args = - me_device_query_subdevice_caps_args; - me_device->me_device_query_timer = me_device_query_timer; - me_device->me_device_query_version_device_driver = - me_device_query_version_device_driver; - me_device->me_device_config_load = me_device_config_load; - me_device->me_device_destructor = me_device_destructor; - - return 0; - - ERROR_0: - me_dlock_deinit(&me_device->dlock); - - ERROR_1: - pci_release_regions(pci_device); - - ERROR_2: - pci_disable_device(pci_device); - - return 1; -} - -void me_device_deinit(me_device_t *me_device) -{ - PDEBUG("executed.\n"); - - me_slist_deinit(&me_device->slist); - me_dlock_deinit(&me_device->dlock); - - if (me_device->bus_type == ME_BUS_TYPE_PCI) { - pci_release_regions(me_device->info.pci.pci_device); - pci_disable_device(me_device->info.pci.pci_device); - } -/* - else - { - // Must be an USB device. - } -*/ -} --- a/drivers/staging/meilhaus/medevice.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : medevice.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEDEVICE_H_ -#define _MEDEVICE_H_ - -#ifndef KBUILD_MODNAME -# define KBUILD_MODNAME KBUILD_STR(memain) -#endif - -#include -//#include -#include -#include - -#include "metypes.h" -#include "meslist.h" -#include "medlock.h" - -#ifdef __KERNEL__ - -/** - * @brief Defines a pointer type to a PCI constructor function. - */ -typedef struct me_device *(*me_pci_constructor_t) (struct pci_dev *); - -/** - * @brief Defines a pointer type to a ME-4000 PCI constructor function. - */ -#ifdef BOSCH -typedef struct me_device *(*me_bosch_constructor_t) (struct pci_dev *, - int me_bosch_fw); -#endif - -/** - * @brief Defines a pointer type to a USB constructor function. - */ -//typedef struct me_device *(*me_usb_constructor_t)(struct usb_interface *); - -/** - * @brief Defines a pointer type to the dummy constructor function. - */ -typedef struct me_device *(*me_dummy_constructor_t) (unsigned short vendor_id, - unsigned short device_id, - unsigned int serial_no, - int bus_type, - int bus_no, - int dev_no, int func_no); - -//extern me_usb_constructor_t mephisto_s1_constructor __attribute__ ((weak)); - -/** - * @brief Holds the PCI device information. - */ -typedef struct me_pci_info { - struct pci_dev *pci_device; /**< Kernel PCI device structure. */ - uint32_t reg_bases[6]; /**< The base adresses of the PCI bars. */ - uint32_t reg_sizes[6]; /**< The sizes of the PCI bars. */ - - uint32_t pci_bus_no; /**< PCI bus number. */ - uint32_t pci_dev_no; /**< PCI device number. */ - uint32_t pci_func_no; /**< PCI function number. */ - - uint16_t vendor_id; /**< Meilhaus PCI vendor id. */ - uint16_t device_id; /**< Meilhaus device id. */ - uint8_t hw_revision; /**< Hardware revision of the device. */ - uint32_t serial_no; /**< Serial number of the device. */ -} me_pci_info_t; - -/** - * @brief Holds the USB device information. - */ -//typedef struct me_usb_info { -//} me_usb_info_t; - -/** - * @brief The Meilhaus device base class structure. - */ -typedef struct me_device { - /* Attributes */ - struct list_head list; /**< Enables the device to be added to a dynamic list. */ -// int magic; /**< The magic number of the structure. */ - - int bus_type; /**< The descriminator for the union. */ - union { - me_pci_info_t pci; /**< PCI specific device information. */ -// me_usb_info_t usb; /**< USB specific device information. */ - } info; /**< Holds the device information. */ - - int irq; /**< The irq assigned to this device. */ - - me_dlock_t dlock; /**< The device locking structure. */ - me_slist_t slist; /**< The container holding all subdevices belonging to this device. */ - - char *device_name; /**< The name of the Meilhaus device. */ - char *device_description; /**< The description of the Meilhaus device. */ - char *driver_name; /**< The name of the device driver module supporting the device family. */ - - /* Methods */ - int (*me_device_io_irq_start) (struct me_device * device, - struct file * filep, - int subdevice, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags); - - int (*me_device_io_irq_wait) (struct me_device * device, - struct file * filep, - int subdevice, - int channel, - int *irq_count, - int *value, int time_out, int flags); - - int (*me_device_io_irq_stop) (struct me_device * device, - struct file * filep, - int subdevice, int channel, int flags); - - int (*me_device_io_reset_device) (struct me_device * device, - struct file * filep, int flags); - - int (*me_device_io_reset_subdevice) (struct me_device * device, - struct file * filep, - int subdevice, int flags); - - int (*me_device_io_single_config) (struct me_device * device, - struct file * filep, - int subdevice, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, - int trig_edge, int flags); - - int (*me_device_io_single_read) (struct me_device * device, - struct file * filep, - int subdevice, - int channel, - int *value, int time_out, int flags); - - int (*me_device_io_single_write) (struct me_device * device, - struct file * filep, - int subdevice, - int channel, - int value, int time_out, int flags); - - int (*me_device_io_stream_config) (struct me_device * device, - struct file * filep, - int subdevice, - meIOStreamConfig_t * config_list, - int count, - meIOStreamTrigger_t * trigger, - int fifo_irq_threshold, int flags); - - int (*me_device_io_stream_new_values) (struct me_device * device, - struct file * filep, - int subdevice, - int time_out, - int *count, int flags); - - int (*me_device_io_stream_read) (struct me_device * device, - struct file * filep, - int subdevice, - int read_mode, - int *values, int *count, int flags); - - int (*me_device_io_stream_start) (struct me_device * device, - struct file * filep, - int subdevice, - int start_mode, - int time_out, int flags); - - int (*me_device_io_stream_status) (struct me_device * device, - struct file * filep, - int subdevice, - int wait, - int *status, int *count, int flags); - - int (*me_device_io_stream_stop) (struct me_device * device, - struct file * filep, - int subdevice, - int stop_mode, int flags); - - int (*me_device_io_stream_write) (struct me_device * device, - struct file * filep, - int subdevice, - int write_mode, - int *values, int *count, int flags); - - int (*me_device_lock_device) (struct me_device * device, - struct file * filep, int lock, int flags); - - int (*me_device_lock_subdevice) (struct me_device * device, - struct file * filep, - int subdevice, int lock, int flags); - - int (*me_device_query_description_device) (struct me_device * device, - char **description); - - int (*me_device_query_info_device) (struct me_device * device, - int *vendor_id, - int *device_id, - int *serial_no, - int *bus_type, - int *bus_no, - int *dev_no, - int *func_no, int *plugged); - - int (*me_device_query_name_device) (struct me_device * device, - char **name); - - int (*me_device_query_name_device_driver) (struct me_device * device, - char **name); - - int (*me_device_query_number_subdevices) (struct me_device * device, - int *number); - - int (*me_device_query_number_channels) (struct me_device * device, - int subdevice, int *number); - - int (*me_device_query_number_ranges) (struct me_device * device, - int subdevice, - int unit, int *count); - - int (*me_device_query_range_by_min_max) (struct me_device * device, - int subdevice, - int unit, - int *min, - int *max, - int *maxdata, int *range); - - int (*me_device_query_range_info) (struct me_device * device, - int subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); - - int (*me_device_query_subdevice_by_type) (struct me_device * device, - int start_subdevice, - int type, - int subtype, int *subdevice); - - int (*me_device_query_subdevice_type) (struct me_device * device, - int subdevice, - int *type, int *subtype); - - int (*me_device_query_subdevice_caps) (struct me_device * device, - int subdevice, int *caps); - - int (*me_device_query_subdevice_caps_args) (struct me_device * device, - int subdevice, - int cap, - int *args, int count); - - int (*me_device_query_timer) (struct me_device * device, - int subdevice, - int timer, - int *base_frequency, - uint64_t * min_ticks, - uint64_t * max_ticks); - - int (*me_device_query_version_device_driver) (struct me_device * device, - int *version); - - int (*me_device_config_load) (struct me_device * device, - struct file * filep, - me_cfg_device_entry_t * config); - - void (*me_device_destructor) (struct me_device * device); -} me_device_t; - -/** - * @brief Initializes a PCI device base class structure. - * - * @param pci_device The PCI device context as handed over by kernel. - * - * @return 0 on success. - */ -int me_device_pci_init(me_device_t * me_device, struct pci_dev *pci_device); - -/** - * @brief Initializes a USB device base class structure. - * - * @param usb_interface The USB device interface as handed over by kernel. - * - * @return 0 on success. - */ -//int me_device_usb_init(me_device_t *me_device, struct usb_interface *interface); - -/** - * @brief Deinitializes a device base class structure and frees any previously - * requested resources related with this structure. It also frees any subdevice - * instance hold by the subdevice list. - * - * @param me_device The device class to deinitialize. - */ -void me_device_deinit(me_device_t * me_device); - -#endif -#endif --- a/drivers/staging/meilhaus/medlist.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @file me_dlist.c - * - * @brief Implements the device list class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#include "meerror.h" -#include "medefines.h" - -#include "medlist.h" -#include "medebug.h" - -int me_dlist_query_number_devices(struct me_dlist *dlist, int *number) -{ - PDEBUG_LOCKS("called.\n"); - *number = dlist->n; - return ME_ERRNO_SUCCESS; -} - -unsigned int me_dlist_get_number_devices(struct me_dlist *dlist) -{ - PDEBUG_LOCKS("called.\n"); - return dlist->n; -} - -me_device_t *me_dlist_get_device(struct me_dlist * dlist, unsigned int index) -{ - - struct list_head *pos; - me_device_t *device = NULL; - unsigned int i = 0; - - PDEBUG_LOCKS("called.\n"); - - if (index >= dlist->n) { - PERROR("Index out of range.\n"); - return NULL; - } - - list_for_each(pos, &dlist->head) { - if (i == index) { - device = list_entry(pos, me_device_t, list); - break; - } - - ++i; - } - - return device; -} - -void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t *device) -{ - PDEBUG_LOCKS("called.\n"); - - list_add_tail(&device->list, &dlist->head); - ++dlist->n; -} - -me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist) -{ - - struct list_head *last; - me_device_t *device; - - PDEBUG_LOCKS("called.\n"); - - if (list_empty(&dlist->head)) - return NULL; - - last = dlist->head.prev; - - device = list_entry(last, me_device_t, list); - - list_del(last); - - --dlist->n; - - return device; -} - -int me_dlist_init(me_dlist_t *dlist) -{ - PDEBUG_LOCKS("called.\n"); - - INIT_LIST_HEAD(&dlist->head); - dlist->n = 0; - return 0; -} - -void me_dlist_deinit(me_dlist_t *dlist) -{ - - struct list_head *s; - me_device_t *device; - - PDEBUG_LOCKS("called.\n"); - - while (!list_empty(&dlist->head)) { - s = dlist->head.next; - list_del(s); - device = list_entry(s, me_device_t, list); - device->me_device_destructor(device); - } - - dlist->n = 0; -} --- a/drivers/staging/meilhaus/medlist.h +++ /dev/null @@ -1,91 +0,0 @@ -/** - * @file me_dlist.h - * - * @brief Provides the device list class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME_DLIST_H_ -#define _ME_DLIST_H_ - -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The device list container. - */ -typedef struct me_dlist { - struct list_head head; /**< The head of the internal list. */ - unsigned int n; /**< The number of devices in the list. */ -} me_dlist_t; - -/** - * @brief Queries the number of devices currently inside the list. - * - * @param dlist The device list to query. - * @param[out] number The number of devices. - * - * @return ME-iDS error code. - */ -int me_dlist_query_number_devices(struct me_dlist *dlist, int *number); - -/** - * @brief Returns the number of devices currently inside the list. - * - * @param dlist The device list to query. - * - * @return The number of devices in the list. - */ -unsigned int me_dlist_get_number_devices(struct me_dlist *dlist); - -/** - * @brief Get a device by index. - * - * @param dlist The device list to query. - * @param index The index of the device to get in the list. - * - * @return The device at index if available.\n - * NULL if the index is out of range. - */ -me_device_t *me_dlist_get_device(struct me_dlist *dlist, unsigned int index); - -/** - * @brief Adds a device to the tail of the list. - * - * @param dlist The device list to add a device to. - * @param device The device to add to the list. - */ -void me_dlist_add_device_tail(struct me_dlist *dlist, me_device_t * device); - -/** - * @brief Removes a device from the tail of the list. - * - * @param dlist The device list. - * - * @return Pointer to the removed subdeivce.\n - * NULL in cases where the list was empty. - */ -me_device_t *me_dlist_del_device_tail(struct me_dlist *dlist); - -/** - * @brief Initializes a device list structure. - * - * @param lock The device list structure to initialize. - * @return 0 on success. - */ -int me_dlist_init(me_dlist_t * dlist); - -/** - * @brief Deinitializes a device list structure and destructs every device in it. - * - * @param dlist The device list structure to deinitialize. - * @return 0 on success. - */ -void me_dlist_deinit(me_dlist_t * dlist); - -#endif -#endif --- a/drivers/staging/meilhaus/medlock.c +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @file medlock.c - * - * @brief Implements the device lock class. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#include - -#include "medefines.h" -#include "meerror.h" - -#include "medebug.h" -#include "meslist.h" -#include "mesubdevice.h" -#include "medlock.h" - -int me_dlock_enter(struct me_dlock *dlock, struct file *filep) -{ - PDEBUG_LOCKS("executed.\n"); - - spin_lock(&dlock->spin_lock); - - if ((dlock->filep) != NULL && (dlock->filep != filep)) { - PERROR("Device is locked by another process.\n"); - spin_unlock(&dlock->spin_lock); - return ME_ERRNO_LOCKED; - } - - dlock->count++; - - spin_unlock(&dlock->spin_lock); - - return ME_ERRNO_SUCCESS; -} - -int me_dlock_exit(struct me_dlock *dlock, struct file *filep) -{ - PDEBUG_LOCKS("executed.\n"); - - spin_lock(&dlock->spin_lock); - dlock->count--; - spin_unlock(&dlock->spin_lock); - - return ME_ERRNO_SUCCESS; -} - -int me_dlock_lock(struct me_dlock *dlock, - struct file *filep, int lock, int flags, me_slist_t *slist) -{ - int err = ME_ERRNO_SUCCESS; - int i; - me_subdevice_t *subdevice; - - PDEBUG_LOCKS("executed.\n"); - - spin_lock(&dlock->spin_lock); - - switch (lock) { - - case ME_LOCK_RELEASE: - if ((dlock->filep == filep) || (dlock->filep == NULL)) { - dlock->filep = NULL; - - /* Unlock all possibly locked subdevices. */ - - for (i = 0; i < me_slist_get_number_subdevices(slist); - i++) { - subdevice = me_slist_get_subdevice(slist, i); - - if (subdevice) - err = - subdevice-> - me_subdevice_lock_subdevice - (subdevice, filep, ME_LOCK_RELEASE, - flags); - else - err = ME_ERRNO_INTERNAL; - } - } - - break; - - case ME_LOCK_SET: - if (dlock->count) { - PERROR("Device is used by another process.\n"); - err = ME_ERRNO_USED; - } else if ((dlock->filep != NULL) && (dlock->filep != filep)) { - PERROR("Device is locked by another process.\n"); - err = ME_ERRNO_LOCKED; - } else if (dlock->filep == NULL) { - /* Check any subdevice is locked by another process. */ - - for (i = 0; i < me_slist_get_number_subdevices(slist); - i++) { - subdevice = me_slist_get_subdevice(slist, i); - - if (subdevice) { - if ((err = - subdevice-> - me_subdevice_lock_subdevice - (subdevice, filep, ME_LOCK_CHECK, - flags))) { - PERROR - ("A subdevice is locked by another process.\n"); - break; - } - } else { - err = ME_ERRNO_INTERNAL; - } - } - - /* If no subdevices are locked by other processes, - we can take ownership of the device. Otherwise we jump ahead. */ - if (!err) - dlock->filep = filep; - } - - break; - - case ME_LOCK_CHECK: - if (dlock->count) { - err = ME_ERRNO_USED; - } else if ((dlock->filep != NULL) && (dlock->filep != filep)) { - err = ME_ERRNO_LOCKED; - } else if (dlock->filep == NULL) { - for (i = 0; i < me_slist_get_number_subdevices(slist); - i++) { - subdevice = me_slist_get_subdevice(slist, i); - - if (subdevice) { - if ((err = - subdevice-> - me_subdevice_lock_subdevice - (subdevice, filep, ME_LOCK_CHECK, - flags))) { - PERROR - ("A subdevice is locked by another process.\n"); - break; - } - } else { - err = ME_ERRNO_INTERNAL; - } - } - } - - break; - - default: - PERROR("Invalid lock.\n"); - - err = ME_ERRNO_INVALID_LOCK; - - break; - } - - spin_unlock(&dlock->spin_lock); - - return err; -} - -void me_dlock_deinit(struct me_dlock *dlock) -{ - PDEBUG_LOCKS("executed.\n"); -} - -int me_dlock_init(me_dlock_t *dlock) -{ - PDEBUG_LOCKS("executed.\n"); - - dlock->filep = NULL; - dlock->count = 0; - spin_lock_init(&dlock->spin_lock); - - return 0; -} --- a/drivers/staging/meilhaus/medlock.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file medlock.h - * - * @brief Provides the device lock class. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _MEDLOCK_H_ -#define _MEDLOCK_H_ - -#include - -#ifdef __KERNEL__ - -/** - * @brief The device lock class. - */ -typedef struct me_dlock { - struct file *filep; /**< Pointer to file structure holding the device. */ - int count; /**< Number of tasks which are inside the device. */ - spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */ -} me_dlock_t; - -/** - * @brief Tries to enter a device. - * - * @param dlock The device lock instance. - * @param filep The file structure identifying the calling process. - * - * @return 0 on success. - */ -int me_dlock_enter(struct me_dlock *dlock, struct file *filep); - -/** - * @brief Exits a device. - * - * @param dlock The device lock instance. - * @param filep The file structure identifying the calling process. - * - * @return 0 on success. - */ -int me_dlock_exit(struct me_dlock *dlock, struct file *filep); - -/** - * @brief Tries to perform a locking action on a device. - * - * @param dlock The device lock instance. - * @param filep The file structure identifying the calling process. - * @param The action to be done. - * @param flags Flags from user space. - * @param slist The subdevice list of the device. - * - * @return 0 on success. - */ -int me_dlock_lock(struct me_dlock *dlock, - struct file *filep, int lock, int flags, me_slist_t * slist); - -/** - * @brief Initializes a lock structure. - * - * @param dlock The lock structure to initialize. - * @return 0 on success. - */ -int me_dlock_init(me_dlock_t * dlock); - -/** - * @brief Deinitializes a lock structure. - * - * @param dlock The lock structure to deinitialize. - * @return 0 on success. - */ -void me_dlock_deinit(me_dlock_t * dlock); - -#endif -#endif --- a/drivers/staging/meilhaus/medriver.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : medriver.h - * Author : GG (Guenter Gebhardt) - * Author: Krzysztof Gantzke - */ - -#ifndef _MEDRIVER_H_ -#define _MEDRIVER_H_ - -#include "metypes.h" -#include "meerror.h" -#include "medefines.h" - -#ifdef __cplusplus -extern "C" { -#endif - - /*=========================================================================== - Functions to access the driver system - =========================================================================*/ - - int meOpen(int iFlags); - int meClose(int iFlags); - - int meLockDriver(int iLock, int iFlags); - int meLockDevice(int iDevice, int iLock, int iFlags); - int meLockSubdevice(int iDevice, int iSubdevice, int iLock, int iFlags); - - /*=========================================================================== - Error handling functions - =========================================================================*/ - - int meErrorGetLastMessage(char *pcErrorMsg, int iCount); - int meErrorGetMessage(int iErrorCode, char *pcErrorMsg, int iCount); - int meErrorSetDefaultProc(int iSwitch); - int meErrorSetUserProc(meErrorCB_t pErrorProc); - - - /*=========================================================================== - Functions to perform I/O on a device - =========================================================================*/ - - int meIOIrqSetCallback( - int iDevice, - int iSubdevice, - meIOIrqCB_t pCallback, - void *pCallbackContext, - int iFlags); - int meIOIrqStart( - int iDevice, - int iSubdevice, - int iChannel, - int iIrqSource, - int iIrqEdge, - int iIrqArg, - int iFlags); - int meIOIrqStop( - int iDevice, - int iSubdevice, - int iChannel, - int iFlags); - int meIOIrqWait( - int iDevice, - int iSubdevice, - int iChannel, - int *piIrqCount, - int *piValue, - int iTimeOut, - int iFlags); - - int meIOResetDevice(int iDevice, int iFlags); - int meIOResetSubdevice(int iDevice, int iSubdevice, int iFlags); - - int meIOStreamFrequencyToTicks( - int iDevice, - int iSubdevice, - int iTimer, - double *pdFrequency, - int *piTicksLow, - int *piTicksHigh, - int iFlags); - - int meIOSingleConfig( - int iDevice, - int iSubdevice, - int iChannel, - int iSingleConfig, - int iRef, - int iTrigChan, - int iTrigType, - int iTrigEdge, - int iFlags); - int meIOSingle(meIOSingle_t *pSingleList, int iCount, int iFlags); - - int meIOStreamConfig( - int iDevice, - int iSubdevice, - meIOStreamConfig_t *pConfigList, - int iCount, - meIOStreamTrigger_t *pTrigger, - int iFifoIrqThreshold, - int iFlags); - int meIOStreamNewValues( - int iDevice, - int iSubdevice, - int iTimeOut, - int *piCount, - int iFlags); - int meIOStreamRead( - int iDevice, - int iSubdevice, - int iReadMode, - int *piValues, - int *piCount, - int iFlags); - int meIOStreamWrite( - int iDevice, - int iSubdevice, - int iWriteMode, - int *piValues, - int *piCount, - int iFlags); - int meIOStreamStart(meIOStreamStart_t *pStartList, int iCount, int iFlags); - int meIOStreamStop(meIOStreamStop_t *pStopList, int iCount, int iFlags); - int meIOStreamStatus( - int iDevice, - int iSubdevice, - int iWait, - int *piStatus, - int *piCount, - int iFlags); - int meIOStreamSetCallbacks( - int iDevice, - int iSubdevice, - meIOStreamCB_t pStartCB, - void *pStartCBContext, - meIOStreamCB_t pNewValuesCB, - void *pNewValuesCBContext, - meIOStreamCB_t pEndCB, - void *pEndCBContext, - int iFlags); - int meIOStreamTimeToTicks( - int iDevice, - int iSubdevice, - int iTimer, - double *pdTime, - int *piTicksLow, - int *piTicksHigh, - int iFlags); - - - /*=========================================================================== - Functions to query the driver system - =========================================================================*/ - - int meQueryDescriptionDevice(int iDevice, char *pcDescription, int iCount); - - int meQueryInfoDevice( - int iDevice, - int *piVendorId, - int *piDeviceId, - int *piSerialNo, - int *piBusType, - int *piBusNo, - int *piDevNo, - int *piFuncNo, - int *piPlugged); - - int meQueryNameDevice(int iDevice, char *pcName, int iCount); - int meQueryNameDeviceDriver(int iDevice, char *pcName, int iCount); - - int meQueryNumberDevices(int *piNumber); - int meQueryNumberSubdevices(int iDevice, int *piNumber); - int meQueryNumberChannels(int iDevice, int iSubdevice, int *piNumber); - int meQueryNumberRanges( - int iDevice, - int iSubdevice, - int iUnit, - int *piNumber); - - int meQueryRangeByMinMax( - int iDevice, - int iSubdevice, - int iUnit, - double *pdMin, - double *pdMax, - int *piMaxData, - int *piRange); - int meQueryRangeInfo( - int iDevice, - int iSubdevice, - int iRange, - int *piUnit, - double *pdMin, - double *pdMax, - int *piMaxData); - - int meQuerySubdeviceByType( - int iDevice, - int iStartSubdevice, - int iType, - int iSubtype, - int *piSubdevice); - int meQuerySubdeviceType( - int iDevice, - int iSubdevice, - int *piType, - int *piSubtype); - int meQuerySubdeviceCaps( - int iDevice, - int iSubdevice, - int *piCaps); - int meQuerySubdeviceCapsArgs( - int iDevice, - int iSubdevice, - int iCap, - int *piArgs, - int iCount); - - int meQueryVersionLibrary(int *piVersion); - int meQueryVersionMainDriver(int *piVersion); - int meQueryVersionDeviceDriver(int iDevice, int *piVersion); - - - /*=========================================================================== - Common utility functions - =========================================================================*/ - - int meUtilityExtractValues( - int iChannel, - int *piAIBuffer, - int iAIBufferCount, - meIOStreamConfig_t *pConfigList, - int iConfigListCount, - int *piChanBuffer, - int *piChanBufferCount); - int meUtilityDigitalToPhysical( - double dMin, - double dMax, - int iMaxData, - int iData, - int iModuleType, - double dRefValue, - double *pdPhysical); - int meUtilityDigitalToPhysicalV( - double dMin, - double dMax, - int iMaxData, - int *piDataBuffer, - int iCount, - int iModuleType, - double dRefValue, - double *pdPhysicalBuffer); - int meUtilityPhysicalToDigital( - double dMin, - double dMax, - int iMaxData, - double dPhysical, - int *piData); - int meUtilityPWMStart( - int iDevice, - int iSubdevice1, - int iSubdevice2, - int iSubdevice3, - int iRef, - int iPrescaler, - int iDutyCycle, - int iFlag); - int meUtilityPWMStop(int iDevice, - int iSubdevice1); - int meUtilityPWMRestart( - int iDevice, - int iSubdevice1, - int iRef, - int iPrescaler); - - - /*=========================================================================== - Load configuration from file into driver system - =========================================================================*/ - - int meConfigLoad(char *pcConfigFile); - - - /*=========================================================================== - Functions to query a remote driver system - =========================================================================*/ - - int meRQueryDescriptionDevice( - char *location, - int iDevice, - char *pcDescription, - int iCount); - - int meRQueryInfoDevice( - char *location, - int iDevice, - int *piVendorId, - int *piDeviceId, - int *piSerialNo, - int *piBusType, - int *piBusNo, - int *piDevNo, - int *piFuncNo, - int *piPlugged); - - int meRQueryNameDevice( - char *location, - int iDevice, - char *pcName, - int iCount); - - int meRQueryNumberDevices(char *location, int *piNumber); - int meRQueryNumberSubdevices(char *location, int iDevice, int *piNumber); - int meRQueryNumberChannels( - char *location, - int iDevice, - int iSubdevice, - int *piNumber); - int meRQueryNumberRanges( - char *location, - int iDevice, - int iSubdevice, - int iUnit, - int *piNumber); - - int meRQueryRangeInfo( - char *location, - int iDevice, - int iSubdevice, - int iRange, - int *piUnit, - double *pdMin, - double *pdMax, - int *piMaxData); - - int meRQuerySubdeviceType( - char *location, - int iDevice, - int iSubdevice, - int *piType, - int *piSubtype); - -#ifdef __cplusplus -} -#endif - -#endif --- a/drivers/staging/meilhaus/medummy.c +++ /dev/null @@ -1,1264 +0,0 @@ -/* Device driver for Meilhaus ME-DUMMY devices. - * =========================================== - * - * Copyright (C) 2005 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. - */ - -/* - * User application could also include the kernel header files. But the - * real kernel functions are protected by #ifdef __KERNEL__. - */ -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * This must be defined before module.h is included. Not needed, when - * it is a built in driver. - */ -#ifndef MODULE -# define MODULE -#endif - -#include -#include - -#include "meerror.h" -#include "meinternal.h" - -#include "meids.h" -#include "mecommon.h" -#include "medevice.h" -#include "medebug.h" - -#include "medummy.h" - -static int medummy_io_irq_start(me_device_t *device, - struct file *filep, - int subdevice, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_irq_wait(me_device_t *device, - struct file *filep, - int subdevice, - int channel, - int *irq_count, - int *value, int timeout, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_irq_stop(me_device_t *device, - struct file *filep, - int subdevice, int channel, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_reset_device(me_device_t *device, - struct file *filep, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_reset_subdevice(me_device_t *device, - struct file *filep, - int subdevice, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_single_config(me_device_t *device, - struct file *filep, - int subdevice, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, int trig_edge, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_single_read(me_device_t *device, - struct file *filep, - int subdevice, - int channel, - int *value, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_single_write(me_device_t *device, - struct file *filep, - int subdevice, - int channel, - int value, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_config(me_device_t *device, - struct file *filep, - int subdevice, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_new_values(me_device_t *device, - struct file *filep, - int subdevice, - int timeout, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_read(me_device_t *device, - struct file *filep, - int subdevice, - int read_mode, - int *values, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_start(me_device_t *device, - struct file *filep, - int subdevice, - int start_mode, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_status(me_device_t *device, - struct file *filep, - int subdevice, - int wait, - int *status, int *values, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_stop(me_device_t *device, - struct file *filep, - int subdevice, int stop_mode, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_io_stream_write(me_device_t *device, - struct file *filep, - int subdevice, - int write_mode, - int *values, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_lock_device(me_device_t *device, - struct file *filep, int lock, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_lock_subdevice(me_device_t *device, - struct file *filep, - int subdevice, int lock, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_description_device(me_device_t *device, - char **description) -{ - medummy_device_t *instance = (medummy_device_t *) device; - - PDEBUG("executed.\n"); - -// if (instance->magic != MEDUMMY_MAGIC_NUMBER) -// { -// PERROR("Wrong magic number.\n"); -// return ME_ERRNO_INTERNAL; -// } - - switch (instance->device_id) { - - case PCI_DEVICE_ID_MEILHAUS_ME1000: - - case PCI_DEVICE_ID_MEILHAUS_ME1000_A: - - case PCI_DEVICE_ID_MEILHAUS_ME1000_B: - *description = ME1000_DESCRIPTION_DEVICE_ME1000; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1400: - *description = ME1400_DESCRIPTION_DEVICE_ME1400; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140A: - *description = ME1400_DESCRIPTION_DEVICE_ME1400A; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140B: - *description = ME1400_DESCRIPTION_DEVICE_ME1400B; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - *description = ME1400_DESCRIPTION_DEVICE_ME1400E; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - *description = ME1400_DESCRIPTION_DEVICE_ME1400EA; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - *description = ME1400_DESCRIPTION_DEVICE_ME1400EB; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - *description = ME1400_DESCRIPTION_DEVICE_ME1400C; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140D: - *description = ME1400_DESCRIPTION_DEVICE_ME1400D; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: - *description = ME1600_DESCRIPTION_DEVICE_ME16004U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: - *description = ME1600_DESCRIPTION_DEVICE_ME16008U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: - *description = ME1600_DESCRIPTION_DEVICE_ME160012U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: - *description = ME1600_DESCRIPTION_DEVICE_ME160016U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: - *description = ME1600_DESCRIPTION_DEVICE_ME160016U8I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - *description = ME4600_DESCRIPTION_DEVICE_ME4610; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4650: - *description = ME4600_DESCRIPTION_DEVICE_ME4650; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660: - *description = ME4600_DESCRIPTION_DEVICE_ME4660; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - *description = ME4600_DESCRIPTION_DEVICE_ME4660I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660S: - *description = ME4600_DESCRIPTION_DEVICE_ME4660S; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660IS: - *description = ME4600_DESCRIPTION_DEVICE_ME4660IS; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670: - *description = ME4600_DESCRIPTION_DEVICE_ME4670; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - *description = ME4600_DESCRIPTION_DEVICE_ME4670I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - *description = ME4600_DESCRIPTION_DEVICE_ME4670S; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - *description = ME4600_DESCRIPTION_DEVICE_ME4670IS; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680: - *description = ME4600_DESCRIPTION_DEVICE_ME4680; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - *description = ME4600_DESCRIPTION_DEVICE_ME4680I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - *description = ME4600_DESCRIPTION_DEVICE_ME4680S; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - *description = ME4600_DESCRIPTION_DEVICE_ME4680IS; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6004: - *description = ME6000_DESCRIPTION_DEVICE_ME60004; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6008: - *description = ME6000_DESCRIPTION_DEVICE_ME60008; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME600F: - *description = ME6000_DESCRIPTION_DEVICE_ME600016; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6014: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6018: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME601F: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6034: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6038: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME603F: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6104: - *description = ME6000_DESCRIPTION_DEVICE_ME61004; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6108: - *description = ME6000_DESCRIPTION_DEVICE_ME61008; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME610F: - *description = ME6000_DESCRIPTION_DEVICE_ME610016; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6114: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6118: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME611F: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6134: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6138: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME613F: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6044: - *description = ME6000_DESCRIPTION_DEVICE_ME60004DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6048: - *description = ME6000_DESCRIPTION_DEVICE_ME60008DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME604F: - *description = ME6000_DESCRIPTION_DEVICE_ME600016DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6054: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6058: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME605F: - *description = ME6000_DESCRIPTION_DEVICE_ME6000I16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6074: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6078: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME607F: - *description = ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6144: - *description = ME6000_DESCRIPTION_DEVICE_ME61004DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6148: - *description = ME6000_DESCRIPTION_DEVICE_ME61008DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME614F: - *description = ME6000_DESCRIPTION_DEVICE_ME610016DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6154: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6158: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME615F: - *description = ME6000_DESCRIPTION_DEVICE_ME6100I16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6174: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6178: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME617F: - *description = ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6259: - *description = ME6000_DESCRIPTION_DEVICE_ME6200I9DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6359: - *description = ME6000_DESCRIPTION_DEVICE_ME6300I9DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0630: - *description = ME0600_DESCRIPTION_DEVICE_ME0630; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - *description = ME8100_DESCRIPTION_DEVICE_ME8100A; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - *description = ME8100_DESCRIPTION_DEVICE_ME8100B; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0940: - *description = ME0900_DESCRIPTION_DEVICE_ME0940; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0950: - *description = ME0900_DESCRIPTION_DEVICE_ME0950; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0960: - *description = ME0900_DESCRIPTION_DEVICE_ME0960; - - break; -/* - case USB_DEVICE_ID_MEPHISTO_S1: - *description = MEPHISTO_S1_DESCRIPTION_DEVICE; - - break; -*/ - default: - *description = EMPTY_DESCRIPTION_DEVICE; - PERROR("Invalid device id in device info.\n"); - - return ME_ERRNO_INTERNAL; - } - - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_info_device(me_device_t *device, - int *vendor_id, - int *device_id, - int *serial_no, - int *bus_type, - int *bus_no, - int *dev_no, int *func_no, int *plugged) -{ - medummy_device_t *instance = (medummy_device_t *) device; - - PDEBUG("executed.\n"); - -// if (instance->magic != MEDUMMY_MAGIC_NUMBER) -// { -// PERROR("Wrong magic number.\n"); -// return ME_ERRNO_INTERNAL; -// } - - *vendor_id = instance->vendor_id; - *device_id = instance->device_id; - *serial_no = instance->serial_no; - *bus_type = instance->bus_type; - *bus_no = instance->bus_no; - *dev_no = instance->dev_no; - *func_no = instance->func_no; - *plugged = ME_PLUGGED_OUT; - - return ME_ERRNO_SUCCESS; -} - -static int medummy_query_name_device_driver(me_device_t *device, char **name) -{ - PDEBUG("executed.\n"); - *name = MEDUMMY_NAME_DRIVER; - return ME_ERRNO_SUCCESS; -} - -static int medummy_query_name_device(me_device_t *device, char **name) -{ - medummy_device_t *instance = (medummy_device_t *) device; - - PDEBUG("executed.\n"); - -// // // if (instance->magic != MEDUMMY_MAGIC_NUMBER) -// // // { -// // // PERROR("Wrong magic number.\n"); -// // // return ME_ERRNO_INTERNAL; -// // // } - - switch (instance->device_id) { - - case PCI_DEVICE_ID_MEILHAUS_ME1000: - - case PCI_DEVICE_ID_MEILHAUS_ME1000_A: - - case PCI_DEVICE_ID_MEILHAUS_ME1000_B: - *name = ME1000_NAME_DEVICE_ME1000; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1400: - *name = ME1400_NAME_DEVICE_ME1400; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140A: - *name = ME1400_NAME_DEVICE_ME1400A; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140B: - *name = ME1400_NAME_DEVICE_ME1400B; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14E0: - *name = ME1400_NAME_DEVICE_ME1400E; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EA: - *name = ME1400_NAME_DEVICE_ME1400EA; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME14EB: - *name = ME1400_NAME_DEVICE_ME1400EB; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140C: - *name = ME1400_NAME_DEVICE_ME1400C; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME140D: - *name = ME1400_NAME_DEVICE_ME1400D; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_4U: - *name = ME1600_NAME_DEVICE_ME16004U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_8U: - *name = ME1600_NAME_DEVICE_ME16008U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_12U: - *name = ME1600_NAME_DEVICE_ME160012U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U: - *name = ME1600_NAME_DEVICE_ME160016U; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I: - *name = ME1600_NAME_DEVICE_ME160016U8I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4610: - *name = ME4600_NAME_DEVICE_ME4610; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4650: - *name = ME4600_NAME_DEVICE_ME4650; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660: - *name = ME4600_NAME_DEVICE_ME4660; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4660I: - *name = ME4600_NAME_DEVICE_ME4660I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670: - *name = ME4600_NAME_DEVICE_ME4670; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670I: - *name = ME4600_NAME_DEVICE_ME4670I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670S: - *name = ME4600_NAME_DEVICE_ME4670S; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4670IS: - *name = ME4600_NAME_DEVICE_ME4670IS; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680: - *name = ME4600_NAME_DEVICE_ME4680; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680I: - *name = ME4600_NAME_DEVICE_ME4680I; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680S: - *name = ME4600_NAME_DEVICE_ME4680S; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME4680IS: - *name = ME4600_NAME_DEVICE_ME4680IS; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6004: - *name = ME6000_NAME_DEVICE_ME60004; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6008: - *name = ME6000_NAME_DEVICE_ME60008; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME600F: - *name = ME6000_NAME_DEVICE_ME600016; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6014: - *name = ME6000_NAME_DEVICE_ME6000I4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6018: - *name = ME6000_NAME_DEVICE_ME6000I8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME601F: - *name = ME6000_NAME_DEVICE_ME6000I16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6034: - *name = ME6000_NAME_DEVICE_ME6000ISLE4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6038: - *name = ME6000_NAME_DEVICE_ME6000ISLE8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME603F: - *name = ME6000_NAME_DEVICE_ME6000ISLE16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6104: - *name = ME6000_NAME_DEVICE_ME61004; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6108: - *name = ME6000_NAME_DEVICE_ME61008; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME610F: - *name = ME6000_NAME_DEVICE_ME610016; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6114: - *name = ME6000_NAME_DEVICE_ME6100I4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6118: - *name = ME6000_NAME_DEVICE_ME6100I8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME611F: - *name = ME6000_NAME_DEVICE_ME6100I16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6134: - *name = ME6000_NAME_DEVICE_ME6100ISLE4; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6138: - *name = ME6000_NAME_DEVICE_ME6100ISLE8; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME613F: - *name = ME6000_NAME_DEVICE_ME6100ISLE16; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6044: - *name = ME6000_NAME_DEVICE_ME60004DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6048: - *name = ME6000_NAME_DEVICE_ME60008DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME604F: - *name = ME6000_NAME_DEVICE_ME600016DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6054: - *name = ME6000_NAME_DEVICE_ME6000I4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6058: - *name = ME6000_NAME_DEVICE_ME6000I8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME605F: - *name = ME6000_NAME_DEVICE_ME6000I16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6074: - *name = ME6000_NAME_DEVICE_ME6000ISLE4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6078: - *name = ME6000_NAME_DEVICE_ME6000ISLE8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME607F: - *name = ME6000_NAME_DEVICE_ME6000ISLE16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6144: - *name = ME6000_NAME_DEVICE_ME61004DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6148: - *name = ME6000_NAME_DEVICE_ME61008DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME614F: - *name = ME6000_NAME_DEVICE_ME610016DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6154: - *name = ME6000_NAME_DEVICE_ME6100I4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6158: - *name = ME6000_NAME_DEVICE_ME6100I8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME615F: - *name = ME6000_NAME_DEVICE_ME6100I16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6174: - *name = ME6000_NAME_DEVICE_ME6100ISLE4DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME6178: - *name = ME6000_NAME_DEVICE_ME6100ISLE8DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME617F: - *name = ME6000_NAME_DEVICE_ME6100ISLE16DIO; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0630: - *name = ME0600_NAME_DEVICE_ME0630; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_A: - *name = ME8100_NAME_DEVICE_ME8100A; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME8100_B: - *name = ME8100_NAME_DEVICE_ME8100B; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0940: - *name = ME0900_NAME_DEVICE_ME0940; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0950: - *name = ME0900_NAME_DEVICE_ME0950; - - break; - - case PCI_DEVICE_ID_MEILHAUS_ME0960: - *name = ME0900_NAME_DEVICE_ME0960; - - break; -/* - case USB_DEVICE_ID_MEPHISTO_S1: - *name = MEPHISTO_S1_NAME_DEVICE; - - break; -*/ - default: - *name = EMPTY_NAME_DEVICE; - PERROR("Invalid PCI device id.\n"); - - return ME_ERRNO_INTERNAL; - } - - return ME_ERRNO_SUCCESS; -} - -static int medummy_query_number_subdevices(me_device_t *device, int *number) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_number_channels(me_device_t *device, - int subdevice, int *number) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_number_ranges(me_device_t *device, - int subdevice, int unit, int *count) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_subdevice_type(me_device_t *device, - int subdevice, int *type, int *subtype) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_subdevice_caps(me_device_t *device, - int subdevice, int *caps) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_subdevice_caps_args(me_device_t *device, - int subdevice, - int cap, int *args, int count) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int medummy_query_subdevice_by_type(me_device_t *device, - int start_subdevice, - int type, - int subtype, int *subdevice) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_range_by_min_max(me_device_t *device, - int subdevice, - int unit, - int *min, - int *max, int *maxdata, int *range) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_range_info(me_device_t *device, - int subdevice, - int range, - int *unit, int *min, int *max, int *maxdata) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -int medummy_query_timer(me_device_t *device, - int subdevice, - int timer, - int *base_frequency, - uint64_t *min_ticks, uint64_t *max_ticks) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_DEVICE_UNPLUGGED; -} - -static int medummy_query_version_device_driver(me_device_t *device, - int *version) -{ - PDEBUG("executed.\n"); - - *version = ME_VERSION_DRIVER; - return ME_ERRNO_SUCCESS; -} - -static void medummy_destructor(me_device_t *device) -{ - PDEBUG("executed.\n"); - kfree(device); -} - -static int init_device_info(unsigned short vendor_id, - unsigned short device_id, - unsigned int serial_no, - int bus_type, - int bus_no, - int dev_no, - int func_no, medummy_device_t *instance) -{ - PDEBUG("executed.\n"); - -// instance->magic = MEDUMMY_MAGIC_NUMBER; - instance->vendor_id = vendor_id; - instance->device_id = device_id; - instance->serial_no = serial_no; - instance->bus_type = bus_type; - instance->bus_no = bus_no; - instance->dev_no = dev_no; - instance->func_no = func_no; - - return 0; -} - -static int medummy_config_load(me_device_t *device, struct file *filep, - me_cfg_device_entry_t *config) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_SUCCESS; -} - -static int init_device_instance(me_device_t *device) -{ - PDEBUG("executed.\n"); - - INIT_LIST_HEAD(&device->list); - - device->me_device_io_irq_start = medummy_io_irq_start; - device->me_device_io_irq_wait = medummy_io_irq_wait; - device->me_device_io_irq_stop = medummy_io_irq_stop; - device->me_device_io_reset_device = medummy_io_reset_device; - device->me_device_io_reset_subdevice = medummy_io_reset_subdevice; - device->me_device_io_single_config = medummy_io_single_config; - device->me_device_io_single_read = medummy_io_single_read; - device->me_device_io_single_write = medummy_io_single_write; - device->me_device_io_stream_config = medummy_io_stream_config; - device->me_device_io_stream_new_values = medummy_io_stream_new_values; - device->me_device_io_stream_read = medummy_io_stream_read; - device->me_device_io_stream_start = medummy_io_stream_start; - device->me_device_io_stream_status = medummy_io_stream_status; - device->me_device_io_stream_stop = medummy_io_stream_stop; - device->me_device_io_stream_write = medummy_io_stream_write; - - device->me_device_lock_device = medummy_lock_device; - device->me_device_lock_subdevice = medummy_lock_subdevice; - - device->me_device_query_description_device = - medummy_query_description_device; - device->me_device_query_info_device = medummy_query_info_device; - device->me_device_query_name_device_driver = - medummy_query_name_device_driver; - device->me_device_query_name_device = medummy_query_name_device; - - device->me_device_query_number_subdevices = - medummy_query_number_subdevices; - device->me_device_query_number_channels = medummy_query_number_channels; - device->me_device_query_number_ranges = medummy_query_number_ranges; - - device->me_device_query_range_by_min_max = - medummy_query_range_by_min_max; - device->me_device_query_range_info = medummy_query_range_info; - - device->me_device_query_subdevice_type = medummy_query_subdevice_type; - device->me_device_query_subdevice_by_type = - medummy_query_subdevice_by_type; - device->me_device_query_subdevice_caps = medummy_query_subdevice_caps; - device->me_device_query_subdevice_caps_args = - medummy_query_subdevice_caps_args; - - device->me_device_query_timer = medummy_query_timer; - - device->me_device_query_version_device_driver = - medummy_query_version_device_driver; - - device->me_device_destructor = medummy_destructor; - device->me_device_config_load = medummy_config_load; - return 0; -} - -me_device_t *medummy_constructor(unsigned short vendor_id, - unsigned short device_id, - unsigned int serial_no, - int bus_type, - int bus_no, int dev_no, int func_no) -{ - int result = 0; - medummy_device_t *instance; - - PDEBUG("executed.\n"); - - /* Allocate structure for device attributes */ - instance = kmalloc(sizeof(medummy_device_t), GFP_KERNEL); - - if (!instance) { - PERROR("Can't get memory for device instance.\n"); - return NULL; - } - - memset(instance, 0, sizeof(medummy_device_t)); - - /* Initialize device info */ - result = init_device_info(vendor_id, - device_id, - serial_no, - bus_type, bus_no, dev_no, func_no, instance); - - if (result) { - PERROR("Cannot init baord info.\n"); - kfree(instance); - return NULL; - } - - /* Initialize device instance */ - result = init_device_instance((me_device_t *) instance); - - if (result) { - PERROR("Cannot init baord info.\n"); - kfree(instance); - return NULL; - } - - return (me_device_t *) instance; -} -EXPORT_SYMBOL(medummy_constructor); - -// Init and exit of module. - -static int __init dummy_init(void) -{ - PDEBUG("executed.\n"); - return 0; -} - -static void __exit dummy_exit(void) -{ - PDEBUG("executed.\n"); -} - -module_init(dummy_init); - -module_exit(dummy_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR("Guenter Gebhardt "); -MODULE_DESCRIPTION("Device Driver Module for Meilhaus ME-DUMMY Devices"); -MODULE_SUPPORTED_DEVICE("Meilhaus ME-DUMMY Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/medummy.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : medummy.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEDUMMY_H_ -#define _MEDUMMY_H_ - -#include "metypes.h" -#include "medefines.h" -#include "medevice.h" - -#ifdef __KERNEL__ - -#define MEDUMMY_MAGIC_NUMBER 0xDDDD - -typedef struct medummy_device { - me_device_t base; /**< The Meilhaus device base class. */ -// int magic; /**< The magic number of the structure */ - unsigned short vendor_id; /**< Vendor ID */ - unsigned short device_id; /**< Device ID */ - unsigned int serial_no; /**< Serial number of the device */ - int bus_type; /**< Bus type */ - int bus_no; /**< Bus number */ - int dev_no; /**< Device number */ - int func_no; /**< Function number */ -} medummy_device_t; - -me_device_t *medummy_constructor(unsigned short vendor_id, - unsigned short device_id, - unsigned int serial_no, - int bus_type, - int bus_no, - int dev_no, - int func_no) __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/meerror.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : meerror.h - * Author : GG (Guenter Gebhardt) - * Author : KG (Krzysztof Gantzke) - */ - -#ifndef _MEERROR_H_ -#define _MEERROR_H_ - -extern char *meErrorMsgTable[]; - -#define ME_ERRNO_SUCCESS 0 -#define ME_ERRNO_INVALID_DEVICE 1 -#define ME_ERRNO_INVALID_SUBDEVICE 2 -#define ME_ERRNO_INVALID_CHANNEL 3 -#define ME_ERRNO_INVALID_SINGLE_CONFIG 4 -#define ME_ERRNO_INVALID_REF 5 -#define ME_ERRNO_INVALID_TRIG_CHAN 6 -#define ME_ERRNO_INVALID_TRIG_TYPE 7 -#define ME_ERRNO_INVALID_TRIG_EDGE 8 -#define ME_ERRNO_INVALID_TIMEOUT 9 -#define ME_ERRNO_INVALID_FLAGS 10 -#define ME_ERRNO_OPEN 11 -#define ME_ERRNO_CLOSE 12 -#define ME_ERRNO_NOT_OPEN 13 -#define ME_ERRNO_INVALID_DIR 14 -#define ME_ERRNO_PREVIOUS_CONFIG 15 -#define ME_ERRNO_NOT_SUPPORTED 16 -#define ME_ERRNO_SUBDEVICE_TYPE 17 -#define ME_ERRNO_USER_BUFFER_SIZE 18 -#define ME_ERRNO_LOCKED 19 -#define ME_ERRNO_NOMORE_SUBDEVICE_TYPE 20 -#define ME_ERRNO_TIMEOUT 21 -#define ME_ERRNO_SIGNAL 22 -#define ME_ERRNO_INVALID_IRQ_SOURCE 23 -#define ME_ERRNO_THREAD_RUNNING 24 -#define ME_ERRNO_START_THREAD 25 -#define ME_ERRNO_CANCEL_THREAD 26 -#define ME_ERRNO_NO_CALLBACK 27 -#define ME_ERRNO_USED 28 -#define ME_ERRNO_INVALID_UNIT 29 -#define ME_ERRNO_INVALID_MIN_MAX 30 -#define ME_ERRNO_NO_RANGE 31 -#define ME_ERRNO_INVALID_RANGE 32 -#define ME_ERRNO_SUBDEVICE_BUSY 33 -#define ME_ERRNO_INVALID_LOCK 34 -#define ME_ERRNO_INVALID_SWITCH 35 -#define ME_ERRNO_INVALID_ERROR_MSG_COUNT 36 -#define ME_ERRNO_INVALID_STREAM_CONFIG 37 -#define ME_ERRNO_INVALID_CONFIG_LIST_COUNT 38 -#define ME_ERRNO_INVALID_ACQ_START_TRIG_TYPE 39 -#define ME_ERRNO_INVALID_ACQ_START_TRIG_EDGE 40 -#define ME_ERRNO_INVALID_ACQ_START_TRIG_CHAN 41 -#define ME_ERRNO_INVALID_ACQ_START_TIMEOUT 42 -#define ME_ERRNO_INVALID_ACQ_START_ARG 43 -#define ME_ERRNO_INVALID_SCAN_START_TRIG_TYPE 44 -#define ME_ERRNO_INVALID_SCAN_START_ARG 45 -#define ME_ERRNO_INVALID_CONV_START_TRIG_TYPE 46 -#define ME_ERRNO_INVALID_CONV_START_ARG 47 -#define ME_ERRNO_INVALID_SCAN_STOP_TRIG_TYPE 48 -#define ME_ERRNO_INVALID_SCAN_STOP_ARG 49 -#define ME_ERRNO_INVALID_ACQ_STOP_TRIG_TYPE 50 -#define ME_ERRNO_INVALID_ACQ_STOP_ARG 51 -#define ME_ERRNO_SUBDEVICE_NOT_RUNNING 52 -#define ME_ERRNO_INVALID_READ_MODE 53 -#define ME_ERRNO_INVALID_VALUE_COUNT 54 -#define ME_ERRNO_INVALID_WRITE_MODE 55 -#define ME_ERRNO_INVALID_TIMER 56 -#define ME_ERRNO_DEVICE_UNPLUGGED 57 -#define ME_ERRNO_USED_INTERNAL 58 -#define ME_ERRNO_INVALID_DUTY_CYCLE 59 -#define ME_ERRNO_INVALID_WAIT 60 -#define ME_ERRNO_CONNECT_REMOTE 61 -#define ME_ERRNO_COMMUNICATION 62 -#define ME_ERRNO_INVALID_SINGLE_LIST 63 -#define ME_ERRNO_INVALID_MODULE_TYPE 64 -#define ME_ERRNO_INVALID_START_MODE 65 -#define ME_ERRNO_INVALID_STOP_MODE 66 -#define ME_ERRNO_INVALID_FIFO_IRQ_THRESHOLD 67 -#define ME_ERRNO_INVALID_POINTER 68 -#define ME_ERRNO_CREATE_EVENT 69 -#define ME_ERRNO_LACK_OF_RESOURCES 70 -#define ME_ERRNO_CANCELLED 71 -#define ME_ERRNO_RING_BUFFER_OVERFLOW 72 -#define ME_ERRNO_RING_BUFFER_UNDEFFLOW 73 -#define ME_ERRNO_INVALID_IRQ_EDGE 74 -#define ME_ERRNO_INVALID_IRQ_ARG 75 -#define ME_ERRNO_INVALID_CAP 76 -#define ME_ERRNO_INVALID_CAP_ARG_COUNT 77 -#define ME_ERRNO_INTERNAL 78 - -/** New error for range check */ -#define ME_ERRNO_VALUE_OUT_OF_RANGE 79 -#define ME_ERRNO_FIFO_BUFFER_OVERFLOW 80 -#define ME_ERRNO_FIFO_BUFFER_UNDEFFLOW 81 - -#define ME_ERRNO_INVALID_ERROR_NUMBER 82 -#endif --- a/drivers/staging/meilhaus/mefirmware.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @file mefirmware.c - * - * @brief Implements the firmware handling. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/*************************************************************************** - * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) * - * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef KBUILD_MODNAME -# define KBUILD_MODNAME KBUILD_STR(mefirmware) -#endif - -#include -#include - -#include - -#include "meplx_reg.h" -#include "medebug.h" - -#include "mefirmware.h" - -int me_xilinx_download(unsigned long register_base_control, - unsigned long register_base_data, - struct device *dev, const char *firmware_name) -{ - int err = ME_ERRNO_FIRMWARE; - uint32_t value = 0; - int idx = 0; - - const struct firmware *fw; - - PDEBUG("executed.\n"); - - if (!firmware_name) { - PERROR("Request for firmware failed. No name provided. \n"); - return err; - } - - PINFO("Request '%s' firmware.\n", firmware_name); - err = request_firmware(&fw, firmware_name, dev); - - if (err) { - PERROR("Request for firmware failed.\n"); - return err; - } - // Set PLX local interrupt 2 polarity to high. - // Interrupt is thrown by init pin of xilinx. - outl(PLX_INTCSR_LOCAL_INT2_POL, register_base_control + PLX_INTCSR); - - // Set /CS and /WRITE of the Xilinx - value = inl(register_base_control + PLX_ICR); - value |= ME_FIRMWARE_CS_WRITE; - outl(value, register_base_control + PLX_ICR); - - // Init Xilinx with CS1 - inl(register_base_data + ME_XILINX_CS1_REG); - - // Wait for init to complete - udelay(20); - - // Checkl /INIT pin - if (! - (inl(register_base_control + PLX_INTCSR) & - PLX_INTCSR_LOCAL_INT2_STATE)) { - PERROR("Can't init Xilinx.\n"); - release_firmware(fw); - return -EIO; - } - // Reset /CS and /WRITE of the Xilinx - value = inl(register_base_control + PLX_ICR); - value &= ~ME_FIRMWARE_CS_WRITE; - outl(value, register_base_control + PLX_ICR); - - // Download Xilinx firmware - udelay(10); - - for (idx = 0; idx < fw->size; idx++) { - outl(fw->data[idx], register_base_data); -#ifdef ME6000_v2_4 -/// This checking only for board's version 2.4 - // Check if BUSY flag is set (low = ready, high = busy) - if (inl(register_base_control + PLX_ICR) & - ME_FIRMWARE_BUSY_FLAG) { - PERROR("Xilinx is still busy (idx = %d)\n", idx); - release_firmware(fw); - return -EIO; - } -#endif //ME6000_v2_4 - } - PDEBUG("Download finished. %d bytes written to PLX.\n", idx); - - // If done flag is high download was successful - if (inl(register_base_control + PLX_ICR) & ME_FIRMWARE_DONE_FLAG) { - PDEBUG("SUCCESS. Done flag is set.\n"); - } else { - PERROR("FAILURE. DONE flag is not set.\n"); - release_firmware(fw); - return -EIO; - } - - // Set /CS and /WRITE - value = inl(register_base_control + PLX_ICR); - value |= ME_FIRMWARE_CS_WRITE; - outl(value, register_base_control + PLX_ICR); - - PDEBUG("Enable interrupts on the PCI interface.\n"); - outl(ME_PLX_PCI_ACTIVATE, register_base_control + PLX_INTCSR); - release_firmware(fw); - - return 0; -} --- a/drivers/staging/meilhaus/mefirmware.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @file mefirmware.h - * - * @brief Definitions of the firmware handling functions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/*************************************************************************** - * Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) * - * Copyright (C) 2007 by Krzysztof Gantzke k.gantzke@meilhaus.de * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef _MEFIRMWARE_H -# define _MEFIRMWARE_H - -# ifdef __KERNEL__ - -#define ME_ERRNO_FIRMWARE -1 - -/** -* Registry -*/ -#define ME_XILINX_CS1_REG 0x00C8 - -/** -* Flags (bits) -*/ - -#define ME_FIRMWARE_BUSY_FLAG 0x00000020 -#define ME_FIRMWARE_DONE_FLAG 0x00000004 -#define ME_FIRMWARE_CS_WRITE 0x00000100 - -#define ME_PLX_PCI_ACTIVATE 0x43 - -int me_xilinx_download(unsigned long register_base_control, - unsigned long register_base_data, - struct device *dev, const char *firmware_name); - -# endif //__KERNEL__ - -#endif //_MEFIRMWARE_H --- a/drivers/staging/meilhaus/meids.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : meids.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEIDS_H_ -#define _MEIDS_H_ - -#ifdef __KERNEL__ - -/*============================================================================= - Driver names - ===========================================================================*/ - -#define MEMAIN_NAME "memain" -#define ME1000_NAME "me1000" -#define ME1400_NAME "me1400" -#define ME1600_NAME "me1600" -#define ME4600_NAME "me4600" -#define ME6000_NAME "me6000" -#define ME0600_NAME "me0600" //"me630" -#define ME8100_NAME "me8100" -#define ME8200_NAME "me8200" -#define ME0900_NAME "me0900" //"me9x" -//#define MEPHISTO_S1_NAME "mephisto_s1" -#define MEDUMMY_NAME "medummy" - -#endif -#endif --- a/drivers/staging/meilhaus/meinternal.h +++ /dev/null @@ -1,363 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : meinternal.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEINTERNAL_H_ -#define _MEINTERNAL_H_ - -/*============================================================================= - PCI Vendor IDs - ===========================================================================*/ - -#define PCI_VENDOR_ID_MEILHAUS 0x1402 - -/*============================================================================= - PCI Device IDs - ===========================================================================*/ - -#define PCI_DEVICE_ID_MEILHAUS_ME1000 0x1000 -#define PCI_DEVICE_ID_MEILHAUS_ME1000_A 0x100A -#define PCI_DEVICE_ID_MEILHAUS_ME1000_B 0x100B - -#define PCI_DEVICE_ID_MEILHAUS_ME1400 0x1400 -#define PCI_DEVICE_ID_MEILHAUS_ME140A 0x140A -#define PCI_DEVICE_ID_MEILHAUS_ME140B 0x140B -#define PCI_DEVICE_ID_MEILHAUS_ME14E0 0x14E0 -#define PCI_DEVICE_ID_MEILHAUS_ME14EA 0x14EA -#define PCI_DEVICE_ID_MEILHAUS_ME14EB 0x14EB -#define PCI_DEVICE_ID_MEILHAUS_ME140C 0X140C -#define PCI_DEVICE_ID_MEILHAUS_ME140D 0X140D - -#define PCI_DEVICE_ID_MEILHAUS_ME1600_4U 0x1604 // 4 voltage outputs -#define PCI_DEVICE_ID_MEILHAUS_ME1600_8U 0x1608 // 8 voltage outputs -#define PCI_DEVICE_ID_MEILHAUS_ME1600_12U 0x160C // 12 voltage outputs -#define PCI_DEVICE_ID_MEILHAUS_ME1600_16U 0x160F // 16 voltage outputs -#define PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I 0x168F // 16 voltage/8 current o. - -#define PCI_DEVICE_ID_MEILHAUS_ME4610 0x4610 // Jekyll - -#define PCI_DEVICE_ID_MEILHAUS_ME4650 0x4650 // Low Cost version - -#define PCI_DEVICE_ID_MEILHAUS_ME4660 0x4660 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4660I 0x4661 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4660S 0x4662 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4660IS 0x4663 // Isolated version with Sample and Hold - -#define PCI_DEVICE_ID_MEILHAUS_ME4670 0x4670 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4670I 0x4671 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4670S 0x4672 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4670IS 0x4673 // Isolated version with Sample and Hold - -#define PCI_DEVICE_ID_MEILHAUS_ME4680 0x4680 // Standard version -#define PCI_DEVICE_ID_MEILHAUS_ME4680I 0x4681 // Isolated version -#define PCI_DEVICE_ID_MEILHAUS_ME4680S 0x4682 // Standard version with Sample and Hold -#define PCI_DEVICE_ID_MEILHAUS_ME4680IS 0x4683 // Isolated version with Sample and Hold - -/* ME6000 standard version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6004 0x6004 -#define PCI_DEVICE_ID_MEILHAUS_ME6008 0x6008 -#define PCI_DEVICE_ID_MEILHAUS_ME600F 0x600F - -/* ME6000 isolated version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6014 0x6014 -#define PCI_DEVICE_ID_MEILHAUS_ME6018 0x6018 -#define PCI_DEVICE_ID_MEILHAUS_ME601F 0x601F - -/* ME6000 isle version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6034 0x6034 -#define PCI_DEVICE_ID_MEILHAUS_ME6038 0x6038 -#define PCI_DEVICE_ID_MEILHAUS_ME603F 0x603F - -/* ME6000 standard version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6044 0x6044 -#define PCI_DEVICE_ID_MEILHAUS_ME6048 0x6048 -#define PCI_DEVICE_ID_MEILHAUS_ME604F 0x604F - -/* ME6000 isolated version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6054 0x6054 -#define PCI_DEVICE_ID_MEILHAUS_ME6058 0x6058 -#define PCI_DEVICE_ID_MEILHAUS_ME605F 0x605F - -/* ME6000 isle version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6074 0x6074 -#define PCI_DEVICE_ID_MEILHAUS_ME6078 0x6078 -#define PCI_DEVICE_ID_MEILHAUS_ME607F 0x607F - -/* ME6100 standard version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6104 0x6104 -#define PCI_DEVICE_ID_MEILHAUS_ME6108 0x6108 -#define PCI_DEVICE_ID_MEILHAUS_ME610F 0x610F - -/* ME6100 isolated version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6114 0x6114 -#define PCI_DEVICE_ID_MEILHAUS_ME6118 0x6118 -#define PCI_DEVICE_ID_MEILHAUS_ME611F 0x611F - -/* ME6100 isle version */ -#define PCI_DEVICE_ID_MEILHAUS_ME6134 0x6134 -#define PCI_DEVICE_ID_MEILHAUS_ME6138 0x6138 -#define PCI_DEVICE_ID_MEILHAUS_ME613F 0x613F - -/* ME6100 standard version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6144 0x6144 -#define PCI_DEVICE_ID_MEILHAUS_ME6148 0x6148 -#define PCI_DEVICE_ID_MEILHAUS_ME614F 0x614F - -/* ME6100 isolated version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6154 0x6154 -#define PCI_DEVICE_ID_MEILHAUS_ME6158 0x6158 -#define PCI_DEVICE_ID_MEILHAUS_ME615F 0x615F - -/* ME6100 isle version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6174 0x6174 -#define PCI_DEVICE_ID_MEILHAUS_ME6178 0x6178 -#define PCI_DEVICE_ID_MEILHAUS_ME617F 0x617F - -/* ME6200 isolated version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6259 0x6259 - -/* ME6300 isolated version with DIO */ -#define PCI_DEVICE_ID_MEILHAUS_ME6359 0x6359 - -/* ME0630 */ -#define PCI_DEVICE_ID_MEILHAUS_ME0630 0x0630 - -/* ME8100 */ -#define PCI_DEVICE_ID_MEILHAUS_ME8100_A 0x810A -#define PCI_DEVICE_ID_MEILHAUS_ME8100_B 0x810B - -/* ME8200 */ -#define PCI_DEVICE_ID_MEILHAUS_ME8200_A 0x820A -#define PCI_DEVICE_ID_MEILHAUS_ME8200_B 0x820B - -/* ME0900 */ -#define PCI_DEVICE_ID_MEILHAUS_ME0940 0x0940 -#define PCI_DEVICE_ID_MEILHAUS_ME0950 0x0950 -#define PCI_DEVICE_ID_MEILHAUS_ME0960 0x0960 - - -/*============================================================================= - USB Vendor IDs - ===========================================================================*/ - -//#define USB_VENDOR_ID_MEPHISTO_S1 0x0403 - - -/*============================================================================= - USB Device IDs - ===========================================================================*/ - -//#define USB_DEVICE_ID_MEPHISTO_S1 0xDCD0 - - -/* ME-1000 defines */ -#define ME1000_NAME_DRIVER "ME-1000" - -#define ME1000_NAME_DEVICE_ME1000 "ME-1000" - -#define ME1000_DESCRIPTION_DEVICE_ME1000 "ME-1000 device, 128 digital i/o lines." - -/* ME-1400 defines */ -#define ME1400_NAME_DRIVER "ME-1400" - -#define ME1400_NAME_DEVICE_ME1400 "ME-1400" -#define ME1400_NAME_DEVICE_ME1400E "ME-1400E" -#define ME1400_NAME_DEVICE_ME1400A "ME-1400A" -#define ME1400_NAME_DEVICE_ME1400EA "ME-1400EA" -#define ME1400_NAME_DEVICE_ME1400B "ME-1400B" -#define ME1400_NAME_DEVICE_ME1400EB "ME-1400EB" -#define ME1400_NAME_DEVICE_ME1400C "ME-1400C" -#define ME1400_NAME_DEVICE_ME1400D "ME-1400D" - -#define ME1400_DESCRIPTION_DEVICE_ME1400 "ME-1400 device, 24 digital i/o lines." -#define ME1400_DESCRIPTION_DEVICE_ME1400E "ME-1400E device, 24 digital i/o lines." -#define ME1400_DESCRIPTION_DEVICE_ME1400A "ME-1400A device, 24 digital i/o lines, 3 counters." -#define ME1400_DESCRIPTION_DEVICE_ME1400EA "ME-1400EA device, 24 digital i/o lines, 3 counters." -#define ME1400_DESCRIPTION_DEVICE_ME1400B "ME-1400B device, 48 digital i/o lines, 6 counters." -#define ME1400_DESCRIPTION_DEVICE_ME1400EB "ME-1400EB device, 48 digital i/o lines, 6 counters." -#define ME1400_DESCRIPTION_DEVICE_ME1400C "ME-1400C device, 24 digital i/o lines, 15 counters." -#define ME1400_DESCRIPTION_DEVICE_ME1400D "ME-1400D device, 48 digital i/o lines, 30 counters." - -/* ME-1600 defines */ -#define ME1600_NAME_DRIVER "ME-1600" - -#define ME1600_NAME_DEVICE_ME16004U "ME-1600/4U" -#define ME1600_NAME_DEVICE_ME16008U "ME-1600/8U" -#define ME1600_NAME_DEVICE_ME160012U "ME-1600/12U" -#define ME1600_NAME_DEVICE_ME160016U "ME-1600/16U" -#define ME1600_NAME_DEVICE_ME160016U8I "ME-1600/16U8I" - -#define ME1600_DESCRIPTION_DEVICE_ME16004U "ME-1600/4U device, 4 voltage outputs." -#define ME1600_DESCRIPTION_DEVICE_ME16008U "ME-1600/8U device, 8 voltage outputs." -#define ME1600_DESCRIPTION_DEVICE_ME160012U "ME-1600/12U device, 12 voltage outputs." -#define ME1600_DESCRIPTION_DEVICE_ME160016U "ME-1600/16U device, 16 voltage outputs." -#define ME1600_DESCRIPTION_DEVICE_ME160016U8I "ME-1600/16U8I device, 16 voltage, 8 current outputs." - -/* ME-4000 defines */ -#define ME4600_NAME_DRIVER "ME-4600" - -#define ME4600_NAME_DEVICE_ME4610 "ME-4610" -#define ME4600_NAME_DEVICE_ME4650 "ME-4650" -#define ME4600_NAME_DEVICE_ME4660 "ME-4660" -#define ME4600_NAME_DEVICE_ME4660I "ME-4660I" -#define ME4600_NAME_DEVICE_ME4660S "ME-4660S" -#define ME4600_NAME_DEVICE_ME4660IS "ME-4660IS" -#define ME4600_NAME_DEVICE_ME4670 "ME-4670" -#define ME4600_NAME_DEVICE_ME4670I "ME-4670I" -#define ME4600_NAME_DEVICE_ME4670S "ME-4670S" -#define ME4600_NAME_DEVICE_ME4670IS "ME-4670IS" -#define ME4600_NAME_DEVICE_ME4680 "ME-4680" -#define ME4600_NAME_DEVICE_ME4680I "ME-4680I" -#define ME4600_NAME_DEVICE_ME4680S "ME-4680S" -#define ME4600_NAME_DEVICE_ME4680IS "ME-4680IS" - -#define ME4600_DESCRIPTION_DEVICE_ME4610 "ME-4610 device, 16 streaming analog inputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4650 "ME-4650 device, 16 streaming analog inputs, 32 digital i/o lines, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4660 "ME-4660 device, 16 streaming analog inputs, 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4660I "ME-4660I opto isolated device, 16 streaming analog inputs, 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4660S "ME-4660 device, 16 streaming analog inputs (8 S&H), 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4660IS "ME-4660I opto isolated device, 16 streaming analog inputs (8 S&H), 2 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4670 "ME-4670 device, 32 streaming analog inputs, 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4670I "ME-4670I opto isolated device, 32 streaming analog inputs, 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4670S "ME-4670S device, 32 streaming analog inputs (8 S&H), 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4670IS "ME-4670IS opto isolated device, 32 streaming analog inputs (8 S&H), 4 single analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4680 "ME-4680 device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4680I "ME-4680I opto isolated device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4680S "ME-4680S device, 32 streaming analog inputs, 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." -#define ME4600_DESCRIPTION_DEVICE_ME4680IS "ME-4680IS opto isolated device, 32 streaming analog inputs (8 S&H), 4 streaming analog outputs, 32 digital i/o lines, 3 counters, 1 external interrupt." - -/* ME-6000 defines */ -#define ME6000_NAME_DRIVER "ME-6000" - -#define ME6000_NAME_DEVICE_ME60004 "ME-6000/4" -#define ME6000_NAME_DEVICE_ME60008 "ME-6000/8" -#define ME6000_NAME_DEVICE_ME600016 "ME-6000/16" -#define ME6000_NAME_DEVICE_ME6000I4 "ME-6000I/4" -#define ME6000_NAME_DEVICE_ME6000I8 "ME-6000I/8" -#define ME6000_NAME_DEVICE_ME6000I16 "ME-6000I/16" -#define ME6000_NAME_DEVICE_ME6000ISLE4 "ME-6000ISLE/4" -#define ME6000_NAME_DEVICE_ME6000ISLE8 "ME-6000ISLE/8" -#define ME6000_NAME_DEVICE_ME6000ISLE16 "ME-6000ISLE/16" -#define ME6000_NAME_DEVICE_ME61004 "ME-6100/4" -#define ME6000_NAME_DEVICE_ME61008 "ME-6100/8" -#define ME6000_NAME_DEVICE_ME610016 "ME-6100/16" -#define ME6000_NAME_DEVICE_ME6100I4 "ME-6100I/4" -#define ME6000_NAME_DEVICE_ME6100I8 "ME-6100I/8" -#define ME6000_NAME_DEVICE_ME6100I16 "ME-6100I/16" -#define ME6000_NAME_DEVICE_ME6100ISLE4 "ME-6100ISLE/4" -#define ME6000_NAME_DEVICE_ME6100ISLE8 "ME-6100ISLE/8" -#define ME6000_NAME_DEVICE_ME6100ISLE16 "ME-6100ISLE/16" -#define ME6000_NAME_DEVICE_ME60004DIO "ME-6000/4/DIO" -#define ME6000_NAME_DEVICE_ME60008DIO "ME-6000/8/DIO" -#define ME6000_NAME_DEVICE_ME600016DIO "ME-6000/16/DIO" -#define ME6000_NAME_DEVICE_ME6000I4DIO "ME-6000I/4/DIO" -#define ME6000_NAME_DEVICE_ME6000I8DIO "ME-6000I/8/DIO" -#define ME6000_NAME_DEVICE_ME6000I16DIO "ME-6000I/16/DIO" -#define ME6000_NAME_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO" -#define ME6000_NAME_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO" -#define ME6000_NAME_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO" -#define ME6000_NAME_DEVICE_ME61004DIO "ME-6100/4/DIO" -#define ME6000_NAME_DEVICE_ME61008DIO "ME-6100/8/DIO" -#define ME6000_NAME_DEVICE_ME610016DIO "ME-6100/16/DIO" -#define ME6000_NAME_DEVICE_ME6100I4DIO "ME-6100I/4/DIO" -#define ME6000_NAME_DEVICE_ME6100I8DIO "ME-6100I/8/DIO" -#define ME6000_NAME_DEVICE_ME6100I16DIO "ME-6100I/16/DIO" -#define ME6000_NAME_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO" -#define ME6000_NAME_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO" -#define ME6000_NAME_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO" -#define ME6000_NAME_DEVICE_ME6200I9DIO "ME-6200I/9/DIO" -#define ME6000_NAME_DEVICE_ME6300I9DIO "ME-6300I/9/DIO" - -#define ME6000_DESCRIPTION_DEVICE_ME60004 "ME-6000/4 device, 4 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME60008 "ME-6000/8 device, 8 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME600016 "ME-6000/16 device, 16 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000I4 "ME-6000I/4 isolated device, 4 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000I8 "ME-6000I/8 isolated device, 8 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000I16 "ME-6000I/16 isolated device, 16 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4 "ME-6000ISLE/4 isle device, 4 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8 "ME-6000ISLE/8 isle device, 8 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16 "ME-6000ISLE/16 isle device, 16 single analog outputs" -#define ME6000_DESCRIPTION_DEVICE_ME61004 "ME-6100/4 device, 4 streaming analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME61008 "ME-6100/8 device, 4 streaming, 4 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME610016 "ME-6100/16 device, 4 streaming, 12 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100I4 "ME-6100I/4 isolated device, 4 streaming analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100I8 "ME-6100I/8 isolated device, 4 streaming, 4 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100I16 "ME-6100I/16 isolated device, 4 streaming, 12 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4 "ME-6100ISLE/4 isle device, 4 streaming analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8 "ME-6100ISLE/8 isle device, 4 streaming, 4 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16 "ME-6100ISLE/16 isle device, 4 streaming, 12 single analog outputs." -#define ME6000_DESCRIPTION_DEVICE_ME60004DIO "ME-6000/4/DIO device, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME60008DIO "ME-6000/8/DIO device, 8 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME600016DIO "ME-6000/16/DIO device, 8 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000I4DIO "ME-6000I/4/DIO isolated device, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000I8DIO "ME-6000I/8/DIO isolated device, 8 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000I16DIO "ME-6000I/16/DIO isolated device, 16 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE4DIO "ME-6000ISLE/4/DIO isle device, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE8DIO "ME-6000ISLE/8/DIO isle device, 8 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6000ISLE16DIO "ME-6000ISLE/16/DIO isle device, 16 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME61004DIO "ME-6100/4/DIO device, 4 streaming analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME61008DIO "ME-6100/8/DIO device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME610016DIO "ME-6100/16/DIO device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100I4DIO "ME-6100I/4/DIO isolated device, 4 streaming analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100I8DIO "ME-6100I/8/DIO isolated device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100I16DIO "ME-6100I/16/DIO isolated device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE4DIO "ME-6100ISLE/4/DIO isle device, 4 streaming analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE8DIO "ME-6100ISLE/8/DIO isle device, 4 streaming, 4 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6100ISLE16DIO "ME-6100ISLE/16/DIO isle device, 4 streaming, 12 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6200I9DIO "ME-6200I/9/DIO isolated device, 9 single analog outputs, 16 digital i/o lines." -#define ME6000_DESCRIPTION_DEVICE_ME6300I9DIO "ME-6300I/9/DIO isolated device, 4 streaming, 5 single analog outputs, 16 digital i/o lines." - -/* ME-630 defines */ -#define ME0600_NAME_DRIVER "ME-0600" - -#define ME0600_NAME_DEVICE_ME0630 "ME-630" - -#define ME0600_DESCRIPTION_DEVICE_ME0630 "ME-630 device, up to 16 relay, 8 digital ttl input lines, 8 isolated digital input lines, 16 digital i/o lines, 2 external interrupts." - -/* ME-8100 defines */ -#define ME8100_NAME_DRIVER "ME-8100" - -#define ME8100_NAME_DEVICE_ME8100A "ME-8100A" -#define ME8100_NAME_DEVICE_ME8100B "ME-8100B" - -#define ME8100_DESCRIPTION_DEVICE_ME8100A "ME-8100A opto isolated device, 16 digital input lines, 16 digital output lines." -#define ME8100_DESCRIPTION_DEVICE_ME8100B "ME-8100B opto isolated device, 32 digital input lines, 32 digital output lines, 3 counters." - -/* ME-8200 defines */ -#define ME8200_NAME_DRIVER "ME-8200" - -#define ME8200_NAME_DEVICE_ME8200A "ME-8200A" -#define ME8200_NAME_DEVICE_ME8200B "ME-8200B" - -#define ME8200_DESCRIPTION_DEVICE_ME8200A "ME-8200A opto isolated device, 8 digital output lines, 8 digital input lines, 16 digital i/o lines." -#define ME8200_DESCRIPTION_DEVICE_ME8200B "ME-8200B opto isolated device, 16 digital output lines, 16 digital input lines, 16 digital i/o lines." - -/* ME-0900 defines */ -#define ME0900_NAME_DRIVER "ME-0900" - -#define ME0900_NAME_DEVICE_ME0940 "ME-94" -#define ME0900_NAME_DEVICE_ME0950 "ME-95" -#define ME0900_NAME_DEVICE_ME0960 "ME-96" - -#define ME0900_DESCRIPTION_DEVICE_ME0940 "ME-94 device, 16 digital input lines, 2 external interrupt lines." -#define ME0900_DESCRIPTION_DEVICE_ME0950 "ME-95 device, 16 digital output lines." -#define ME0900_DESCRIPTION_DEVICE_ME0960 "ME-96 device, 8 digital input lines, 8 digital output lines, 2 external interrupt lines." - -/* ME-DUMMY defines */ -#define MEDUMMY_NAME_DRIVER "ME-Dummy" - -/* MEPHISTO_S1 defines */ -/* -#define MEPHISTO_S1_NAME_DRIVER "MEphisto Scope 1" -#define MEPHISTO_S1_NAME_DEVICE "MEphisto Scope 1" -#define MEPHISTO_S1_DESCRIPTION_DEVICE "MEphisto Scope 1 device, 2 analog inputs, 24 digital i/o." -*/ -/* Error defines */ -#define EMPTY_NAME_DRIVER "ME-???" -#define EMPTY_NAME_DEVICE "ME-???" -#define EMPTY_DESCRIPTION_DEVICE "ME-??? unknown device" - -#endif --- a/drivers/staging/meilhaus/meioctl.h +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : meioctl.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEIOCTL_H_ -#define _MEIOCTL_H_ - - -/*============================================================================= - Types for the input/output ioctls - ===========================================================================*/ - -typedef struct me_io_irq_start { - int device; - int subdevice; - int channel; - int irq_source; - int irq_edge; - int irq_arg; - int flags; - int errno; -} me_io_irq_start_t; - - -typedef struct me_io_irq_wait { - int device; - int subdevice; - int channel; - int irq_count; - int value; - int time_out; - int flags; - int errno; -} me_io_irq_wait_t; - - -typedef struct me_io_irq_stop { - int device; - int subdevice; - int channel; - int flags; - int errno; -} me_io_irq_stop_t; - - -typedef struct me_io_reset_device { - int device; - int flags; - int errno; -} me_io_reset_device_t; - - -typedef struct me_io_reset_subdevice { - int device; - int subdevice; - int flags; - int errno; -} me_io_reset_subdevice_t; - - -typedef struct me_io_single_config { - int device; - int subdevice; - int channel; - int single_config; - int ref; - int trig_chan; - int trig_type; - int trig_edge; - int flags; - int errno; -} me_io_single_config_t; - - -typedef struct me_io_single { - meIOSingle_t *single_list; - int count; - int flags; - int errno; -} me_io_single_t; - - -typedef struct me_io_stream_config { - int device; - int subdevice; - meIOStreamConfig_t *config_list; - int count; - meIOStreamTrigger_t trigger; - int fifo_irq_threshold; - int flags; - int errno; -} me_io_stream_config_t; - - -typedef struct me_io_stream_new_values { - int device; - int subdevice; - int time_out; - int count; - int flags; - int errno; -} me_io_stream_new_values_t; - - -typedef struct me_io_stream_read { - int device; - int subdevice; - int read_mode; - int *values; - int count; - int flags; - int errno; -} me_io_stream_read_t; - - -typedef struct me_io_stream_start { - meIOStreamStart_t *start_list; - int count; - int flags; - int errno; -} me_io_stream_start_t; - - -typedef struct me_io_stream_status { - int device; - int subdevice; - int wait; - int status; - int count; - int flags; - int errno; -} me_io_stream_status_t; - - -typedef struct me_io_stream_stop { - meIOStreamStop_t *stop_list; - int count; - int flags; - int errno; -} me_io_stream_stop_t; - - -typedef struct me_io_stream_write { - int device; - int subdevice; - int write_mode; - int *values; - int count; - int flags; - int errno; -} me_io_stream_write_t; - - -/*============================================================================= - Types for the lock ioctls - ===========================================================================*/ - -typedef struct me_lock_device { - int device; - int lock; - int flags; - int errno; -} me_lock_device_t; - - -typedef struct me_lock_driver { - int flags; - int lock; - int errno; -} me_lock_driver_t; - - -typedef struct me_lock_subdevice { - int device; - int subdevice; - int lock; - int flags; - int errno; -} me_lock_subdevice_t; - - -/*============================================================================= - Types for the query ioctls - ===========================================================================*/ - -typedef struct me_query_info_device { - int device; - int vendor_id; - int device_id; - int serial_no; - int bus_type; - int bus_no; - int dev_no; - int func_no; - int plugged; - int errno; -} me_query_info_device_t; - - -typedef struct me_query_description_device { - int device; - char *name; - int count; - int errno; -} me_query_description_device_t; - - -typedef struct me_query_name_device { - int device; - char *name; - int count; - int errno; -} me_query_name_device_t; - - -typedef struct me_query_name_device_driver { - int device; - char *name; - int count; - int errno; -} me_query_name_device_driver_t; - - -typedef struct me_query_version_main_driver { - int version; - int errno; -} me_query_version_main_driver_t; - - -typedef struct me_query_version_device_driver { - int device; - int version; - int errno; -} me_query_version_device_driver_t; - - -typedef struct me_query_number_devices { - int number; - int errno; -} me_query_number_devices_t; - - -typedef struct me_query_number_subdevices { - int device; - int number; - int errno; -} me_query_number_subdevices_t; - - -typedef struct me_query_number_channels { - int device; - int subdevice; - int number; - int errno; -} me_query_number_channels_t; - - -typedef struct me_query_number_ranges { - int device; - int subdevice; - int channel; - int unit; - int number; - int errno; -} me_query_number_ranges_t; - - -typedef struct me_query_subdevice_by_type { - int device; - int start_subdevice; - int type; - int subtype; - int subdevice; - int errno; -} me_query_subdevice_by_type_t; - - -typedef struct me_query_subdevice_type { - int device; - int subdevice; - int type; - int subtype; - int errno; -} me_query_subdevice_type_t; - - -typedef struct me_query_subdevice_caps { - int device; - int subdevice; - int caps; - int errno; -} me_query_subdevice_caps_t; - - -typedef struct me_query_subdevice_caps_args { - int device; - int subdevice; - int cap; - int args[8]; - int count; - int errno; -} me_query_subdevice_caps_args_t; - - -typedef struct me_query_timer { - int device; - int subdevice; - int timer; - int base_frequency; - long long min_ticks; - long long max_ticks; - int errno; -} me_query_timer_t; - - -typedef struct me_query_range_by_min_max { - int device; - int subdevice; - int channel; - int unit; - int min; - int max; - int max_data; - int range; - int errno; -} me_query_range_by_min_max_t; - - -typedef struct me_query_range_info { - int device; - int subdevice; - int channel; - int unit; - int range; - int min; - int max; - int max_data; - int errno; -} me_query_range_info_t; - - -/*============================================================================= - Types for the configuration ioctls - ===========================================================================*/ - -typedef struct me_cfg_tcpip_location { - int access_type; - char *remote_host; - int remote_device_number; -} me_cfg_tcpip_location_t; - - -typedef union me_cfg_tcpip { - int access_type; - me_cfg_tcpip_location_t location; -} me_cfg_tcpip_t; - - -typedef struct me_cfg_pci_hw_location { - unsigned int bus_type; - unsigned int bus_no; - unsigned int device_no; - unsigned int function_no; -} me_cfg_pci_hw_location_t; - -/* -typedef struct me_cfg_usb_hw_location { - unsigned int bus_type; - unsigned int root_hub_no; -} me_cfg_usb_hw_location_t; -*/ - -typedef union me_cfg_hw_location { - unsigned int bus_type; - me_cfg_pci_hw_location_t pci; -// me_cfg_usb_hw_location_t usb; -} me_cfg_hw_location_t; - - -typedef struct me_cfg_device_info { - unsigned int vendor_id; - unsigned int device_id; - unsigned int serial_no; - me_cfg_hw_location_t hw_location; -} me_cfg_device_info_t; - - -typedef struct me_cfg_subdevice_info { - int type; - int sub_type; - unsigned int number_channels; -} me_cfg_subdevice_info_t; - - -typedef struct me_cfg_range_entry { - int unit; - double min; - double max; - unsigned int max_data; -} me_cfg_range_entry_t; - - -typedef struct me_cfg_mux32m_device { - int type; - int timed; - unsigned int ai_channel; - unsigned int dio_device; - unsigned int dio_subdevice; - unsigned int timer_device; - unsigned int timer_subdevice; - unsigned int mux32s_count; -} me_cfg_mux32m_device_t; - - -typedef struct me_cfg_demux32_device { - int type; - int timed; - unsigned int ao_channel; - unsigned int dio_device; - unsigned int dio_subdevice; - unsigned int timer_device; - unsigned int timer_subdevice; -} me_cfg_demux32_device_t; - - -typedef union me_cfg_external_device { - int type; - me_cfg_mux32m_device_t mux32m; - me_cfg_demux32_device_t demux32; -} me_cfg_external_device_t; - - -typedef struct me_cfg_subdevice_entry { - me_cfg_subdevice_info_t info; - me_cfg_range_entry_t *range_list; - unsigned int count; - int locked; - me_cfg_external_device_t external_device; -} me_cfg_subdevice_entry_t; - - -typedef struct me_cfg_device_entry { - me_cfg_tcpip_t tcpip; - me_cfg_device_info_t info; - me_cfg_subdevice_entry_t *subdevice_list; - unsigned int count; -} me_cfg_device_entry_t; - - -typedef struct me_config_load { - me_cfg_device_entry_t *device_list; - unsigned int count; - int errno; -} me_config_load_t; - - -/*============================================================================= - The ioctls of the board - ===========================================================================*/ - -#define MEMAIN_MAGIC 'y' - -#define ME_IO_IRQ_ENABLE _IOR (MEMAIN_MAGIC, 1, me_io_irq_start_t) -#define ME_IO_IRQ_WAIT _IOR (MEMAIN_MAGIC, 2, me_io_irq_wait_t) -#define ME_IO_IRQ_DISABLE _IOR (MEMAIN_MAGIC, 3, me_io_irq_stop_t) - -#define ME_IO_RESET_DEVICE _IOW (MEMAIN_MAGIC, 4, me_io_reset_device_t) -#define ME_IO_RESET_SUBDEVICE _IOW (MEMAIN_MAGIC, 5, me_io_reset_subdevice_t) - -#define ME_IO_SINGLE _IOWR(MEMAIN_MAGIC, 6, me_io_single_t) -#define ME_IO_SINGLE_CONFIG _IOW (MEMAIN_MAGIC, 7, me_io_single_config_t) - -#define ME_IO_STREAM_CONFIG _IOW (MEMAIN_MAGIC, 8, me_io_stream_config_t) -#define ME_IO_STREAM_NEW_VALUES _IOR (MEMAIN_MAGIC, 9, me_io_stream_new_values_t) -#define ME_IO_STREAM_READ _IOR (MEMAIN_MAGIC, 10, me_io_stream_read_t) -#define ME_IO_STREAM_START _IOW (MEMAIN_MAGIC, 11, me_io_stream_start_t) -#define ME_IO_STREAM_STATUS _IOR (MEMAIN_MAGIC, 12, me_io_stream_status_t) -#define ME_IO_STREAM_STOP _IOW (MEMAIN_MAGIC, 13, me_io_stream_stop_t) -#define ME_IO_STREAM_WRITE _IOW (MEMAIN_MAGIC, 14, me_io_stream_write_t) - -#define ME_LOCK_DRIVER _IOW (MEMAIN_MAGIC, 15, me_lock_driver_t) -#define ME_LOCK_DEVICE _IOW (MEMAIN_MAGIC, 16, me_lock_device_t) -#define ME_LOCK_SUBDEVICE _IOW (MEMAIN_MAGIC, 17, me_lock_subdevice_t) - -#define ME_QUERY_DESCRIPTION_DEVICE _IOR (MEMAIN_MAGIC, 18, me_query_description_device_t) - -#define ME_QUERY_INFO_DEVICE _IOR (MEMAIN_MAGIC, 19, me_query_info_device_t) - -#define ME_QUERY_NAME_DEVICE _IOR (MEMAIN_MAGIC, 20, me_query_name_device_t) -#define ME_QUERY_NAME_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 21, me_query_name_device_driver_t) - -#define ME_QUERY_NUMBER_DEVICES _IOR (MEMAIN_MAGIC, 22, me_query_number_devices_t) -#define ME_QUERY_NUMBER_SUBDEVICES _IOR (MEMAIN_MAGIC, 23, me_query_number_subdevices_t) -#define ME_QUERY_NUMBER_CHANNELS _IOR (MEMAIN_MAGIC, 24, me_query_number_channels_t) -#define ME_QUERY_NUMBER_RANGES _IOR (MEMAIN_MAGIC, 25, me_query_number_ranges_t) - -#define ME_QUERY_RANGE_BY_MIN_MAX _IOR (MEMAIN_MAGIC, 26, me_query_range_by_min_max_t) -#define ME_QUERY_RANGE_INFO _IOR (MEMAIN_MAGIC, 27, me_query_range_info_t) - -#define ME_QUERY_SUBDEVICE_BY_TYPE _IOR (MEMAIN_MAGIC, 28, me_query_subdevice_by_type_t) -#define ME_QUERY_SUBDEVICE_TYPE _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_type_t) -#define ME_QUERY_SUBDEVICE_CAPS _IOR (MEMAIN_MAGIC, 29, me_query_subdevice_caps_t) -#define ME_QUERY_SUBDEVICE_CAPS_ARGS _IOR (MEMAIN_MAGIC, 30, me_query_subdevice_caps_args_t) - -#define ME_QUERY_TIMER _IOR (MEMAIN_MAGIC, 31, me_query_timer_t) - -#define ME_QUERY_VERSION_DEVICE_DRIVER _IOR (MEMAIN_MAGIC, 32, me_query_version_device_driver_t) -#define ME_QUERY_VERSION_MAIN_DRIVER _IOR (MEMAIN_MAGIC, 33, me_query_version_main_driver_t) - -#define ME_CONFIG_LOAD _IOWR(MEMAIN_MAGIC, 34, me_config_load_t) - -#endif --- a/drivers/staging/meilhaus/memain.c +++ /dev/null @@ -1,2084 +0,0 @@ -/** - * @file memain.c - * - * @brief Main Meilhaus device driver. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - * @author Krzysztof Gantzke (k.gantzke@meilhaus.de) - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include -#include -//#include -#include -#include -#include -#include - -#include "medefines.h" -#include "metypes.h" -#include "meerror.h" - -#include "medebug.h" -#include "memain.h" -#include "medevice.h" -#include "meioctl.h" -#include "mecommon.h" - -/* Module parameters -*/ - -#ifdef BOSCH -static unsigned int me_bosch_fw = 0; -EXPORT_SYMBOL(me_bosch_fw); - -# ifdef module_param -module_param(me_bosch_fw, int, S_IRUGO); -# else -MODULE_PARM(me_bosch_fw, "i"); -# endif - -MODULE_PARM_DESC(me_bosch_fw, - "Flags which signals the ME-4600 driver to load the bosch firmware (default = 0)."); -#endif //BOSCH - -/* Global Driver Lock -*/ - -static struct file *me_filep = NULL; -static int me_count = 0; -static DEFINE_SPINLOCK(me_lock); -static DECLARE_RWSEM(me_rwsem); - -/* Board instances are kept in a global list */ -LIST_HEAD(me_device_list); - -/* Prototypes -*/ - -static int me_probe_pci(struct pci_dev *dev, const struct pci_device_id *id); -static void me_remove_pci(struct pci_dev *dev); -static int insert_to_device_list(me_device_t *n_device); -static int replace_with_dummy(int vendor_id, int device_id, int serial_no); -static void clear_device_list(void); -static int me_open(struct inode *inode_ptr, struct file *filep); -static int me_release(struct inode *, struct file *); -static int me_ioctl(struct inode *, struct file *, unsigned int, unsigned long); -//static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id); -//static void me_disconnect_usb(struct usb_interface *interface); - -/* File operations provided by the module -*/ - -static const struct file_operations me_file_operations = { - .owner = THIS_MODULE, - .ioctl = me_ioctl, - .open = me_open, - .release = me_release, -}; - -static const struct pci_device_id me_pci_table[] = { - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_A) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1000_B) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1400) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140A) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140B) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14E0) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EA) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME14EB) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140C) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME140D) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_4U) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_8U) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_12U) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME1600_16U_8I) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4610) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4650) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4660I) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670I) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670S) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4670IS) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680I) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680S) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME4680IS) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6004) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6008) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME600F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6014) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6018) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME601F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6034) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6038) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME603F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6104) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6108) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME610F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6114) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6118) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME611F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6134) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6138) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME613F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6044) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6048) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME604F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6054) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6058) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME605F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6074) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6078) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME607F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6144) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6148) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME614F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6154) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6158) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME615F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6174) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6178) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME617F) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6259) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME6359) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0630) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_A) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8100_B) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_A) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME8200_B) }, - - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0940) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0950) }, - { PCI_VDEVICE(MEILHAUS, PCI_DEVICE_ID_MEILHAUS_ME0960) }, - - { } -}; -MODULE_DEVICE_TABLE(pci, me_pci_table); - -static struct pci_driver me_pci_driver = { - .name = MEMAIN_NAME, - .id_table = me_pci_table, - .probe = me_probe_pci, - .remove = __devexit_p(me_remove_pci), -}; - -/* -static struct usb_device_id me_usb_table[] = { - { USB_DEVICE(USB_VENDOR_ID_MEPHISTO_S1, USB_DEVICE_ID_MEPHISTO_S1) }, - { 0 } -}; -MODULE_DEVICE_TABLE (usb, me_usb_table); - -static struct usb_driver me_usb_driver = -{ - .name = MEMAIN_NAME, - .id_table = me_usb_table, - .probe = me_probe_usb, - .disconnect = me_disconnect_usb -}; -*/ - -#ifdef ME_LOCK_MULTIPLEX_TEMPLATE -ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_device", - me_lock_device_t, - me_lock_device, - me_device_lock_device, - (device, filep, karg.lock, karg.flags)) - - ME_LOCK_MULTIPLEX_TEMPLATE("me_lock_subdevice", - me_lock_subdevice_t, - me_lock_subdevice, - me_device_lock_subdevice, - (device, filep, karg.subdevice, karg.lock, - karg.flags)) -#else -#error macro ME_LOCK_MULTIPLEX_TEMPLATE not defined -#endif - -#ifdef ME_IO_MULTIPLEX_TEMPLATE -ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_start", - me_io_irq_start_t, - me_io_irq_start, - me_device_io_irq_start, - (device, - filep, - karg.subdevice, - karg.channel, - karg.irq_source, - karg.irq_edge, karg.irq_arg, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_wait", - me_io_irq_wait_t, - me_io_irq_wait, - me_device_io_irq_wait, - (device, - filep, - karg.subdevice, - karg.channel, - &karg.irq_count, &karg.value, karg.time_out, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_irq_stop", - me_io_irq_stop_t, - me_io_irq_stop, - me_device_io_irq_stop, - (device, - filep, karg.subdevice, karg.channel, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_device", - me_io_reset_device_t, - me_io_reset_device, - me_device_io_reset_device, (device, filep, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_reset_subdevice", - me_io_reset_subdevice_t, - me_io_reset_subdevice, - me_device_io_reset_subdevice, - (device, filep, karg.subdevice, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_single_config", - me_io_single_config_t, - me_io_single_config, - me_device_io_single_config, - (device, - filep, - karg.subdevice, - karg.channel, - karg.single_config, - karg.ref, - karg.trig_chan, - karg.trig_type, karg.trig_edge, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_new_values", - me_io_stream_new_values_t, - me_io_stream_new_values, - me_device_io_stream_new_values, - (device, - filep, - karg.subdevice, karg.time_out, &karg.count, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_read", - me_io_stream_read_t, - me_io_stream_read, - me_device_io_stream_read, - (device, - filep, - karg.subdevice, - karg.read_mode, karg.values, &karg.count, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_status", - me_io_stream_status_t, - me_io_stream_status, - me_device_io_stream_status, - (device, - filep, - karg.subdevice, - karg.wait, &karg.status, &karg.count, karg.flags)) - - ME_IO_MULTIPLEX_TEMPLATE("me_io_stream_write", - me_io_stream_write_t, - me_io_stream_write, - me_device_io_stream_write, - (device, - filep, - karg.subdevice, - karg.write_mode, karg.values, &karg.count, karg.flags)) -#else -#error macro ME_IO_MULTIPLEX_TEMPLATE not defined -#endif - -#ifdef ME_QUERY_MULTIPLEX_STR_TEMPLATE -ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device", - me_query_name_device_t, - me_query_name_device, - me_device_query_name_device, (device, &msg)) - - ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_name_device_driver", - me_query_name_device_driver_t, - me_query_name_device_driver, - me_device_query_name_device_driver, - (device, &msg)) - - ME_QUERY_MULTIPLEX_STR_TEMPLATE("me_query_description_device", - me_query_description_device_t, - me_query_description_device, - me_device_query_description_device, - (device, &msg)) -#else -#error macro ME_QUERY_MULTIPLEX_STR_TEMPLATE not defined -#endif - -#ifdef ME_QUERY_MULTIPLEX_TEMPLATE -ME_QUERY_MULTIPLEX_TEMPLATE("me_query_info_device", - me_query_info_device_t, - me_query_info_device, - me_device_query_info_device, - (device, - &karg.vendor_id, - &karg.device_id, - &karg.serial_no, - &karg.bus_type, - &karg.bus_no, - &karg.dev_no, &karg.func_no, &karg.plugged)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_subdevices", - me_query_number_subdevices_t, - me_query_number_subdevices, - me_device_query_number_subdevices, - (device, &karg.number)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_channels", - me_query_number_channels_t, - me_query_number_channels, - me_device_query_number_channels, - (device, karg.subdevice, &karg.number)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_by_type", - me_query_subdevice_by_type_t, - me_query_subdevice_by_type, - me_device_query_subdevice_by_type, - (device, - karg.start_subdevice, - karg.type, karg.subtype, &karg.subdevice)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_type", - me_query_subdevice_type_t, - me_query_subdevice_type, - me_device_query_subdevice_type, - (device, karg.subdevice, &karg.type, &karg.subtype)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps", - me_query_subdevice_caps_t, - me_query_subdevice_caps, - me_device_query_subdevice_caps, - (device, karg.subdevice, &karg.caps)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_subdevice_caps_args", - me_query_subdevice_caps_args_t, - me_query_subdevice_caps_args, - me_device_query_subdevice_caps_args, - (device, karg.subdevice, karg.cap, karg.args, - karg.count)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_number_ranges", - me_query_number_ranges_t, - me_query_number_ranges, - me_device_query_number_ranges, - (device, karg.subdevice, karg.unit, &karg.number)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_by_min_max", - me_query_range_by_min_max_t, - me_query_range_by_min_max, - me_device_query_range_by_min_max, - (device, - karg.subdevice, - karg.unit, - &karg.min, &karg.max, &karg.max_data, &karg.range)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_range_info", - me_query_range_info_t, - me_query_range_info, - me_device_query_range_info, - (device, - karg.subdevice, - karg.range, - &karg.unit, &karg.min, &karg.max, &karg.max_data)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_timer", - me_query_timer_t, - me_query_timer, - me_device_query_timer, - (device, - karg.subdevice, - karg.timer, - &karg.base_frequency, - &karg.min_ticks, &karg.max_ticks)) - - ME_QUERY_MULTIPLEX_TEMPLATE("me_query_version_device_driver", - me_query_version_device_driver_t, - me_query_version_device_driver, - me_device_query_version_device_driver, - (device, &karg.version)) -#else -#error macro ME_QUERY_MULTIPLEX_TEMPLATE not defined -#endif - -/** ******************************************************************************** **/ - -static me_device_t *get_dummy_instance(unsigned short vendor_id, - unsigned short device_id, - unsigned int serial_no, - int bus_type, - int bus_no, int dev_no, int func_no) -{ - int err; - me_dummy_constructor_t constructor = NULL; - me_device_t *instance; - - PDEBUG("executed.\n"); - - if ((constructor = symbol_get(medummy_constructor)) == NULL) { - err = request_module(MEDUMMY_NAME); - - if (err) { - PERROR("Error while request for module %s.\n", - MEDUMMY_NAME); - return NULL; - } - - if ((constructor = symbol_get(medummy_constructor)) == NULL) { - PERROR("Can't get %s driver module constructor.\n", - MEDUMMY_NAME); - return NULL; - } - } - - if ((instance = (*constructor) (vendor_id, - device_id, - serial_no, - bus_type, - bus_no, dev_no, func_no)) == NULL) - symbol_put(medummy_constructor); - - return instance; -} - -static int __devinit me_probe_pci(struct pci_dev *dev, - const struct pci_device_id *id) -{ - int err; - me_pci_constructor_t constructor = NULL; -#ifdef BOSCH - me_bosch_constructor_t constructor_bosch = NULL; -#endif - me_device_t *n_device = NULL; - uint32_t device; - - char constructor_name[24] = "me0000_pci_constructor"; - char module_name[7] = "me0000"; - - PDEBUG("executed.\n"); - device = dev->device; - if ((device & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver. - device &= 0xF0FF; - } - - constructor_name[2] += (char)((device >> 12) & 0x000F); - constructor_name[3] += (char)((device >> 8) & 0x000F); - PDEBUG("constructor_name: %s\n", constructor_name); - module_name[2] += (char)((device >> 12) & 0x000F); - module_name[3] += (char)((device >> 8) & 0x000F); - PDEBUG("module_name: %s\n", module_name); - - if ((constructor = - (me_pci_constructor_t) symbol_get(constructor_name)) == NULL) { - if (request_module("%s", module_name)) { - PERROR("Error while request for module %s.\n", - module_name); - return -ENODEV; - } - - if ((constructor = - (me_pci_constructor_t) symbol_get(constructor_name)) == - NULL) { - PERROR("Can't get %s driver module constructor.\n", - module_name); - return -ENODEV; - } - } -#ifdef BOSCH - if ((device & 0xF000) == 0x4000) { // Bosch build has differnt constructor for me4600. - if ((n_device = - (*constructor_bosch) (dev, me_bosch_fw)) == NULL) { - symbol_put(constructor_name); - PERROR - ("Can't get device instance of %s driver module.\n", - module_name); - return -ENODEV; - } - } else { -#endif - if ((n_device = (*constructor) (dev)) == NULL) { - symbol_put(constructor_name); - PERROR - ("Can't get device instance of %s driver module.\n", - module_name); - return -ENODEV; - } -#ifdef BOSCH - } -#endif - - insert_to_device_list(n_device); - err = - n_device->me_device_io_reset_device(n_device, NULL, - ME_IO_RESET_DEVICE_NO_FLAGS); - if (err) { - PERROR("Error while reseting device.\n"); - } else { - PDEBUG("Reseting device was sucessful.\n"); - } - return ME_ERRNO_SUCCESS; -} - -static void release_instance(me_device_t *device) -{ - int vendor_id; - int device_id; - int serial_no; - int bus_type; - int bus_no; - int dev_no; - int func_no; - int plugged; - - uint32_t dev_id; - - char constructor_name[24] = "me0000_pci_constructor"; - - PDEBUG("executed.\n"); - - device->me_device_query_info_device(device, - &vendor_id, - &device_id, - &serial_no, - &bus_type, - &bus_no, - &dev_no, &func_no, &plugged); - - dev_id = device_id; - device->me_device_destructor(device); - - if (plugged != ME_PLUGGED_IN) { - PDEBUG("release: medummy_constructor\n"); - - symbol_put("medummy_constructor"); - } else { - if ((dev_id & 0xF000) == 0x6000) { // Exceptions: me61xx, me62xx, me63xx are handled by one driver. - dev_id &= 0xF0FF; - } - - constructor_name[2] += (char)((dev_id >> 12) & 0x000F); - constructor_name[3] += (char)((dev_id >> 8) & 0x000F); - PDEBUG("release: %s\n", constructor_name); - - symbol_put(constructor_name); - } -} - -static int insert_to_device_list(me_device_t *n_device) -{ - me_device_t *o_device = NULL; - - struct list_head *pos; - int n_vendor_id; - int n_device_id; - int n_serial_no; - int n_bus_type; - int n_bus_no; - int n_dev_no; - int n_func_no; - int n_plugged; - int o_vendor_id; - int o_device_id; - int o_serial_no; - int o_bus_type; - int o_bus_no; - int o_dev_no; - int o_func_no; - int o_plugged; - - PDEBUG("executed.\n"); - - n_device->me_device_query_info_device(n_device, - &n_vendor_id, - &n_device_id, - &n_serial_no, - &n_bus_type, - &n_bus_no, - &n_dev_no, - &n_func_no, &n_plugged); - - down_write(&me_rwsem); - - list_for_each(pos, &me_device_list) { - o_device = list_entry(pos, me_device_t, list); - o_device->me_device_query_info_device(o_device, - &o_vendor_id, - &o_device_id, - &o_serial_no, - &o_bus_type, - &o_bus_no, - &o_dev_no, - &o_func_no, &o_plugged); - - if (o_plugged == ME_PLUGGED_OUT) { - if (((o_vendor_id == n_vendor_id) && - (o_device_id == n_device_id) && - (o_serial_no == n_serial_no) && - (o_bus_type == n_bus_type)) || - ((o_vendor_id == n_vendor_id) && - (o_device_id == n_device_id) && - (o_bus_type == n_bus_type) && - (o_bus_no == n_bus_no) && - (o_dev_no == n_dev_no) && - (o_func_no == n_func_no))) { - n_device->list.prev = pos->prev; - n_device->list.next = pos->next; - pos->prev->next = &n_device->list; - pos->next->prev = &n_device->list; - release_instance(o_device); - break; - } - } - } - - if (pos == &me_device_list) { - list_add_tail(&n_device->list, &me_device_list); - } - - up_write(&me_rwsem); - - return 0; -} - -static void __devexit me_remove_pci(struct pci_dev *dev) -{ - int vendor_id = dev->vendor; - int device_id = dev->device; - int subsystem_vendor = dev->subsystem_vendor; - int subsystem_device = dev->subsystem_device; - int serial_no = (subsystem_device << 16) | subsystem_vendor; - - PDEBUG("executed.\n"); - - PINFO("Vendor id = 0x%08X\n", vendor_id); - PINFO("Device id = 0x%08X\n", device_id); - PINFO("Serial Number = 0x%08X\n", serial_no); - - replace_with_dummy(vendor_id, device_id, serial_no); -} - -static int replace_with_dummy(int vendor_id, int device_id, int serial_no) -{ - - struct list_head *pos; - me_device_t *n_device = NULL; - me_device_t *o_device = NULL; - int o_vendor_id; - int o_device_id; - int o_serial_no; - int o_bus_type; - int o_bus_no; - int o_dev_no; - int o_func_no; - int o_plugged; - - PDEBUG("executed.\n"); - - down_write(&me_rwsem); - - list_for_each(pos, &me_device_list) { - o_device = list_entry(pos, me_device_t, list); - o_device->me_device_query_info_device(o_device, - &o_vendor_id, - &o_device_id, - &o_serial_no, - &o_bus_type, - &o_bus_no, - &o_dev_no, - &o_func_no, &o_plugged); - - if (o_plugged == ME_PLUGGED_IN) { - if (((o_vendor_id == vendor_id) && - (o_device_id == device_id) && - (o_serial_no == serial_no))) { - n_device = get_dummy_instance(o_vendor_id, - o_device_id, - o_serial_no, - o_bus_type, - o_bus_no, - o_dev_no, - o_func_no); - - if (!n_device) { - up_write(&me_rwsem); - PERROR("Cannot get dummy instance.\n"); - return 1; - } - - n_device->list.prev = pos->prev; - - n_device->list.next = pos->next; - pos->prev->next = &n_device->list; - pos->next->prev = &n_device->list; - release_instance(o_device); - break; - } - } - } - - up_write(&me_rwsem); - - return 0; -} - -static void clear_device_list(void) -{ - - struct list_head *entry; - me_device_t *device; - - // Clear the device info list . - down_write(&me_rwsem); - - while (!list_empty(&me_device_list)) { - entry = me_device_list.next; - device = list_entry(entry, me_device_t, list); - list_del(entry); - release_instance(device); - } - - up_write(&me_rwsem); -} - -static int lock_driver(struct file *filep, int lock, int flags) -{ - int err = ME_ERRNO_SUCCESS; - me_device_t *device; - - PDEBUG("executed.\n"); - - down_read(&me_rwsem); - - spin_lock(&me_lock); - - switch (lock) { - - case ME_LOCK_SET: - if (me_count) { - PERROR - ("Driver System is currently used by another process.\n"); - err = ME_ERRNO_USED; - } else if ((me_filep != NULL) && (me_filep != filep)) { - PERROR - ("Driver System is already logged by another process.\n"); - err = ME_ERRNO_LOCKED; - } else { - list_for_each_entry(device, &me_device_list, list) { - err = - device->me_device_lock_device(device, filep, - ME_LOCK_CHECK, - flags); - - if (err) - break; - } - - if (!err) - me_filep = filep; - } - - break; - - case ME_LOCK_RELEASE: - if ((me_filep != NULL) && (me_filep != filep)) { - err = ME_ERRNO_SUCCESS; - } else { - list_for_each_entry(device, &me_device_list, list) { - device->me_device_lock_device(device, filep, - ME_LOCK_RELEASE, - flags); - } - - me_filep = NULL; - } - - break; - - default: - PERROR("Invalid lock specified.\n"); - - err = ME_ERRNO_INVALID_LOCK; - - break; - } - - spin_unlock(&me_lock); - - up_read(&me_rwsem); - - return err; -} - -static int me_lock_driver(struct file *filep, me_lock_driver_t *arg) -{ - int err = 0; - - me_lock_driver_t lock; - - PDEBUG("executed.\n"); - - err = copy_from_user(&lock, arg, sizeof(me_lock_driver_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - - lock.errno = lock_driver(filep, lock.lock, lock.flags); - - err = copy_to_user(arg, &lock, sizeof(me_lock_driver_t)); - - if (err) { - PERROR("Can't copy query back to user space.\n"); - return -EFAULT; - } - - return ME_ERRNO_SUCCESS; -} - -static int me_open(struct inode *inode_ptr, struct file *filep) -{ - - PDEBUG("executed.\n"); - // Nothing to do here. - return 0; -} - -static int me_release(struct inode *inode_ptr, struct file *filep) -{ - - PDEBUG("executed.\n"); - lock_driver(filep, ME_LOCK_RELEASE, ME_LOCK_DRIVER_NO_FLAGS); - - return 0; -} - -static int me_query_version_main_driver(struct file *filep, - me_query_version_main_driver_t *arg) -{ - int err; - me_query_version_main_driver_t karg; - - PDEBUG("executed.\n"); - - karg.version = ME_VERSION_DRIVER; - karg.errno = ME_ERRNO_SUCCESS; - - err = copy_to_user(arg, &karg, sizeof(me_query_version_main_driver_t)); - - if (err) { - PERROR("Can't copy query back to user space.\n"); - return -EFAULT; - } - - return 0; -} - -static int me_config_load_device(struct file *filep, - me_cfg_device_entry_t *karg, int device_no) -{ - - int err = ME_ERRNO_SUCCESS; - int k = 0; - - struct list_head *pos = NULL; - me_device_t *device = NULL; - - PDEBUG("executed.\n"); - - list_for_each(pos, &me_device_list) { - if (k == device_no) { - device = list_entry(pos, me_device_t, list); - break; - } - - k++; - } - - if (pos == &me_device_list) { - PERROR("Invalid device number specified.\n"); - return ME_ERRNO_INVALID_DEVICE; - } else { - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Resource is locked by another process.\n"); - return ME_ERRNO_LOCKED; - } else { - me_count++; - spin_unlock(&me_lock); - - err = - device->me_device_config_load(device, filep, karg); - - spin_lock(&me_lock); - me_count--; - spin_unlock(&me_lock); - } - } - - return err; -} - -static int me_config_load(struct file *filep, me_config_load_t *arg) -{ - int err; - int i; - me_config_load_t cfg_setup; - me_config_load_t karg_cfg_setup; - - struct list_head *pos = NULL; - - struct list_head new_list; - me_device_t *o_device; - me_device_t *n_device; - int o_vendor_id; - int o_device_id; - int o_serial_no; - int o_bus_type; - int o_bus_no; - int o_dev_no; - int o_func_no; - int o_plugged; - - PDEBUG("executed.\n"); - - // Copy argument to kernel space. - err = copy_from_user(&karg_cfg_setup, arg, sizeof(me_config_load_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - // Allocate kernel buffer for device list. - cfg_setup.device_list = - kmalloc(sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count, - GFP_KERNEL); - - if (!cfg_setup.device_list) { - PERROR("Can't get buffer %li for device list.\n", - sizeof(me_cfg_device_entry_t) * karg_cfg_setup.count); - return -ENOMEM; - } - // Copy device list to kernel space. - err = - copy_from_user(cfg_setup.device_list, karg_cfg_setup.device_list, - sizeof(me_cfg_device_entry_t) * - karg_cfg_setup.count); - - if (err) { - PERROR("Can't copy device list to kernel space.\n"); - kfree(cfg_setup.device_list); - return -EFAULT; - } - - cfg_setup.count = karg_cfg_setup.count; - - INIT_LIST_HEAD(&new_list); - - down_write(&me_rwsem); - - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Driver System is logged by another process.\n"); - karg_cfg_setup.errno = ME_ERRNO_LOCKED; - } else { - me_count++; - spin_unlock(&me_lock); - - for (i = 0; i < karg_cfg_setup.count; i++) { - PDEBUG("me_config_load() device=%d.\n", i); - if (cfg_setup.device_list[i].tcpip.access_type == - ME_ACCESS_TYPE_LOCAL) { - list_for_each(pos, &me_device_list) { - o_device = - list_entry(pos, me_device_t, list); - o_device-> - me_device_query_info_device - (o_device, &o_vendor_id, - &o_device_id, &o_serial_no, - &o_bus_type, &o_bus_no, &o_dev_no, - &o_func_no, &o_plugged); - - if (cfg_setup.device_list[i].info. - hw_location.bus_type == - ME_BUS_TYPE_PCI) { - if (((o_vendor_id == - cfg_setup.device_list[i]. - info.vendor_id) - && (o_device_id == - cfg_setup. - device_list[i].info. - device_id) - && (o_serial_no == - cfg_setup. - device_list[i].info. - serial_no) - && (o_bus_type == - cfg_setup. - device_list[i].info. - hw_location.bus_type)) - || - ((o_vendor_id == - cfg_setup.device_list[i]. - info.vendor_id) - && (o_device_id == - cfg_setup. - device_list[i].info. - device_id) - && (o_bus_type == - cfg_setup. - device_list[i].info. - hw_location.bus_type) - && (o_bus_no == - cfg_setup. - device_list[i].info. - hw_location.pci.bus_no) - && (o_dev_no == - cfg_setup. - device_list[i].info. - hw_location.pci. - device_no) - && (o_func_no == - cfg_setup. - device_list[i].info. - hw_location.pci. - function_no))) { - list_move_tail(pos, - &new_list); - break; - } - } -/* - else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB) - { - if (((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) && - (o_device_id == cfg_setup.device_list[i].info.device_id) && - (o_serial_no == cfg_setup.device_list[i].info.serial_no) && - (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type)) || - ((o_vendor_id == cfg_setup.device_list[i].info.vendor_id) && - (o_device_id == cfg_setup.device_list[i].info.device_id) && - (o_bus_type == cfg_setup.device_list[i].info.hw_location.bus_type) && - (o_bus_no == cfg_setup.device_list[i].info.hw_location.usb.root_hub_no))) - { - list_move_tail(pos, &new_list); - break; - } - } -*/ - else { - PERROR("Wrong bus type: %d.\n", - cfg_setup.device_list[i]. - info.hw_location. - bus_type); - } - } - - if (pos == &me_device_list) { // Device is not already in the list - if (cfg_setup.device_list[i].info. - hw_location.bus_type == - ME_BUS_TYPE_PCI) { - n_device = - get_dummy_instance - (cfg_setup.device_list[i]. - info.vendor_id, - cfg_setup.device_list[i]. - info.device_id, - cfg_setup.device_list[i]. - info.serial_no, - cfg_setup.device_list[i]. - info.hw_location.bus_type, - cfg_setup.device_list[i]. - info.hw_location.pci. - bus_no, - cfg_setup.device_list[i]. - info.hw_location.pci. - device_no, - cfg_setup.device_list[i]. - info.hw_location.pci. - function_no); - - if (!n_device) { - PERROR - ("Can't get dummy instance.\n"); - kfree(cfg_setup. - device_list); - spin_lock(&me_lock); - me_count--; - spin_unlock(&me_lock); - up_write(&me_rwsem); - return -EFAULT; - } - - list_add_tail(&n_device->list, - &new_list); - } -/* - else if (cfg_setup.device_list[i].info.hw_location.bus_type == ME_BUS_TYPE_USB) - { - n_device = get_dummy_instance( - cfg_setup.device_list[i].info.vendor_id, - cfg_setup.device_list[i].info.device_id, - cfg_setup.device_list[i].info.serial_no, - cfg_setup.device_list[i].info.hw_location.bus_type, - cfg_setup.device_list[i].info.hw_location.usb.root_hub_no, - 0, - 0); - - if (!n_device) - { - PERROR("Can't get dummy instance.\n"); - kfree(cfg_setup.device_list); - spin_lock(&me_lock); - me_count--; - spin_unlock(&me_lock); - up_write(&me_rwsem); - return -EFAULT; - } - - list_add_tail(&n_device->list, &new_list); - } -*/ - } - } else { - n_device = get_dummy_instance(0, - 0, 0, 0, 0, 0, 0); - - if (!n_device) { - PERROR("Can't get dummy instance.\n"); - kfree(cfg_setup.device_list); - spin_lock(&me_lock); - me_count--; - spin_unlock(&me_lock); - up_write(&me_rwsem); - return -EFAULT; - } - - list_add_tail(&n_device->list, &new_list); - } - } - - while (!list_empty(&me_device_list)) { - o_device = - list_entry(me_device_list.next, me_device_t, list); - o_device->me_device_query_info_device(o_device, - &o_vendor_id, - &o_device_id, - &o_serial_no, - &o_bus_type, - &o_bus_no, - &o_dev_no, - &o_func_no, - &o_plugged); - - if (o_plugged == ME_PLUGGED_IN) { - list_move_tail(me_device_list.next, &new_list); - } else { - list_del(me_device_list.next); - release_instance(o_device); - } - } - - // Move temporary new list to global driver list. - list_splice(&new_list, &me_device_list); - - karg_cfg_setup.errno = ME_ERRNO_SUCCESS; - } - - for (i = 0; i < cfg_setup.count; i++) { - - karg_cfg_setup.errno = - me_config_load_device(filep, &cfg_setup.device_list[i], i); - if (karg_cfg_setup.errno) { - PERROR("me_config_load_device(%d)=%d\n", i, - karg_cfg_setup.errno); - break; - } - } - - spin_lock(&me_lock); - - me_count--; - spin_unlock(&me_lock); - up_write(&me_rwsem); - - err = copy_to_user(arg, &karg_cfg_setup, sizeof(me_config_load_t)); - - if (err) { - PERROR("Can't copy config list to user space.\n"); - kfree(cfg_setup.device_list); - return -EFAULT; - } - - kfree(cfg_setup.device_list); - return 0; -} - -static int me_io_stream_start(struct file *filep, me_io_stream_start_t *arg) -{ - int err; - int i, k; - - struct list_head *pos; - me_device_t *device; - me_io_stream_start_t karg; - meIOStreamStart_t *list; - - PDEBUG("executed.\n"); - - err = copy_from_user(&karg, arg, sizeof(me_io_stream_start_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - - karg.errno = ME_ERRNO_SUCCESS; - - list = kmalloc(sizeof(meIOStreamStart_t) * karg.count, GFP_KERNEL); - - if (!list) { - PERROR("Can't get buffer for start list.\n"); - return -ENOMEM; - } - - err = - copy_from_user(list, karg.start_list, - sizeof(meIOStreamStart_t) * karg.count); - - if (err) { - PERROR("Can't copy start list to kernel space.\n"); - kfree(list); - return -EFAULT; - } - - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Driver System is logged by another process.\n"); - - for (i = 0; i < karg.count; i++) { - list[i].iErrno = ME_ERRNO_LOCKED; - } - } else { - me_count++; - spin_unlock(&me_lock); - - for (i = 0; i < karg.count; i++) { - down_read(&me_rwsem); - k = 0; - list_for_each(pos, &me_device_list) { - if (k == list[i].iDevice) { - device = - list_entry(pos, me_device_t, list); - break; - } - - k++; - } - - if (pos == &me_device_list) { - up_read(&me_rwsem); - PERROR("Invalid device number specified.\n"); - list[i].iErrno = ME_ERRNO_INVALID_DEVICE; - karg.errno = ME_ERRNO_INVALID_DEVICE; - break; - } else { - list[i].iErrno = - device->me_device_io_stream_start(device, - filep, - list[i]. - iSubdevice, - list[i]. - iStartMode, - list[i]. - iTimeOut, - list[i]. - iFlags); - - if (list[i].iErrno) { - up_read(&me_rwsem); - karg.errno = list[i].iErrno; - break; - } - } - - up_read(&me_rwsem); - } - - spin_lock(&me_lock); - - me_count--; - spin_unlock(&me_lock); - } - - err = copy_to_user(arg, &karg, sizeof(me_io_stream_start_t)); - - if (err) { - PERROR("Can't copy arguments to user space.\n"); - kfree(list); - return -EFAULT; - } - - err = - copy_to_user(karg.start_list, list, - sizeof(meIOStreamStart_t) * karg.count); - - if (err) { - PERROR("Can't copy start list to user space.\n"); - kfree(list); - return -EFAULT; - } - - kfree(list); - - return err; -} - -static int me_io_single(struct file *filep, me_io_single_t *arg) -{ - int err; - int i, k; - - struct list_head *pos; - me_device_t *device; - me_io_single_t karg; - meIOSingle_t *list; - - PDEBUG("executed.\n"); - - err = copy_from_user(&karg, arg, sizeof(me_io_single_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - - karg.errno = ME_ERRNO_SUCCESS; - - list = kmalloc(sizeof(meIOSingle_t) * karg.count, GFP_KERNEL); - - if (!list) { - PERROR("Can't get buffer for single list.\n"); - return -ENOMEM; - } - - err = - copy_from_user(list, karg.single_list, - sizeof(meIOSingle_t) * karg.count); - - if (err) { - PERROR("Can't copy single list to kernel space.\n"); - kfree(list); - return -EFAULT; - } - - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Driver System is logged by another process.\n"); - - for (i = 0; i < karg.count; i++) { - list[i].iErrno = ME_ERRNO_LOCKED; - } - } else { - me_count++; - spin_unlock(&me_lock); - - for (i = 0; i < karg.count; i++) { - k = 0; - - down_read(&me_rwsem); - - list_for_each(pos, &me_device_list) { - if (k == list[i].iDevice) { - device = - list_entry(pos, me_device_t, list); - break; - } - - k++; - } - - if (pos == &me_device_list) { - up_read(&me_rwsem); - PERROR("Invalid device number specified.\n"); - list[i].iErrno = ME_ERRNO_INVALID_DEVICE; - karg.errno = ME_ERRNO_INVALID_DEVICE; - break; - } else { - if (list[i].iDir == ME_DIR_OUTPUT) { - list[i].iErrno = - device-> - me_device_io_single_write(device, - filep, - list[i]. - iSubdevice, - list[i]. - iChannel, - list[i]. - iValue, - list[i]. - iTimeOut, - list[i]. - iFlags); - - if (list[i].iErrno) { - up_read(&me_rwsem); - karg.errno = list[i].iErrno; - break; - } - } else if (list[i].iDir == ME_DIR_INPUT) { - list[i].iErrno = - device-> - me_device_io_single_read(device, - filep, - list[i]. - iSubdevice, - list[i]. - iChannel, - &list[i]. - iValue, - list[i]. - iTimeOut, - list[i]. - iFlags); - - if (list[i].iErrno) { - up_read(&me_rwsem); - karg.errno = list[i].iErrno; - break; - } - } else { - up_read(&me_rwsem); - PERROR - ("Invalid single direction specified.\n"); - list[i].iErrno = ME_ERRNO_INVALID_DIR; - karg.errno = ME_ERRNO_INVALID_DIR; - break; - } - } - - up_read(&me_rwsem); - } - - spin_lock(&me_lock); - - me_count--; - spin_unlock(&me_lock); - } - - err = copy_to_user(arg, &karg, sizeof(me_io_single_t)); - - if (err) { - PERROR("Can't copy arguments to user space.\n"); - return -EFAULT; - } - - err = - copy_to_user(karg.single_list, list, - sizeof(meIOSingle_t) * karg.count); - - if (err) { - PERROR("Can't copy single list to user space.\n"); - kfree(list); - return -EFAULT; - } - - kfree(list); - - return err; -} - -static int me_io_stream_config(struct file *filep, me_io_stream_config_t *arg) -{ - int err; - int k = 0; - - struct list_head *pos; - me_device_t *device; - me_io_stream_config_t karg; - meIOStreamConfig_t *list; - - PDEBUG("executed.\n"); - - err = copy_from_user(&karg, arg, sizeof(me_io_stream_config_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - - list = kmalloc(sizeof(meIOStreamConfig_t) * karg.count, GFP_KERNEL); - - if (!list) { - PERROR("Can't get buffer for config list.\n"); - return -ENOMEM; - } - - err = - copy_from_user(list, karg.config_list, - sizeof(meIOStreamConfig_t) * karg.count); - - if (err) { - PERROR("Can't copy config list to kernel space.\n"); - kfree(list); - return -EFAULT; - } - - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Driver System is logged by another process.\n"); - karg.errno = ME_ERRNO_LOCKED; - } else { - me_count++; - spin_unlock(&me_lock); - - down_read(&me_rwsem); - - list_for_each(pos, &me_device_list) { - if (k == karg.device) { - device = list_entry(pos, me_device_t, list); - break; - } - - k++; - } - - if (pos == &me_device_list) { - PERROR("Invalid device number specified.\n"); - karg.errno = ME_ERRNO_INVALID_DEVICE; - } else { - karg.errno = - device->me_device_io_stream_config(device, filep, - karg.subdevice, - list, karg.count, - &karg.trigger, - karg. - fifo_irq_threshold, - karg.flags); - } - - up_read(&me_rwsem); - - spin_lock(&me_lock); - me_count--; - spin_unlock(&me_lock); - } - - err = copy_to_user(arg, &karg, sizeof(me_io_stream_config_t)); - - if (err) { - PERROR("Can't copy back to user space.\n"); - kfree(list); - return -EFAULT; - } - - kfree(list); - - return err; -} - -static int me_query_number_devices(struct file *filep, - me_query_number_devices_t *arg) -{ - int err; - me_query_number_devices_t karg; - - struct list_head *pos; - - PDEBUG("executed.\n"); - - karg.number = 0; - down_read(&me_rwsem); - list_for_each(pos, &me_device_list) { - karg.number++; - } - - up_read(&me_rwsem); - - karg.errno = ME_ERRNO_SUCCESS; - - err = copy_to_user(arg, &karg, sizeof(me_query_number_devices_t)); - - if (err) { - PERROR("Can't copy query back to user space.\n"); - return -EFAULT; - } - - return 0; -} - -static int me_io_stream_stop(struct file *filep, me_io_stream_stop_t *arg) -{ - int err; - int i, k; - - struct list_head *pos; - me_device_t *device; - me_io_stream_stop_t karg; - meIOStreamStop_t *list; - - PDEBUG("executed.\n"); - - err = copy_from_user(&karg, arg, sizeof(me_io_stream_stop_t)); - - if (err) { - PERROR("Can't copy arguments to kernel space.\n"); - return -EFAULT; - } - - karg.errno = ME_ERRNO_SUCCESS; - - list = kmalloc(sizeof(meIOStreamStop_t) * karg.count, GFP_KERNEL); - - if (!list) { - PERROR("Can't get buffer for stop list.\n"); - return -ENOMEM; - } - - err = - copy_from_user(list, karg.stop_list, - sizeof(meIOStreamStop_t) * karg.count); - - if (err) { - PERROR("Can't copy stop list to kernel space.\n"); - kfree(list); - return -EFAULT; - } - - spin_lock(&me_lock); - - if ((me_filep != NULL) && (me_filep != filep)) { - spin_unlock(&me_lock); - PERROR("Driver System is logged by another process.\n"); - - for (i = 0; i < karg.count; i++) { - list[i].iErrno = ME_ERRNO_LOCKED; - } - } else { - me_count++; - spin_unlock(&me_lock); - - for (i = 0; i < karg.count; i++) { - k = 0; - down_read(&me_rwsem); - list_for_each(pos, &me_device_list) { - if (k == list[i].iDevice) { - device = - list_entry(pos, me_device_t, list); - break; - } - - k++; - } - - if (pos == &me_device_list) { - up_read(&me_rwsem); - PERROR("Invalid device number specified.\n"); - list[i].iErrno = ME_ERRNO_INVALID_DEVICE; - karg.errno = ME_ERRNO_INVALID_DEVICE; - break; - } else { - list[i].iErrno = - device->me_device_io_stream_stop(device, - filep, - list[i]. - iSubdevice, - list[i]. - iStopMode, - list[i]. - iFlags); - - if (list[i].iErrno) { - up_read(&me_rwsem); - karg.errno = list[i].iErrno; - break; - } - } - - up_read(&me_rwsem); - } - - spin_lock(&me_lock); - - me_count--; - spin_unlock(&me_lock); - } - - err = copy_to_user(arg, &karg, sizeof(me_io_stream_stop_t)); - - if (err) { - PERROR("Can't copy arguments to user space.\n"); - return -EFAULT; - } - - err = - copy_to_user(karg.stop_list, list, - sizeof(meIOStreamStop_t) * karg.count); - - if (err) { - PERROR("Can't copy stop list to user space.\n"); - kfree(list); - return -EFAULT; - } - - kfree(list); - - return err; -} - -/* //me_probe_usb -static int me_probe_usb(struct usb_interface *interface, const struct usb_device_id *id) -{ - //int err; - //me_usb_constructor_t *constructor = NULL; - me_device_t *n_device = NULL; - - PDEBUG("executed.\n"); - - switch (id->idProduct) - { - case USB_DEVICE_ID_MEPHISTO_S1: - if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){ - err = request_module(MEPHISTO_S1_NAME); - if(err){ - PERROR("Error while request for module %s.\n", MEPHISTO_S1_NAME); - return -ENODEV; - } - if((constructor = symbol_get(mephisto_s1_constructor)) == NULL){ - PERROR("Can't get %s driver module constructor.\n", MEPHISTO_S1_NAME); - return -ENODEV; - } - } - - if((n_device = (*constructor)(interface)) == NULL){ - symbol_put(mephisto_s1_constructor); - PERROR("Can't get device instance of %s driver module.\n", MEPHISTO_S1_NAME); - return -ENODEV; - } - - break; - - default: - PERROR("Invalid product id.\n"); - - return -EINVAL; - } - - return insert_to_device_list(n_device); -} -*/ - -/* //me_disconnect_usb -static void me_disconnect_usb(struct usb_interface *interface) -{ - - struct usb_device *device = interface_to_usbdev(interface); - int vendor_id = device->descriptor.idVendor; - int device_id = device->descriptor.idProduct; - int serial_no; - - sscanf(&device->serial[2], "%x", &serial_no); - - PDEBUG("executed.\n"); - - PINFO("Vendor id = 0x%08X\n", vendor_id); - PINFO("Device id = 0x%08X\n", device_id); - PINFO("Serial Number = 0x%08X\n", serial_no); - - replace_with_dummy(vendor_id, device_id, serial_no); -} -*/ - -static int me_ioctl(struct inode *inodep, - struct file *filep, unsigned int service, unsigned long arg) -{ - - PDEBUG("executed.\n"); - - if (_IOC_TYPE(service) != MEMAIN_MAGIC) { - PERROR("Invalid magic number.\n"); - return -ENOTTY; - } - - PDEBUG("service number: 0x%x.\n", service); - - switch (service) { - case ME_IO_IRQ_ENABLE: - return me_io_irq_start(filep, (me_io_irq_start_t *) arg); - - case ME_IO_IRQ_WAIT: - return me_io_irq_wait(filep, (me_io_irq_wait_t *) arg); - - case ME_IO_IRQ_DISABLE: - return me_io_irq_stop(filep, (me_io_irq_stop_t *) arg); - - case ME_IO_RESET_DEVICE: - return me_io_reset_device(filep, (me_io_reset_device_t *) arg); - - case ME_IO_RESET_SUBDEVICE: - return me_io_reset_subdevice(filep, - (me_io_reset_subdevice_t *) arg); - - case ME_IO_SINGLE_CONFIG: - return me_io_single_config(filep, - (me_io_single_config_t *) arg); - - case ME_IO_SINGLE: - return me_io_single(filep, (me_io_single_t *) arg); - - case ME_IO_STREAM_CONFIG: - return me_io_stream_config(filep, - (me_io_stream_config_t *) arg); - - case ME_IO_STREAM_NEW_VALUES: - return me_io_stream_new_values(filep, - (me_io_stream_new_values_t *) - arg); - - case ME_IO_STREAM_READ: - return me_io_stream_read(filep, (me_io_stream_read_t *) arg); - - case ME_IO_STREAM_START: - return me_io_stream_start(filep, (me_io_stream_start_t *) arg); - - case ME_IO_STREAM_STATUS: - return me_io_stream_status(filep, - (me_io_stream_status_t *) arg); - - case ME_IO_STREAM_STOP: - return me_io_stream_stop(filep, (me_io_stream_stop_t *) arg); - - case ME_IO_STREAM_WRITE: - return me_io_stream_write(filep, (me_io_stream_write_t *) arg); - - case ME_LOCK_DRIVER: - return me_lock_driver(filep, (me_lock_driver_t *) arg); - - case ME_LOCK_DEVICE: - return me_lock_device(filep, (me_lock_device_t *) arg); - - case ME_LOCK_SUBDEVICE: - return me_lock_subdevice(filep, (me_lock_subdevice_t *) arg); - - case ME_QUERY_INFO_DEVICE: - return me_query_info_device(filep, - (me_query_info_device_t *) arg); - - case ME_QUERY_DESCRIPTION_DEVICE: - return me_query_description_device(filep, - (me_query_description_device_t - *) arg); - - case ME_QUERY_NAME_DEVICE: - return me_query_name_device(filep, - (me_query_name_device_t *) arg); - - case ME_QUERY_NAME_DEVICE_DRIVER: - return me_query_name_device_driver(filep, - (me_query_name_device_driver_t - *) arg); - - case ME_QUERY_NUMBER_DEVICES: - return me_query_number_devices(filep, - (me_query_number_devices_t *) - arg); - - case ME_QUERY_NUMBER_SUBDEVICES: - return me_query_number_subdevices(filep, - (me_query_number_subdevices_t - *) arg); - - case ME_QUERY_NUMBER_CHANNELS: - return me_query_number_channels(filep, - (me_query_number_channels_t *) - arg); - - case ME_QUERY_NUMBER_RANGES: - return me_query_number_ranges(filep, - (me_query_number_ranges_t *) arg); - - case ME_QUERY_RANGE_BY_MIN_MAX: - return me_query_range_by_min_max(filep, - (me_query_range_by_min_max_t *) - arg); - - case ME_QUERY_RANGE_INFO: - return me_query_range_info(filep, - (me_query_range_info_t *) arg); - - case ME_QUERY_SUBDEVICE_BY_TYPE: - return me_query_subdevice_by_type(filep, - (me_query_subdevice_by_type_t - *) arg); - - case ME_QUERY_SUBDEVICE_TYPE: - return me_query_subdevice_type(filep, - (me_query_subdevice_type_t *) - arg); - - case ME_QUERY_SUBDEVICE_CAPS: - return me_query_subdevice_caps(filep, - (me_query_subdevice_caps_t *) - arg); - - case ME_QUERY_SUBDEVICE_CAPS_ARGS: - return me_query_subdevice_caps_args(filep, - (me_query_subdevice_caps_args_t - *) arg); - - case ME_QUERY_TIMER: - return me_query_timer(filep, (me_query_timer_t *) arg); - - case ME_QUERY_VERSION_MAIN_DRIVER: - return me_query_version_main_driver(filep, - (me_query_version_main_driver_t - *) arg); - - case ME_QUERY_VERSION_DEVICE_DRIVER: - return me_query_version_device_driver(filep, - (me_query_version_device_driver_t - *) arg); - - case ME_CONFIG_LOAD: - return me_config_load(filep, (me_config_load_t *) arg); - } - - PERROR("Invalid ioctl number.\n"); - return -ENOTTY; -} - -static struct miscdevice me_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = MEMAIN_NAME, - .fops = &me_file_operations, -}; - -// Init and exit of module. -static int memain_init(void) -{ - int result = 0; - - PDEBUG("executed.\n"); - - // Register pci driver. This will return 0 if the PCI subsystem is not available. - result = pci_register_driver(&me_pci_driver); - - if (result < 0) { - PERROR("Can't register pci driver.\n"); - goto INIT_ERROR_1; - } - -/* - // Register usb driver. This will return -ENODEV if no USB subsystem is available. - result = usb_register(&me_usb_driver); - - if (result) - { - if (result == -ENODEV) - { - PERROR("No USB subsystem available.\n"); - } - else - { - PERROR("Can't register usb driver.\n"); - goto INIT_ERROR_2; - } - } -*/ - result = misc_register(&me_miscdev); - if (result < 0) { - printk(KERN_ERR MEMAIN_NAME ": can't register misc device\n"); - goto INIT_ERROR_3; - } - - return 0; - - INIT_ERROR_3: -// usb_deregister(&me_usb_driver); - -//INIT_ERROR_2: - pci_unregister_driver(&me_pci_driver); - clear_device_list(); - - INIT_ERROR_1: - return result; -} - -static void __exit memain_exit(void) -{ - PDEBUG("executed.\n"); - - misc_deregister(&me_miscdev); - pci_unregister_driver(&me_pci_driver); -// usb_deregister(&me_usb_driver); - clear_device_list(); -} - -module_init(memain_init); -module_exit(memain_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR - ("Guenter Gebhardt & Krzysztof Gantzke "); -MODULE_DESCRIPTION("Central module for Meilhaus Driver System."); -MODULE_SUPPORTED_DEVICE("Meilhaus PCI/cPCI boards."); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/memain.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : memain.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _MEMAIN_H_ -#define _MEMAIN_H_ - -#include "meinternal.h" - -#include "meids.h" -#include "medebug.h" - -#include "medevice.h" -/*#include "me1000_device.h" -#include "me1400_device.h" -#include "me1600_device.h"*/ -#include "me4600_device.h" -/*#include "me6000_device.h" -#include "me0600_device.h" -#include "me8100_device.h" -#include "me8200_device.h" -#include "me0900_device.h"*/ -#include "medummy.h" - -#ifdef __KERNEL__ - -/*============================================================================= - Templates - ===========================================================================*/ - -#define ME_LOCK_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ -static int CALL(struct file *filep, TYPE *arg){ \ - int err = 0; \ - int k = 0; \ - struct list_head *pos; \ - me_device_t *device; \ - TYPE karg; \ - \ - PDEBUG("executed.\n"); \ - \ - err = copy_from_user(&karg, arg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments to kernel space\n"); \ - return -EFAULT; \ - } \ - \ - down_read(&me_rwsem); \ - \ - list_for_each(pos, &me_device_list){ \ - if(k == karg.device){ \ - device = list_entry(pos, me_device_t, list); \ - break; \ - } \ - k++; \ - } \ - \ - if(pos == &me_device_list){ \ - PERROR("Invalid device number specified\n"); \ - karg.errno = ME_ERRNO_INVALID_DEVICE; \ - } \ - else{ \ - spin_lock(&me_lock); \ - if((me_filep != NULL) && (me_filep != filep)){ \ - spin_unlock(&me_lock); \ - PERROR("Resource is locked by another process\n"); \ - if(karg.lock == ME_LOCK_SET) \ - karg.errno = ME_ERRNO_LOCKED; \ - else if(karg.lock == ME_LOCK_RELEASE) \ - karg.errno = ME_ERRNO_SUCCESS; \ - else{ \ - PERROR("Invalid lock specified\n"); \ - karg.errno = ME_ERRNO_INVALID_LOCK; \ - }\ - } \ - else { \ - me_count++; \ - spin_unlock(&me_lock); \ - \ - karg.errno = device->DEV_CALL ARGS; \ - \ - spin_lock(&me_lock); \ - me_count--; \ - spin_unlock(&me_lock); \ - } \ - } \ - \ - up_read(&me_rwsem); \ - \ - err = copy_to_user(arg, &karg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments back to user space\n"); \ - return -EFAULT; \ - } \ - \ - return ME_ERRNO_SUCCESS; \ -} - -#define ME_IO_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ -static int CALL(struct file *filep, TYPE *arg){ \ - int err = 0; \ - int k = 0; \ - struct list_head *pos; \ - me_device_t *device; \ - TYPE karg; \ - \ - PDEBUG("executed.\n"); \ - \ - err = copy_from_user(&karg, arg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments to kernel space\n"); \ - return -EFAULT; \ - } \ - \ - down_read(&me_rwsem); \ - \ - list_for_each(pos, &me_device_list){ \ - if(k == karg.device){ \ - device = list_entry(pos, me_device_t, list); \ - break; \ - } \ - k++; \ - } \ - \ - if(pos == &me_device_list){ \ - PERROR("Invalid device number specified\n"); \ - karg.errno = ME_ERRNO_INVALID_DEVICE; \ - } \ - else{ \ - spin_lock(&me_lock); \ - if((me_filep != NULL) && (me_filep != filep)){ \ - spin_unlock(&me_lock); \ - PERROR("Resource is locked by another process\n"); \ - karg.errno = ME_ERRNO_LOCKED; \ - } \ - else { \ - me_count++; \ - spin_unlock(&me_lock); \ - \ - karg.errno = device->DEV_CALL ARGS; \ - \ - spin_lock(&me_lock); \ - me_count--; \ - spin_unlock(&me_lock); \ - } \ - } \ - \ - up_read(&me_rwsem); \ - \ - err = copy_to_user(arg, &karg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments back to user space\n"); \ - return -EFAULT; \ - } \ - \ - return ME_ERRNO_SUCCESS; \ -} - -#define ME_QUERY_MULTIPLEX_STR_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ -static int CALL(struct file *filep, TYPE *arg){ \ - int err = 0; \ - int k = 0; \ - struct list_head *pos; \ - me_device_t *device; \ - char *msg = NULL; \ - TYPE karg; \ - \ - PDEBUG("executed.\n"); \ - \ - err = copy_from_user(&karg, arg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments to kernel space\n"); \ - return -EFAULT; \ - } \ - \ - down_read(&me_rwsem); \ - \ - list_for_each(pos, &me_device_list){ \ - if(k == karg.device){ \ - device = list_entry(pos, me_device_t, list); \ - break; \ - } \ - k++; \ - } \ - \ - if(pos == &me_device_list){ \ - PERROR("Invalid device number specified\n"); \ - karg.errno = ME_ERRNO_INVALID_DEVICE; \ - } \ - else{ \ - karg.errno = device->DEV_CALL ARGS; \ - if(!karg.errno){ \ - if((strlen(msg) + 1) > karg.count){ \ - PERROR("User buffer for device name is to little\n"); \ - karg.errno = ME_ERRNO_USER_BUFFER_SIZE; \ - } \ - else{ \ - err = copy_to_user(karg.name, msg, strlen(msg) + 1); \ - if(err){ \ - PERROR("Can't copy device name to user space\n"); \ - return -EFAULT; \ - } \ - } \ - } \ - } \ - \ - up_read(&me_rwsem); \ - \ - err = copy_to_user(arg, &karg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy query back to user space\n"); \ - return -EFAULT; \ - } \ - \ - return ME_ERRNO_SUCCESS; \ -} - -#define ME_QUERY_MULTIPLEX_TEMPLATE(NAME, TYPE, CALL, DEV_CALL, ARGS) \ -static int CALL(struct file *filep, TYPE *arg){ \ - int err = 0; \ - int k = 0; \ - struct list_head *pos; \ - me_device_t *device; \ - TYPE karg; \ - \ - PDEBUG("executed.\n"); \ - \ - err = copy_from_user(&karg, arg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments from user space\n"); \ - return -EFAULT; \ - } \ - \ - down_read(&me_rwsem); \ - \ - list_for_each(pos, &me_device_list){ \ - if(k == karg.device){ \ - device = list_entry(pos, me_device_t, list); \ - break; \ - } \ - k++; \ - } \ - \ - if(pos == &me_device_list){ \ - PERROR("Invalid device number specified\n"); \ - karg.errno = ME_ERRNO_INVALID_DEVICE; \ - } \ - else{ \ - karg.errno = device->DEV_CALL ARGS; \ - } \ - \ - up_read(&me_rwsem); \ - \ - err = copy_to_user(arg, &karg, sizeof(TYPE)); \ - if(err){ \ - PERROR("Can't copy arguments to user space\n"); \ - return -EFAULT; \ - } \ - \ - return ME_ERRNO_SUCCESS; \ -} - -#endif //__KERNEL__ -#endif --- a/drivers/staging/meilhaus/meplx_reg.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @file meplx_reg.h - * - * @brief PLX 9052 PCI bridge register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _MEPLX_REG_H_ -#define _MEPLX_REG_H_ - -#ifdef __KERNEL__ - -#define PLX_INTCSR 0x4C /**< Interrupt control and status register. */ -#define PLX_INTCSR_LOCAL_INT1_EN 0x01 /**< If set, local interrupt 1 is enabled (r/w). */ -#define PLX_INTCSR_LOCAL_INT1_POL 0x02 /**< If set, local interrupt 1 polarity is active high (r/w). */ -#define PLX_INTCSR_LOCAL_INT1_STATE 0x04 /**< If set, local interrupt 1 is active (r/_). */ -#define PLX_INTCSR_LOCAL_INT2_EN 0x08 /**< If set, local interrupt 2 is enabled (r/w). */ -#define PLX_INTCSR_LOCAL_INT2_POL 0x10 /**< If set, local interrupt 2 polarity is active high (r/w). */ -#define PLX_INTCSR_LOCAL_INT2_STATE 0x20 /**< If set, local interrupt 2 is active (r/_). */ -#define PLX_INTCSR_PCI_INT_EN 0x40 /**< If set, PCI interrupt is enabled (r/w). */ -#define PLX_INTCSR_SOFT_INT 0x80 /**< If set, a software interrupt is generated (r/w). */ - -#define PLX_ICR 0x50 /**< Initialization control register. */ -#define PLX_ICR_BIT_EEPROM_CLOCK_SET 0x01000000 -#define PLX_ICR_BIT_EEPROM_CHIP_SELECT 0x02000000 -#define PLX_ICR_BIT_EEPROM_WRITE 0x04000000 -#define PLX_ICR_BIT_EEPROM_READ 0x08000000 -#define PLX_ICR_BIT_EEPROM_VALID 0x10000000 - -#define PLX_ICR_MASK_EEPROM 0x1F000000 -#define EEPROM_DELAY 1 - -#endif -#endif --- a/drivers/staging/meilhaus/meslist.c +++ /dev/null @@ -1,173 +0,0 @@ -/** - * @file me_slist.c - * - * @brief Implements the subdevice list class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#include "meerror.h" -#include "medefines.h" - -#include "meslist.h" -#include "medebug.h" - -int me_slist_query_number_subdevices(struct me_slist *slist, int *number) -{ - PDEBUG_LOCKS("called.\n"); - *number = slist->n; - return ME_ERRNO_SUCCESS; -} - -unsigned int me_slist_get_number_subdevices(struct me_slist *slist) -{ - PDEBUG_LOCKS("called.\n"); - return slist->n; -} - -me_subdevice_t *me_slist_get_subdevice(struct me_slist * slist, - unsigned int index) -{ - - struct list_head *pos; - me_subdevice_t *subdevice = NULL; - unsigned int i = 0; - - PDEBUG_LOCKS("called.\n"); - - if (index >= slist->n) { - PERROR("Index out of range.\n"); - return NULL; - } - - list_for_each(pos, &slist->head) { - if (i == index) { - subdevice = list_entry(pos, me_subdevice_t, list); - break; - } - - ++i; - } - - return subdevice; -} - -int me_slist_get_subdevice_by_type(struct me_slist *slist, - unsigned int start_subdevice, - int type, int subtype, int *subdevice) -{ - me_subdevice_t *pos; - int s_type, s_subtype; - unsigned int index = 0; - - PDEBUG_LOCKS("called.\n"); - - if (start_subdevice >= slist->n) { - PERROR("Start index out of range.\n"); - return ME_ERRNO_NOMORE_SUBDEVICE_TYPE; - } - - list_for_each_entry(pos, &slist->head, list) { - if (index < start_subdevice) { // Go forward to start subdevice. - ++index; - continue; - } - - pos->me_subdevice_query_subdevice_type(pos, - &s_type, &s_subtype); - - if (subtype == ME_SUBTYPE_ANY) { - if (s_type == type) - break; - } else { - if ((s_type == type) && (s_subtype == subtype)) - break; - } - - ++index; - } - - if (index >= slist->n) { - return ME_ERRNO_NOMORE_SUBDEVICE_TYPE; - } - - *subdevice = index; - - return ME_ERRNO_SUCCESS; -} - -void me_slist_add_subdevice_tail(struct me_slist *slist, - me_subdevice_t *subdevice) -{ - PDEBUG_LOCKS("called.\n"); - - list_add_tail(&subdevice->list, &slist->head); - ++slist->n; -} - -me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist) -{ - - struct list_head *last; - me_subdevice_t *subdevice; - - PDEBUG_LOCKS("called.\n"); - - if (list_empty(&slist->head)) - return NULL; - - last = slist->head.prev; - - subdevice = list_entry(last, me_subdevice_t, list); - - list_del(last); - - --slist->n; - - return subdevice; -} - -int me_slist_init(me_slist_t *slist) -{ - PDEBUG_LOCKS("called.\n"); - - INIT_LIST_HEAD(&slist->head); - slist->n = 0; - return 0; -} - -void me_slist_deinit(me_slist_t *slist) -{ - - struct list_head *s; - me_subdevice_t *subdevice; - - PDEBUG_LOCKS("called.\n"); - - while (!list_empty(&slist->head)) { - s = slist->head.next; - list_del(s); - subdevice = list_entry(s, me_subdevice_t, list); - subdevice->me_subdevice_destructor(subdevice); - } - - slist->n = 0; -} --- a/drivers/staging/meilhaus/meslist.h +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @file me_slist.h - * - * @brief Provides the subdevice list class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _ME_SLIST_H_ -#define _ME_SLIST_H_ - -#include - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The subdevice list container. - */ -typedef struct me_slist { - struct list_head head; /**< The head of the internal list. */ - unsigned int n; /**< The number of subdevices in the list. */ -} me_slist_t; - -/** - * @brief Queries the number of subdevices currently inside the list. - * - * @param slist The subdevice list to query. - * @param[out] number The number of subdevices of the device. - * - * @return ME-iDS error code. - */ -int me_slist_query_number_subdevices(struct me_slist *slist, int *number); - -/** - * @brief Returns the number of subdevices currently inside the list. - * - * @param slist The subdevice list to query. - * - * @return The number of subdevices in the list. - */ -unsigned int me_slist_get_number_subdevices(struct me_slist *slist); - -/** - * @brief Get a subdevice by index. - * - * @param slist The subdevice list to query. - * @param index The index of the subdevice to get in the list. - * - * @return The subdevice at index if available.\n - * NULL if the index is out of range. - */ -me_subdevice_t *me_slist_get_subdevice(struct me_slist *slist, - unsigned int index); - -/** - * @brief Get a subdevice index by type and subtype. - * - * @param slist The subdevice list to query. - * @param start_subdevice The subdevice index at which the start shall begin. - * @param type The type of the subdevice to query. - * @param subtype The subtype of the subdevice to query. - * @param[out] subdevice On success this parameter returns the index of the subdevice matching the requested type. - * - * @return ME_ERRNO_SUCCESS on success. - */ -int me_slist_get_subdevice_by_type(struct me_slist *slist, - unsigned int start_subdevice, - int type, int subtype, int *subdevice); - -/** - * @brief Adds a subdevice to the tail of the list. - * - * @param slist The subdevice list to add a subdevice to. - * @param subdevice The subdevice to add to the list. - */ -void me_slist_add_subdevice_tail(struct me_slist *slist, - me_subdevice_t * subdevice); - -/** - * @brief Removes a subdevice from the tail of the list. - * - * @param slist The subdevice list. - * - * @return Pointer to the removed subdeivce.\n - * NULL in cases where the list was empty. - */ -me_subdevice_t *me_slist_del_subdevice_tail(struct me_slist *slist); - -/** - * @brief Initializes a subdevice list structure. - * - * @param lock The subdevice list structure to initialize. - * @return 0 on success. - */ -int me_slist_init(me_slist_t * slist); - -/** - * @brief Deinitializes a subdevice list structure and destructs every subdevice in it. - * - * @param slist The subdevice list structure to deinitialize. - * @return 0 on success. - */ -void me_slist_deinit(me_slist_t * slist); - -#endif -#endif --- a/drivers/staging/meilhaus/meslock.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @file meslock.c - * - * @brief Implements the subdevice lock class. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2006 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. - */ - -#include - -#include "medefines.h" -#include "meerror.h" - -#include "medebug.h" -#include "meslock.h" - -int me_slock_enter(struct me_slock *slock, struct file *filep) -{ - PDEBUG_LOCKS("executed.\n"); - - spin_lock(&slock->spin_lock); - - if ((slock->filep) != NULL && (slock->filep != filep)) { - PERROR("Subdevice is locked by another process.\n"); - spin_unlock(&slock->spin_lock); - return ME_ERRNO_LOCKED; - } - - slock->count++; - - spin_unlock(&slock->spin_lock); - - return ME_ERRNO_SUCCESS; -} - -int me_slock_exit(struct me_slock *slock, struct file *filep) -{ - PDEBUG_LOCKS("executed.\n"); - - spin_lock(&slock->spin_lock); - slock->count--; - spin_unlock(&slock->spin_lock); - - return ME_ERRNO_SUCCESS; -} - -int me_slock_lock(struct me_slock *slock, struct file *filep, int lock) -{ - PDEBUG_LOCKS("executed.\n"); - - switch (lock) { - - case ME_LOCK_RELEASE: - spin_lock(&slock->spin_lock); - - if (slock->filep == filep) - slock->filep = NULL; - - spin_unlock(&slock->spin_lock); - - break; - - case ME_LOCK_SET: - spin_lock(&slock->spin_lock); - - if (slock->count) { - spin_unlock(&slock->spin_lock); - PERROR("Subdevice is used by another process.\n"); - return ME_ERRNO_USED; - } else if (slock->filep == NULL) - slock->filep = filep; - else if (slock->filep != filep) { - spin_unlock(&slock->spin_lock); - PERROR("Subdevice is locked by another process.\n"); - return ME_ERRNO_LOCKED; - } - - spin_unlock(&slock->spin_lock); - - break; - - case ME_LOCK_CHECK: - spin_lock(&slock->spin_lock); - - if (slock->count) { - spin_unlock(&slock->spin_lock); - return ME_ERRNO_USED; - } else if ((slock->filep != NULL) && (slock->filep != filep)) { - spin_unlock(&slock->spin_lock); - return ME_ERRNO_LOCKED; - } - - spin_unlock(&slock->spin_lock); - - break; - - default: - break; - } - - return ME_ERRNO_SUCCESS; -} - -void me_slock_deinit(struct me_slock *slock) -{ - PDEBUG_LOCKS("executed.\n"); -} - -int me_slock_init(me_slock_t *slock) -{ - PDEBUG_LOCKS("executed.\n"); - - slock->filep = NULL; - slock->count = 0; - spin_lock_init(&slock->spin_lock); - - return 0; -} --- a/drivers/staging/meilhaus/meslock.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file meslock.h - * - * @brief Provides the subdevice lock class. - * @note Copyright (C) 2006 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _MESLOCK_H_ -#define _MESLOCK_H_ - -#include - -#ifdef __KERNEL__ - -/** - * @brief The subdevice lock class. - */ -typedef struct me_slock { - struct file *filep; /**< Pointer to file structure holding the subdevice. */ - int count; /**< Number of tasks which are inside the subdevice. */ - spinlock_t spin_lock; /**< Spin lock protecting the attributes from concurrent access. */ -} me_slock_t; - -/** - * @brief Tries to enter a subdevice. - * - * @param slock The subdevice lock instance. - * @param filep The file structure identifying the calling process. - * - * @return 0 on success. - */ -int me_slock_enter(struct me_slock *slock, struct file *filep); - -/** - * @brief Exits a subdevice. - * - * @param slock The subdevice lock instance. - * @param filep The file structure identifying the calling process. - * - * @return 0 on success. - */ -int me_slock_exit(struct me_slock *slock, struct file *filep); - -/** - * @brief Tries to perform a locking action on a subdevice. - * - * @param slock The subdevice lock instance. - * @param filep The file structure identifying the calling process. - * @param The action to be done. - * - * @return 0 on success. - */ -int me_slock_lock(struct me_slock *slock, struct file *filep, int lock); - -/** - * @brief Initializes a lock structure. - * - * @param slock The lock structure to initialize. - * @return 0 on success. - */ -int me_slock_init(me_slock_t * slock); - -/** - * @brief Deinitializes a lock structure. - * - * @param slock The lock structure to deinitialize. - * @return 0 on success. - */ -void me_slock_deinit(me_slock_t * slock); - -#endif -#endif --- a/drivers/staging/meilhaus/mesubdevice.c +++ /dev/null @@ -1,317 +0,0 @@ -/** - * @file mesubdevice.c - * - * @brief Subdevice base class implemention. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#include - -#include "medefines.h" -#include "meerror.h" - -#include "medebug.h" -#include "mesubdevice.h" - -static int me_subdevice_io_irq_start(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_irq_wait(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *irq_count, - int *value, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_irq_stop(struct me_subdevice *subdevice, - struct file *filep, int channel, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_reset_subdevice(struct me_subdevice *subdevice, - struct file *filep, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_single_config(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, - int trig_edge, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_single_read(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int *value, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_single_write(struct me_subdevice *subdevice, - struct file *filep, - int channel, - int value, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_config(struct me_subdevice *subdevice, - struct file *filep, - meIOStreamConfig_t *config_list, - int count, - meIOStreamTrigger_t *trigger, - int fifo_irq_threshold, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_new_values(struct me_subdevice *subdevice, - struct file *filep, - int time_out, - int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_read(struct me_subdevice *subdevice, - struct file *filep, - int read_mode, - int *values, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_start(struct me_subdevice *subdevice, - struct file *filep, - int start_mode, int time_out, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_status(struct me_subdevice *subdevice, - struct file *filep, - int wait, - int *status, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_stop(struct me_subdevice *subdevice, - struct file *filep, - int stop_mode, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_io_stream_write(struct me_subdevice *subdevice, - struct file *filep, - int write_mode, - int *values, int *count, int flags) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_lock_subdevice(me_subdevice_t *subdevice, - struct file *filep, int lock, int flags) -{ - PDEBUG("executed.\n"); - return me_slock_lock(&subdevice->lock, filep, lock); -} - -static int me_subdevice_query_number_channels(struct me_subdevice *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_number_ranges(struct me_subdevice *subdevice, - int unit, int *count) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_range_by_min_max(struct me_subdevice *subdevice, - int unit, - int *min, - int *max, - int *maxdata, int *range) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_range_info(struct me_subdevice *subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_subdevice_type(struct me_subdevice *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_subdevice_caps(struct me_subdevice *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -static int me_subdevice_query_subdevice_caps_args(struct me_subdevice - *subdevice, int cap, - int *args, int count) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_query_timer(struct me_subdevice *subdevice, - int timer, - int *base_frequency, - long long *min_ticks, long long *max_ticks) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_NOT_SUPPORTED; -} - -static int me_subdevice_config_load(struct me_subdevice *subdevice, - me_cfg_device_entry_t *config) -{ - PDEBUG("executed.\n"); - return ME_ERRNO_SUCCESS; -} - -static void me_subdevice_destructor(struct me_subdevice *subdevice) -{ - PDEBUG("executed.\n"); - me_subdevice_deinit(subdevice); - kfree(subdevice); -} - -int me_subdevice_init(me_subdevice_t *subdevice) -{ - int err; - - PDEBUG("executed.\n"); - - /* Init list head */ - INIT_LIST_HEAD(&subdevice->list); - - /* Initialize the subdevice lock instance */ - - err = me_slock_init(&subdevice->lock); - - if (err) { - PERROR("Cannot initialize subdevice lock instance.\n"); - return 1; - } - - /* Subdevice base class methods */ - subdevice->me_subdevice_io_irq_start = me_subdevice_io_irq_start; - subdevice->me_subdevice_io_irq_wait = me_subdevice_io_irq_wait; - subdevice->me_subdevice_io_irq_stop = me_subdevice_io_irq_stop; - subdevice->me_subdevice_io_reset_subdevice = - me_subdevice_io_reset_subdevice; - subdevice->me_subdevice_io_single_config = - me_subdevice_io_single_config; - subdevice->me_subdevice_io_single_read = me_subdevice_io_single_read; - subdevice->me_subdevice_io_single_write = me_subdevice_io_single_write; - subdevice->me_subdevice_io_stream_config = - me_subdevice_io_stream_config; - subdevice->me_subdevice_io_stream_new_values = - me_subdevice_io_stream_new_values; - subdevice->me_subdevice_io_stream_read = me_subdevice_io_stream_read; - subdevice->me_subdevice_io_stream_start = me_subdevice_io_stream_start; - subdevice->me_subdevice_io_stream_status = - me_subdevice_io_stream_status; - subdevice->me_subdevice_io_stream_stop = me_subdevice_io_stream_stop; - subdevice->me_subdevice_io_stream_write = me_subdevice_io_stream_write; - subdevice->me_subdevice_lock_subdevice = me_subdevice_lock_subdevice; - subdevice->me_subdevice_query_number_channels = - me_subdevice_query_number_channels; - subdevice->me_subdevice_query_number_ranges = - me_subdevice_query_number_ranges; - subdevice->me_subdevice_query_range_by_min_max = - me_subdevice_query_range_by_min_max; - subdevice->me_subdevice_query_range_info = - me_subdevice_query_range_info; - subdevice->me_subdevice_query_subdevice_type = - me_subdevice_query_subdevice_type; - subdevice->me_subdevice_query_subdevice_caps = - me_subdevice_query_subdevice_caps; - subdevice->me_subdevice_query_subdevice_caps_args = - me_subdevice_query_subdevice_caps_args; - subdevice->me_subdevice_query_timer = me_subdevice_query_timer; - subdevice->me_subdevice_config_load = me_subdevice_config_load; - subdevice->me_subdevice_destructor = me_subdevice_destructor; - - return 0; -} - -void me_subdevice_deinit(me_subdevice_t *subdevice) -{ - PDEBUG("executed.\n"); - me_subdevice_io_reset_subdevice(subdevice, NULL, - ME_IO_RESET_SUBDEVICE_NO_FLAGS); - me_slock_deinit(&subdevice->lock); -} --- a/drivers/staging/meilhaus/mesubdevice.h +++ /dev/null @@ -1,197 +0,0 @@ -/** - * @file mesubdevice.h - * - * @brief Provides the subdevice base class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -#ifndef _MESUBDEVICE_H_ -#define _MESUBDEVICE_H_ - -#include - -#include "metypes.h" -#include "meioctl.h" -#include "meslock.h" - -# include - -#ifdef __KERNEL__ - -/** - * @brief Macro used to enter a subdevice. - */ -#define ME_SUBDEVICE_ENTER \ -{ \ - int err; \ - err = me_slock_enter(&instance->base.lock, filep); \ - if(err){ \ - PERROR("Cannot enter subdevice.\n"); \ - return err; \ - } \ -} - -/** - * @brief Macro used to exit a subdevice. - */ -#define ME_SUBDEVICE_EXIT \ -{\ - int err; \ - err = me_slock_exit(&instance->base.lock, filep); \ - if(err){ \ - PERROR("Cannot exit subdevice.\n"); \ - return err; \ - } \ -} - -/** - * @brief The subdevice base class. - */ -typedef struct me_subdevice { - /* Attributes */ - struct list_head list; /**< Enables the subdevice to be added to a dynamic list. */ - me_slock_t lock; /**< Used by user application in order to lock the subdevice for exclusive usage. */ - - /* Methods */ - int (*me_subdevice_io_irq_start) (struct me_subdevice * subdevice, - struct file * filep, - int channel, - int irq_source, - int irq_edge, int irq_arg, int flags); - - int (*me_subdevice_io_irq_wait) (struct me_subdevice * subdevice, - struct file * filep, - int channel, - int *irq_count, - int *value, int time_out, int flags); - - int (*me_subdevice_io_irq_stop) (struct me_subdevice * subdevice, - struct file * filep, - int channel, int flags); - - int (*me_subdevice_io_reset_subdevice) (struct me_subdevice * subdevice, - struct file * filep, int flags); - - int (*me_subdevice_io_single_config) (struct me_subdevice * subdevice, - struct file * filep, - int channel, - int single_config, - int ref, - int trig_chan, - int trig_type, - int trig_edge, int flags); - - int (*me_subdevice_io_single_read) (struct me_subdevice * subdevice, - struct file * filep, - int channel, - int *value, - int time_out, int flags); - - int (*me_subdevice_io_single_write) (struct me_subdevice * subdevice, - struct file * filep, - int channel, - int value, - int time_out, int flags); - - int (*me_subdevice_io_stream_config) (struct me_subdevice * subdevice, - struct file * filep, - meIOStreamConfig_t * config_list, - int count, - meIOStreamTrigger_t * trigger, - int fifo_irq_threshold, - int flags); - - int (*me_subdevice_io_stream_new_values) (struct me_subdevice * - subdevice, - struct file * filep, - int time_out, int *count, - int flags); - - int (*me_subdevice_io_stream_read) (struct me_subdevice * subdevice, - struct file * filep, - int read_mode, - int *values, int *count, int flags); - - int (*me_subdevice_io_stream_start) (struct me_subdevice * subdevice, - struct file * filep, - int start_mode, - int time_out, int flags); - - int (*me_subdevice_io_stream_status) (struct me_subdevice * subdevice, - struct file * filep, - int wait, - int *status, - int *count, int flags); - - int (*me_subdevice_io_stream_stop) (struct me_subdevice * subdevice, - struct file * filep, - int stop_mode, int flags); - - int (*me_subdevice_io_stream_write) (struct me_subdevice * subdevice, - struct file * filep, - int write_mode, - int *values, - int *count, int flags); - - int (*me_subdevice_lock_subdevice) (struct me_subdevice * subdevice, - struct file * filep, - int lock, int flags); - - int (*me_subdevice_query_number_channels) (struct me_subdevice * - subdevice, int *number); - - int (*me_subdevice_query_number_ranges) (struct me_subdevice * - subdevice, int unit, - int *count); - - int (*me_subdevice_query_range_by_min_max) (struct me_subdevice * - subdevice, int unit, - int *min, int *max, - int *maxdata, int *range); - - int (*me_subdevice_query_range_info) (struct me_subdevice * subdevice, - int range, - int *unit, - int *min, int *max, int *maxdata); - - int (*me_subdevice_query_subdevice_type) (struct me_subdevice * - subdevice, int *type, - int *subtype); - - int (*me_subdevice_query_subdevice_caps) (struct me_subdevice * - subdevice, int *caps); - - int (*me_subdevice_query_subdevice_caps_args) (struct me_subdevice * - subdevice, int cap, - int *args, int count); - - int (*me_subdevice_query_timer) (struct me_subdevice * subdevice, - int timer, - int *base_frequency, - long long *min_ticks, - long long *max_ticks); - - int (*me_subdevice_config_load) (struct me_subdevice * subdevice, - me_cfg_device_entry_t * config); - - void (*me_subdevice_destructor) (struct me_subdevice * subdevice); -} me_subdevice_t; - -/** - * @brief Initializes a subdevice structure. - * - * @param subdevice The subdevice structure to initialize. - * @return 0 on success. - */ -int me_subdevice_init(me_subdevice_t * subdevice); - -/** - * @brief Deinitializes a subdevice structure. - * - * @param subdevice The subdevice structure to initialize. - */ -void me_subdevice_deinit(me_subdevice_t * subdevice); - -#endif -#endif --- a/drivers/staging/meilhaus/metempl_device.c +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @file metempl_device.c - * - * @brief template device class implementation. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -#ifndef MODULE -# define MODULE -#endif - -#include - -#include -#include - -#include -#include "meerror.h" -#include "mecommon.h" -#include "meinternal.h" - -#include "medebug.h" -#include "medevice.h" -#include "metempl_device.h" -#include "mesubdevice.h" -#include "metempl_sub.h" - -me_device_t *metempl_pci_constructor(struct pci_dev *pci_device) -{ - metempl_device_t *metempl_device; - me_subdevice_t *subdevice; - unsigned int version_idx; - int err; - int i; - - PDEBUG("executed.\n"); - - // Allocate structure for device instance. - metempl_device = kmalloc(sizeof(metempl_device_t), GFP_KERNEL); - - if (!metempl_device) { - PERROR("Cannot get memory for device instance.\n"); - return NULL; - } - - memset(metempl_device, 0, sizeof(metempl_device_t)); - - // Initialize base class structure. - err = me_device_pci_init((me_device_t *) metempl_device, pci_device); - - if (err) { - kfree(metempl_device); - PERROR("Cannot initialize device base class.\n"); - return NULL; - } - - /* Get the index in the device version information table. */ - version_idx = - metempl_versions_get_device_index(metempl_device->base.info.pci. - device_id); - - // Initialize spin lock . - spin_lock_init(&metempl_device->ctrl_reg_lock); - - // Create subdevice instances. - for (i = 0; i < metempl_versions[version_idx].subdevices; i++) { - subdevice = - (me_subdevice_t *) metempl_sub_constructor(metempl_device-> - base.info.pci. - reg_bases[2], i, - &metempl_device-> - ctrl_reg_lock); - - if (!subdevice) { - me_device_deinit((me_device_t *) metempl_device); - kfree(metempl_device); - PERROR("Cannot get memory for subdevice.\n"); - return NULL; - } - - me_slist_add_subdevice_tail(&metempl_device->base.slist, - subdevice); - } - - /* Overwrite base class methods if applicable. */ - - return (me_device_t *) metempl_device; -} -EXPORT_SYMBOL(metempl_pci_constructor); - -// Init and exit of module. - -static int __init metempl_init(void) -{ - PDEBUG("executed.\n."); - return 0; -} - -static void __exit metempl_exit(void) -{ - PDEBUG("executed.\n."); -} - -module_init(metempl_init); - -module_exit(metempl_exit); - -// Administrative stuff for modinfo. -MODULE_AUTHOR("Guenter Gebhardt "); -MODULE_DESCRIPTION("Device Driver Module for Template Device"); -MODULE_SUPPORTED_DEVICE("Meilhaus Template Devices"); -MODULE_LICENSE("GPL"); --- a/drivers/staging/meilhaus/metempl_device.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @file metempl_device.h - * - * @brief template device class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _METEMPL_DEVICE_H -#define _METEMPL_DEVICE_H - -#include -#include - -#include "medevice.h" - -#ifdef __KERNEL__ - -/** - * @brief Structure holding template device capabilities. - */ -typedef struct metempl_version { - uint16_t device_id; - unsigned int subdevices; -} metempl_version_t; - -/** - * @brief Device capabilities. - */ -static metempl_version_t metempl_versions[] = { - {0xDEAD, 1}, - {0}, -}; - -#define METEMPL_DEVICE_VERSIONS (ARRAY_SIZE(metempl_versions) - 1) /**< Returns the number of entries in #metempl_versions. */ - -/** - * @brief Returns the index of the device entry in #metempl_versions. - * - * @param device_id The PCI device id of the device to query. - * @return The index of the device in #metempl_versions. - */ -static inline unsigned int metempl_versions_get_device_index(uint16_t device_id) -{ - unsigned int i; - for (i = 0; i < METEMPL_DEVICE_VERSIONS; i++) - if (metempl_versions[i].device_id == device_id) - break; - return i; -} - -/** - * @brief The template device class structure. - */ -typedef struct metempl_device { - me_device_t base; /**< The Meilhaus device base class. */ - - /* Child class attributes. */ - spinlock_t ctrl_reg_lock; -} metempl_device_t; - -/** - * @brief The template device class constructor. - * - * @param pci_device The pci device structure given by the PCI subsystem. - * - * @return On succes a new template device instance. \n - * NULL on error. - */ -me_device_t *metempl_pci_constructor(struct pci_dev *pci_device) - __attribute__ ((weak)); - -#endif -#endif --- a/drivers/staging/meilhaus/metempl_sub.c +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @file metempl_sub.c - * - * @brief Subdevice instance. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef __KERNEL__ -# define __KERNEL__ -#endif - -/* - * Includes - */ -#include - -#include -#include -#include -#include - -#include "medefines.h" -#include "meinternal.h" -#include "meerror.h" - -#include "medebug.h" -#include "metempl_sub_reg.h" -#include "metempl_sub.h" - -/* - * Defines - */ - -/* - * Functions - */ - -static void metempl_sub_destructor(struct me_subdevice *subdevice) -{ - metempl_sub_subdevice_t *instance; - - PDEBUG("executed.\n"); - instance = (metempl_sub_subdevice_t *) subdevice; - - /* Until there this was the things the default constructor does. - If you do not have any additional things to do you can wipe it out. */ - - me_subdevice_deinit(&instance->base); - kfree(instance); -} - -static int metempl_sub_query_number_channels(me_subdevice_t *subdevice, - int *number) -{ - PDEBUG("executed.\n"); - *number = 0; - return ME_ERRNO_SUCCESS; -} - -static int metempl_sub_query_subdevice_type(me_subdevice_t *subdevice, - int *type, int *subtype) -{ - PDEBUG("executed.\n"); - *type = 0; - *subtype = 0; - return ME_ERRNO_SUCCESS; -} - -static int metempl_sub_query_subdevice_caps(me_subdevice_t *subdevice, - int *caps) -{ - PDEBUG("executed.\n"); - *caps = 0; - return ME_ERRNO_SUCCESS; -} - -metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base, - unsigned int sub_idx, - spinlock_t *ctrl_reg_lock) -{ - metempl_sub_subdevice_t *subdevice; - int err; - - PDEBUG("executed.\n"); - - /* Allocate memory for subdevice instance */ - subdevice = kmalloc(sizeof(metempl_sub_subdevice_t), GFP_KERNEL); - - if (!subdevice) { - PERROR("Cannot get memory for subdevice instance.\n"); - return NULL; - } - - memset(subdevice, 0, sizeof(metempl_sub_subdevice_t)); - - /* Check if subdevice index is out of range */ - - if (sub_idx >= 2) { - PERROR("Template subdevice index is out of range.\n"); - kfree(subdevice); - return NULL; - } - - /* Initialize subdevice base class */ - err = me_subdevice_init(&subdevice->base); - - if (err) { - PERROR("Cannot initialize subdevice base class instance.\n"); - kfree(subdevice); - return NULL; - } - // Initialize spin locks. - spin_lock_init(&subdevice->subdevice_lock); - - subdevice->ctrl_reg_lock = ctrl_reg_lock; - - /* Save the subdevice index */ - subdevice->sub_idx = sub_idx; - - /* Override base class methods. */ - subdevice->base.me_subdevice_destructor = metempl_sub_destructor; - subdevice->base.me_subdevice_query_number_channels = - metempl_sub_query_number_channels; - subdevice->base.me_subdevice_query_subdevice_type = - metempl_sub_query_subdevice_type; - subdevice->base.me_subdevice_query_subdevice_caps = - metempl_sub_query_subdevice_caps; - - return subdevice; -} --- a/drivers/staging/meilhaus/metempl_sub.h +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file metempl_sub.h - * - * @brief Meilhaus subdevice class. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _METEMPL_SUB_H_ -#define _METEMPL_SUB_H_ - -#include "mesubdevice.h" - -#ifdef __KERNEL__ - -/** - * @brief The subdevice class. - */ -typedef struct metempl_sub_subdevice { - /* Inheritance */ - me_subdevice_t base; /**< The subdevice base class. */ - - /* Attributes */ - spinlock_t subdevice_lock; /**< Spin lock to protect the subdevice from concurrent access. */ - spinlock_t *ctrl_reg_lock; /**< Spin lock to protect #ctrl_reg from concurrent access. */ - int sub_idx; /**< The index of the subdevice on the device. */ - - unsigned long ctrl_reg; /**< Register to configure the modes. */ -} metempl_sub_subdevice_t; - -/** - * @brief The constructor to generate a subdevice instance. - * - * @param reg_base The register base address of the device as returned by the PCI BIOS. - * @param sub_idx The index of the subdevice on the device. - * @param ctrl_reg_lock Pointer to spin lock protecting the control register from concurrent access. - * - * @return Pointer to new instance on success.\n - * NULL on error. - */ -metempl_sub_subdevice_t *metempl_sub_constructor(uint32_t reg_base, - unsigned int sub_idx, - spinlock_t * ctrl_reg_lock); - -#endif -#endif --- a/drivers/staging/meilhaus/metempl_sub_reg.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @file metempl_sub_reg.h - * - * @brief Subdevice register definitions. - * @note Copyright (C) 2007 Meilhaus Electronic GmbH (support@meilhaus.de) - * @author Guenter Gebhardt - */ - -/* - * Copyright (C) 2007 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. - */ - -#ifndef _METEMPL_SUB_REG_H_ -#define _METEMPL_SUB_REG_H_ - -#ifdef __KERNEL__ - -#define METEMPL_PORT_MODE 0x0010 /**< Configuration register. */ - -#endif -#endif --- a/drivers/staging/meilhaus/metypes.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2005 Meilhaus Electronic GmbH (support@meilhaus.de) - * - * Source File : metypes.h - * Author : GG (Guenter Gebhardt) - */ - -#ifndef _METYPES_H_ -#define _METYPES_H_ - - -typedef int (*meErrorCB_t)(char *pcFunctionName, int iErrorCode); - -typedef int (*meIOStreamCB_t)( - int iDevice, - int iSubdevice, - int iCount, - void *pvContext, - int iErrorCode); - -typedef int (*meIOIrqCB_t)( - int iDevice, - int iSubdevice, - int iChannel, - int iIrqCount, - int iValue, - void *pvContext, - int iErrorCode); - - -typedef struct meIOSingle { - int iDevice; - int iSubdevice; - int iChannel; - int iDir; - int iValue; - int iTimeOut; - int iFlags; - int iErrno; -} meIOSingle_t; - - -typedef struct meIOStreamConfig { - int iChannel; - int iStreamConfig; - int iRef; - int iFlags; -} meIOStreamConfig_t; - - -typedef struct meIOStreamTrigger { - int iAcqStartTrigType; - int iAcqStartTrigEdge; - int iAcqStartTrigChan; - int iAcqStartTicksLow; - int iAcqStartTicksHigh; - int iAcqStartArgs[10]; - int iScanStartTrigType; - int iScanStartTicksLow; - int iScanStartTicksHigh; - int iScanStartArgs[10]; - int iConvStartTrigType; - int iConvStartTicksLow; - int iConvStartTicksHigh; - int iConvStartArgs[10]; - int iScanStopTrigType; - int iScanStopCount; - int iScanStopArgs[10]; - int iAcqStopTrigType; - int iAcqStopCount; - int iAcqStopArgs[10]; - int iFlags; -} meIOStreamTrigger_t; - - -typedef struct meIOStreamStart { - int iDevice; - int iSubdevice; - int iStartMode; - int iTimeOut; - int iFlags; - int iErrno; -} meIOStreamStart_t; - - -typedef struct meIOStreamStop { - int iDevice; - int iSubdevice; - int iStopMode; - int iFlags; - int iErrno; -} meIOStreamStop_t; - - -#endif --- a/drivers/staging/meilhaus/TODO +++ /dev/null @@ -1,10 +0,0 @@ -TODO: - - checkpatch.pl cleanups - - sparse issues - - Lindent - - audit userspace interface - - handle firmware properly - - possible comedi merge - -Please send cleanup patches to Greg Kroah-Hartman -and CC: David Kiliani and Meilhaus Support